通用makefile
文章目錄
- 1 最基本的makefile
- 1.1 簡單粗暴的makefile
- 1.2 稍微提高效率的makefile
- 1.3 更加精煉的makefile
- 1.4 需要手工添加頭文件規則的makefile
- 1.5 支持自動檢測頭文件的makefile
- 1.6 支持自動獲取目標文件的makefile
- 2 通用makefile
- 2.1 makefile
- 2.2 通用makefile的使用說明
- 2.3 通用makefile的設計思想
- 2.4 通用makefile原理分析
1 最基本的makefile
有main.c、sub.c、sub.h三個文件,文件內容如下:
main.c:
sub.c:
#include <stdio.h> #include "sub.h"void sub_fun(void) {printf("Sub fun, A= %d!\n", A); }sub.h:
#define A 1 void sub_fun(void);1.1 簡單粗暴的makefile
test : main.c sub.c sub.hgcc -o test main.c sub.c簡單粗暴,效率低。
1.2 稍微提高效率的makefile
test : main.o sub.ogcc -o test main.o sub.omain.o : main.cgcc -c -o main.o main.csub.o : sub.cgcc -c -o sub.o sub.c clean:rm *.o test -f效率高,相似規則太多太啰嗦,不支持檢測頭文件。
1.3 更加精煉的makefile
test : main.o sub.ogcc -o test main.o sub.o%.o : %.cgcc -c -o $@ $<clean:rm *.o test -f效率高,精煉,不支持檢測頭文件。
1.4 需要手工添加頭文件規則的makefile
est : main.o sub.ogcc -o test main.o sub.o%.o : %.cgcc -c -o $@ $<sub.o : sub.hclean:rm *.o test -f效率高,精煉,支持檢測頭文件(但是需要手工添加頭文件規則)。
注意: 對于只有目標和依賴而沒有命令的規則會將其依賴和有命令的規則進行合并。
1.5 支持自動檢測頭文件的makefile
objs := main.o sub.otest : $(objs)gcc -o test $^# 需要判斷是否存在依賴文件 # .main.o.d .sub.o.d dep_files := $(foreach f, $(objs), .$(f).d) dep_files := $(wildcard $(dep_files))# 把依賴文件包含進來 ifneq ($(dep_files),)include $(dep_files) endif%.o : %.cgcc -Wp,-MD,.$@.d -c -o $@ $<clean:rm *.o test -fdistclean:rm $(dep_files) *.o test -f效率高,精煉,支持自動檢測頭文件,但是目標文件需要手動指定。
1.6 支持自動獲取目標文件的makefile
src := $(wildcard *.c) objs := $(patsubst %.c, %.o, $(src))test : $(objs)gcc -o test $^# 需要判斷是否存在依賴文件 # .main.o.d .sub.o.d dep_files := $(foreach f, $(objs), .$(f).d) dep_files := $(wildcard $(dep_files))# 把依賴文件包含進來 ifneq ($(dep_files),)include $(dep_files) endif%.o : %.cgcc -Wp,-MD,.$@.d -c -o $@ $<clean:rm *.o test -fdistclean:rm $(dep_files) *.o test -f2 通用makefile
此處只關注文件目錄,不關注文件的具體內容,測試使用的文件目錄如下:
2.1 makefile
頂層目錄的makefile:
CROSS_COMPILE = AS = $(CROSS_COMPILE)as LD = $(CROSS_COMPILE)ld CC = $(CROSS_COMPILE)gcc CPP = $(CC) -E AR = $(CROSS_COMPILE)ar NM = $(CROSS_COMPILE)nmSTRIP = $(CROSS_COMPILE)strip OBJCOPY = $(CROSS_COMPILE)objcopy OBJDUMP = $(CROSS_COMPILE)objdumpexport AS LD CC CPP AR NM export STRIP OBJCOPY OBJDUMPCFLAGS := -Wall -O2 -g CFLAGS += -I $(shell pwd)/includeLDFLAGS := export CFLAGS LDFLAGSTOPDIR := $(shell pwd) export TOPDIRTARGET := mainobj-y += main.o obj-y += sub.o obj-y += a/all : start_recursive_build $(TARGET)@echo $(TARGET) has been built!start_recursive_build:make -C ./ -f $(TOPDIR)/Makefile.build$(TARGET) : built-in.o$(CC) $(LDFLAGS) -o $(TARGET) built-in.oclean:rm -f $(shell find -name "*.o")rm -f $(TARGET)distclean:rm -f $(shell find -name "*.o")rm -f $(shell find -name "*.d")rm -f $(TARGET)頂層目錄的makefile.build:
PHONY := __build __build:obj-y := subdir-y := EXTRA_CFLAGS :=include Makefile# obj-y := a.o b.o c/ d/ # $(filter %/, $(obj-y)) : c/ d/ # __subdir-y : c d # subdir-y : c d __subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y))) subdir-y += $(__subdir-y)# c/built-in.o d/built-in.o subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)# a.o b.o cur_objs := $(filter-out %/, $(obj-y)) dep_files := $(foreach f,$(cur_objs),.$(f).d) dep_files := $(wildcard $(dep_files))ifneq ($(dep_files),)include $(dep_files) endifPHONY += $(subdir-y)__build : $(subdir-y) built-in.o$(subdir-y):make -C $@ -f $(TOPDIR)/Makefile.buildbuilt-in.o : $(cur_objs) $(subdir_objs)$(LD) -r -o $@ $^dep_file = .$@.d%.o : %.c$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -Wp,-MD,$(dep_file) -c -o $@ $<.PHONY : $(PHONY)目錄a下的makefile:
EXTRA_CFLAGS := -D DEBUG CFLAGS_sub3.o := -D DEBUG_SUB3obj-y += sub2.o obj-y += sub3.o2.2 通用makefile的使用說明
本程序的Makefile分為3類:
一、各級子目錄的Makefile:
它最簡單,形式如下:
EXTRA_CFLAGS := CFLAGS_file.o := obj-y += file.o obj-y += subdir/其中:
- “obj-y += file.o” ,表示把當前目錄下的file.c編進程序里。
- “obj-y += subdir/” ,表示要進入subdir這個子目錄下去尋找文件來編進程序里,是哪些文件由subdir目錄下的Makefile決定。
- “EXTRA_CFLAGS”, 它給當前目錄下的所有文件(不含其下的子目錄)設置額外的編譯選項, 可以不設置。
- “CFLAGS_xxx.o”, 它給當前目錄下的xxx.c設置它自己的編譯選項, 可以不設置。
注意:
二、頂層目錄的Makefile:
它除了定義obj-y來指定根目錄下要編進程序去的文件、子目錄外,還定義工具鏈前綴CROSS_COMPILE,定義編譯參數CFLAGS,定義鏈接參數LDFLAGS,這些參數就是文件中用export導出的各變量。
三、頂層目錄的Makefile.build:
這是最復雜的部分,它的功能就是把某個目錄及它的所有子目錄中、需要編進程序去的文件都編譯出來,打包為built-in.o。
四、怎么使用這套Makefile:
把頂層Makefile, Makefile.build放入程序的頂層目錄,在各自子目錄創建一個空白的Makefile。
確定編譯哪些源文件:
修改頂層目錄和各自子目錄Makefile的obj-y :
obj-y += xxx.o
obj-y += yyy/
這表示要編譯當前目錄下的xxx.c, 要編譯當前目錄下的yyy子目錄
確定編譯選項、鏈接選項:
修改頂層目錄Makefile的CFLAGS,這是編譯所有.c文件時都要用的編譯選項;
修改頂層目錄Makefile的LDFLAGS,這是鏈接最后的應用程序時的鏈接選項;
修改各自子目錄下的Makefile:
“EXTRA_CFLAGS”, 它給當前目錄下的所有文件(不含其下的子目錄)設置額外的編譯選項, 可以不設置
“CFLAGS_xxx.o”, 它給當前目錄下的xxx.c設置它自己的編譯選項, 可以不設置
使用哪個編譯器?
修改頂層目錄Makefile的CROSS_COMPILE, 用來指定工具鏈的前綴(比如arm-linux-)。
確定應用程序的名字:
修改頂層目錄Makefile的TARGET, 這是用來指定編譯出來的程序的名字。
執行"make"來編譯,執行"make clean"來清除,執行"make distclean"來徹底清除。
2.3 通用makefile的設計思想
1. 在Makefile文件中確定要編譯的文件、目錄,比如:
obj-y += main.o obj-y += a/“Makefile”文件總是被“Makefile.build”包含的。
2. 在Makefile.build中設置編譯規則,有3條編譯規則:
i. 怎么編譯子目錄? 進入子目錄編譯:
$(subdir-y):make -C $@ -f $(TOPDIR)/Makefile.buildii. 怎么編譯當前目錄中的文件?
%.o : %.c$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -Wp,-MD,$(dep_file) -c -o $@ $<iii. 當前目錄下的.o和子目錄下的built-in.o要打包起來:
built-in.o : $(cur_objs) $(subdir_objs)$(LD) -r -o $@ $^3. 頂層Makefile中把頂層目錄的built-in.o鏈接成APP:
$(TARGET) : built-in.o$(CC) $(LDFLAGS) -o $(TARGET) built-in.o2.4 通用makefile原理分析
總結
以上是生活随笔為你收集整理的通用makefile的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 处理器的启动过程
- 下一篇: 女生工资3000算低吗 其实大家的工