-o並非編譯參數,而是gcc內部的重命名參數。真正參與編譯的參數有-c -s -e等。html
gcc -o test main.c 若不制定相似於-c -s -e這樣的編譯參數,直接使用-o參數,gcc會自動默認執行-c -s -e參數,並根據-o參數指定的名稱生成可執行文件。
https://www.cnblogs.com/zhangpengshou/p/3587751.htmllinux
2.1.一、變量定義與變量操做shell
https://blog.csdn.net/naughfy/article/details/80150312tcp
obj = test.c
obj := test.c
二者之間的區別?函數
變量追加、變量替換 makefile 文件變量賦值有如下幾種 = // 最通用的用法,用在遞歸展開方式較多 := //變量必須以前就定義了,用在直接展開方式較多 ?= 若是該變量沒有賦值,則對該變量賦值 += 給變量追加賦值 @echo $(OPT) // 變量使用 make OPT=add //make 傳遞參數
2.1.一、變量參數傳遞
https://blog.csdn.net/darennet/article/details/9003010學習
//宏定義參數傳遞,用於源代碼中宏開關。 CFLAGS += -D POSGP730 -D*表示:#define * 如:-DPOSGP730等價於#define POSGP730 -Wall 表示打開全部編譯告警信息 -O2表示優化級別
在makefile中能夠預先使用一個未定義的變量, 這個變量能夠在make執行時傳遞給它
好比makefile中有這麼一行
include $(M)/$(COMPAT_CONFIG)
這個M能夠經過make傳遞過來
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
其中的M就是$(PWD)
甚至能夠進行更復雜的操做, 就像在Makefile中同樣
make CFLAG=-DDEBUG優化
2.1.一、編譯查找規則
一、入口: makefile認爲"第一個目標做爲入口。 重點:第一個、目標。
二、依賴性查找
三、若能找到,則執行對應的操做。(顯示)
四、若找不到,makefile強大的自動推倒能力,執行隱士的相關操做。(隱士)ui
//顯示 all:test1.o test2.o gcc -o $@ $^ test1.o:test1.c gcc -o test1.o test1.c test2.o:test2.c gcc -o test2.o test2.c //隱士 all:test1.o test2.o gcc -o $@ $^ test1.o: //自動推倒依賴test1.c 並編譯cc -c -o test1.0 test1.c test2.o: //隱士 all:test1.o test2.o gcc -o $@ $^ //自動推倒目標與依賴,並編譯cc -c -o test1.0 test1.c
2.1.二、可執行文件生成規則
makefile最終編譯生成的可執行程序與僞目標沒有任何關係,僅僅取決於arm-linux-gcc -o 以後所定義的名稱。 (通常也採用@<)使其名字與僞目標相同。.net
2.1.二、新舊比對編譯
一、若是目標不存在,執行命令。(包括依賴和命令)
二、若是目標存在,依賴文件有更新(依賴文件是遞歸的,找依賴的依賴,若是有更新,就更新)。執行命令。
三、若是目標存在,且依賴沒有更新,(遞歸的,包括依賴的依賴。。。),不更新,不執行命令。code
https://www.cnblogs.com/warren-wong/p/3979270.html
$@:目標的名字 $^:構造所需文件列表全部全部文件的名字 $<:構造所需文件列表的第一個文件的名字 $?:構造所需文件列表中更新過的文件 //$@:就是test1.o $<:就是test1.c test1.o:test1.c gcc -o $@ $< // $^:就是test1.c head.c test1.o:test1.c head.c gcc -o $@ $^
%與*通配符的關係:
轉義符的使用:
https://blog.csdn.net/liuzhuchen/article/details/51776820
if then else then
ifep
wildcard擴展通配符
Makefile規則中,通配符會被自動展開。但在變量
的定義和函數引用
時,通配符將失效。這種狀況下若是須要通配符有效,就須要使用函數「wildcard」,它的用法是:$(wildcard PATTERN...) 。在Makefile中,它被展開爲已經存在的、使用空格分開的、匹配此模式的全部文件列表。若是不存在任何符合此模式的文件,函數會忽略模式字符並返回空。
//使用說明 obj = $(wildcard *.c)
//變量定義與函數引用通配符失效,舉例說明 //好比函數爲swapfun,使用通配符的方式去引用函數 obj = %.c $(*fun argument)
notdir去除路徑
去除全部的目錄信息,SRC2裏的文件名列表將只有文件名,去除掉已xx.c命名的文件夾信息。
SRC = $(wildcard *.c) SRC2 = $(notdir wildcard)
patsubst 替換通配符
patsubst( patten substitude, 匹配替換的縮寫)函數。
它須要3個參數:第一個是一個須要匹配的式樣,第二個表示用什麼來替換它,第三個是一個須要被處理的由空格分隔的字列。例如,處理那個通過上面定義後的變量,
OBJS = $(patsubst %.c,%.o,$(SRC2 ))
這行將處理全部在 SRC2 列箇中的字(一列文件名),若是它的 結尾是 '.c' ,就用'.o' 把 '.c' 取代。
//使用舉例 SOURCES = $(wildcard *.c) FILES = $(notdir$(SOURCES)) OBJS = $(patsubst %.c, %.o, $(FILES) ) SRC = $(wildcard *.c) OBJ = $(patsubst %.c,%.o,$(notdir ${SRC}))
TARGET = arm-none-linux-gnueabi CC = $(TARGET)-gcc AR = $(TARGET)-ar LD = $(TARGET)-ld STRIP = $(TARGET)-strip CFLAGS = -Wall -I../../include -I../../../include -fPIC LDFLAGS = -L../../lib -ldrivercomm -lmodbus -lmodbustcp -lprintmanage -L ../../lib.arm -lxmlrpcsys ifeq (1,${release}) CFLAGS += -Os else CFLAGS += -g -DDEBUG_PRINTF endif NAME = CL_DL_JG_YJ_BMU-H1 PROGRAM_OUTPUT = $(NAME).so PAC_OUTPUT = $(NAME).pac PROGRAM_OBJS = Driver.o TEST_OUTPUT = test TEST_OBJS = Test.o all: program test program: version.h $(PROGRAM_OBJS) $(CC) -shared $(PROGRAM_OBJS) $(LDFLAGS) -o $(PROGRAM_OUTPUT) ../../pack/pack $(NAME) test: version.h $(TEST_OBJS) $(CC) $(TEST_OBJS) -o $(TEST_OUTPUT) $(LDFLAGS) -ldl newversion: @if [ ! -f .version ]; then \ echo 1 > .version; \ else \ expr 0`cat .version` + 1 > .version; \ fi compile.h: newversion @echo \#define SOFTWARE_COMPILE_TIME \"`date +%H:%M:%S`\" >> .ver @echo \#define SOFTWARE_COMPILE_DATE \"`date +%Y/%m/%d`\" >> .ver @echo \#define SOFTWARE_COMPILE_BY \"`logname`\" >> .ver @echo \#define SOFTWARE_COMPILE_HOST \"`hostname`\" >> .ver @echo \#define SOFTWARE_COMPILER \"`$(CC) -v 2>&1 | tail -1`\" >> .ver @mv -f .ver $@ version.h: compile.h @echo \#define SOFTWARE_BUILD_VERSION `cat .version` >> .ver @mv -f .ver $@ .PHONY: clean clean: @rm -f *.o *.d version.h compile.h @rm -f $(PROGRAM_OUTPUT) $(TEST_OUTPUT) $(PAC_OUTPUT) %.o: %.c $(CC) $(CFLAGS) -c -o $@ $<
以上述makefile爲例,分析makefile的查找規則與執行熟悉。
https://blog.csdn.net/skywalkzf/article/details/6926395
makefile學習筆記: https://www.cnblogs.com/wang_yb/p/3990952.html
strip:
函數名稱:去空格函數—strip。
函數功能:去掉字串開頭和結尾的空字符, 若字串中間部分也包含空格,則會多個連續空字符合併爲一個空字符。
示例:
STR = a b c
LOSTR = $(strip $(STR))
結果是「a b c」。
makefeil:fileter函數 foreach函數
https://www.cnblogs.com/lengbingshy/p/3936116.html
https://www.cnblogs.com/yuguangyuan/p/10929967.html
https://blog.csdn.net/zhoudengqing/article/details/41777957
https://www.cnblogs.com/GyForever1004/category/1155268.html
makefiel中使用shell的語法進行判斷
在Makefile中執行shell命令,一行建立一個進程來執行。這也是爲何不少Makefile中有不少行的末尾都是「; 」,以此來保證代碼是一行而不是多行,這樣Makefile能夠在一個進程中執行
http://ju.outofmemory.cn/entry/322934
# 適用與.h與.c處於同一文件的工程 CC = gcc CFLAGS = -Wall LIB = -lpthread -levent -lssl -ldl -lcrypto -levent_openssl #去除編譯連接的文件 CLIENT_IGNORE_SOURCE := https-server.c SERVER_IGNORE_SOURCE := https-client.c #分別獲取須要連接的文件 CLIENT_LOCAL_SOURCE = $(filter-out $(CLIENT_IGNORE_SOURCE),$(wildcard *.c)) SERVER_LOCAL_SOURCE = $(filter-out $(SERVER_IGNORE_SOURCE),$(wildcard *.c)) CLIENT_LOCAL_OBJ = $(patsubst %.c,%.o,$(notdir ${CLIENT_LOCAL_SOURCE})) SERVER_LOCAL_OBJ = $(patsubst %.c,%.o,$(notdir ${SERVER_LOCAL_SOURCE})) all: @echo "Wrong build option, please run 'make client' or "make server" to build."; @exit 13; client:${CLIENT_LOCAL_OBJ} $(CC) $(CLIENT_LOCAL_OBJ) -o $@ $(LIB) server:${SERVER_LOCAL_OBJ} $(CC) $(SERVER_LOCAL_OBJ) -o $@ $(LIB) %.o:%.c $(CC) $(CFLAGS) -c $< -o $@ clean: rm *.o client server