Makefile

Makefile

1、編譯參數

-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、Makefile語法

2.一、編譯規則

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

2.二、通配符

https://www.cnblogs.com/warren-wong/p/3979270.html

2.二、特殊符號

$@:目標的名字
$^:構造所需文件列表全部全部文件的名字
$<:構造所需文件列表的第一個文件的名字
$?:構造所需文件列表中更新過的文件
 
//$@:就是test1.o  $<:就是test1.c
test1.o:test1.c
   gcc -o $@ $<
   
// $^:就是test1.c head.c
test1.o:test1.c head.c
   gcc -o $@ $^

%與*通配符的關係:

 轉義符的使用:

2.三、邏輯判斷

https://blog.csdn.net/liuzhuchen/article/details/51776820

if then else then

ifep

2.四、經常使用函數

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}))

3、Makefile例程分析

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的查找規則與執行熟悉。

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
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息