Linux Makefile由淺入深剖析
經(jīng)過長時間學(xué)習(xí)linux Makefile,于是和大家分享一下,看完本文你肯定有不少收獲,希望本文能教會你更多東西。
假設(shè)我們有一個程序由5個文件組成,源代碼如下:
/*main.c*/
#include "mytool1.h"
#include "mytool2.h"
int main()
{
mytool1_print("hello mytool1!");
mytool2_print("hello mytool2!");
return 0;
}
/*mytool1.c*/
#include "mytool1.h"
#include
void mytool1_print(char *print_str)
{
printf("This is mytool1 print : %s ", print_str);
}
/*mytool1.h*/
#ifndef _MYTOOL_1_H
#define _MYTOOL_1_H
void mytool1_print(char *print_str);
#endif
/*mytool2.c*/
#include "mytool2.h"
#include
void mytool2_print(char *print_str)
{
printf("This is mytool2 print : %s ", print_str);
}
/*mytool2.h*/
#ifndef _MYTOOL_2_H
#define _MYTOOL_2_H
void mytool2_print(char *print_str);
#endif
首先了解一下make和linux Makefile。GNU make是一個工程管理器,它可以管理較多的文件。我所使用的RedHat 9.0的make版本為GNU Make version 3.79.1。使用make的***好處就是實(shí)現(xiàn)了“自動化編譯”。如果有一個上百個文件的代碼構(gòu)成的項(xiàng)目,其中一個或者幾個文件進(jìn)行了修改,make就能夠自動識別更新了的文件代碼,不需要輸入冗長的命令行就可以完成***的編譯工作。make執(zhí)行時,自動尋找Makefile(makefile)文件,然后執(zhí)行編譯工作。所以我們需要編寫Makefile文件,這樣可以提高實(shí)際項(xiàng)目的工作效率。
在一個linux Makefile中通常包含下面內(nèi)容:
1、需要由make工具創(chuàng)建的目標(biāo)體(target),通常是目標(biāo)文件或可執(zhí)行文件。
2、要創(chuàng)建的目標(biāo)體所依賴的文件(dependency_file)。
3、創(chuàng)建每個目標(biāo)體時需要運(yùn)行的命令(command)。
格式如下:
target:dependency_files
target:規(guī)則的目標(biāo)。通常是程序中間或者***需要生成的文件名,可以是.o文件、也可以是***的可執(zhí)行程序的文件名。另外,目標(biāo)也可以是一個make執(zhí)行的動作的名稱,如目標(biāo)“clean”,這樣的目標(biāo)稱為“偽目標(biāo)”。dependency_files:規(guī)則的依賴。生成規(guī)則目標(biāo)所需要的文件名列表。通常一個目標(biāo)依賴于一個或者多個文件。
command:規(guī)則的命令行。是make程序所有執(zhí)行的動作(任意的shell命令或者可在shell下執(zhí)行的程序)一個規(guī)則可以有多個命令行,每一條命令占一行。注意:每一個命令行必須以[Tab]字符開始,[Tab]字符告訴make此行是一個命令行。make按照命令完成相應(yīng)的動作。這也是書寫Makefile中容易產(chǎn)生,而且比較隱蔽的錯誤。命令就是在任何一個目標(biāo)的依賴文件發(fā)生變化后重建目標(biāo)的動作描述。一個目標(biāo)可以沒有依賴而只有動作(指定的命令)。比如Makefile中的目標(biāo)“clean”,此目標(biāo)沒有依賴,只有命令。它所指定的命令用來刪除make過程產(chǎn)生的中間文件(清理工作)。
在Makefile中“規(guī)則”就是描述在什么情況下、如何重建規(guī)則的目標(biāo)文件,通常規(guī)則中包括了目標(biāo)的依賴關(guān)系(目標(biāo)的依賴文件)和重建目標(biāo)的命令。make執(zhí)行重建目標(biāo)的命令,來創(chuàng)建或者重建規(guī)則的目標(biāo)(此目標(biāo)文件也可以是觸發(fā)這個規(guī)則的上一個規(guī)則中的依賴文件)。規(guī)則包含了目標(biāo)和依賴的關(guān)系以及更新目標(biāo)所要求的命令。
Makefile中可以包含除規(guī)則以外的部分。一個最簡單的Makefile可能只包含規(guī)則描述。規(guī)則在有些Makefile中可能看起來非常復(fù)雜,但是無論規(guī)則的書寫是多么的復(fù)雜,它都符合規(guī)則的基本格式。
下面就可以寫出***個Makefile了。
main:main.o mytool1.o mytool2.o
gcc -o main main.o mytool1.o mytool2.o
main.o:main.c mytool1.h mytool2.h
gcc -c main.c
mytool1.o:mytool1.c mytool1.h
gcc -c mytool1.c
mytool2.o:mytool2.c mytool2.h
gcc -c mytool2.c
clean:
rm -f *.o main
在shell提示符下輸入make,執(zhí)行顯示:
gcc -c main.c
gcc -c mytool1.c
gcc -c mytool2.c
gcc -o main main.o mytool1.o mytool2.o
執(zhí)行結(jié)果如下:
[armlinux@lqm makefile-easy]$ ./main
This is mytool1 print : hello mytool1!
This is mytool2 print : hello mytool2!
這只是最為初級的Makefile,現(xiàn)在來對這個Makefile進(jìn)行改進(jìn)。
改進(jìn)一:使用變量
一般在書寫Makefile時,各部分變量引用的格式如下:
1. make變量(Mak1. make變量(Makefile中定義的或者是make的環(huán)境變量)的引用使用“$(VAR)”格式,無論“VAR”是單字符變量名還是多字符變量名。
2. 出現(xiàn)在規(guī)則命令行中shell變量(一般為執(zhí)行命令過程中的臨時變量,它不屬于Makefile變量,而是一個shell變量)引用使用shell的“$tmp”格式。
3. 對出現(xiàn)在命令行中的make變量同樣使用“$(CMDVAR)” 格式來引用。
OBJ=main.o mytool1.o mytool2.o
make:$(OBJ)
gcc -o main $(OBJ)
main.o:main.c mytool1.h mytool2.h
gcc -c main.c
mytool1.o:mytool1.c mytool1.h
gcc -c mytool1.c
mytool2.o:mytool2.c mytool2.h
gcc -c mytool2.c
clean:
rm -f main $(OBJ)
改進(jìn)二:使用自動推導(dǎo)
讓make自動推導(dǎo),只要make看到一個.o文件,它就會自動的把對應(yīng)的.c文件加到依賴文件中,并且gcc -c .c也會被推導(dǎo)出來,所以Makefile就簡化了。
CC = gcc
OBJ = main.o mytool1.o mytool2.o
make: $(OBJ)
$(CC) -o main $(OBJ)
main.o: mytool1.h mytool2.h
mytool1.o: mytool1.h
mytool2.o: mytool2.h
.PHONY: clean
clean:
rm -f main $(OBJ)
改進(jìn)三:自動變量($^ $< $@)的應(yīng)用
Makefile 有三個非常有用的變量,分別是$@、$^、$<。代表的意義分別是:
$@--目標(biāo)文件,
$^--所有的依賴文件,
$<--***個依賴文件。
CC = gcc
OBJ = main.o mytool1.o mytool2.o
main: $(OBJ)
$(CC) -o $@ $^
main.o: main.c mytool1.h mytool2.h
$(CC) -c $<
mytool1.o: mytool1.c mytool1.h
$(CC) -c $<
mytool2.o: mytool2.c mytool2.h
$(CC) -c $<
.PHONY: clean
clean:
rm -f main $(OBJ)
這些是最為初級的知識,現(xiàn)在至少可以減少編譯時的工作量。細(xì)節(jié)方面的東西還需要在以后的工作和學(xué)習(xí)中不斷的總結(jié),不斷的深化理解??梢?參考GNU Make手冊,這里講解的比較全面。
【編輯推薦】