Linux C : Makefile 的编写和示例
? ? ? ? make工具是Unix/Linux 的一個編譯工具,它按照順序讀取 Makefile? 或 makefile ,進行自動地有選擇地執行編譯鏈接,只對影響到的修改的文件進行重新編譯,不需要對整個工程進行重新編譯。而Makefile中些內容的就是它的編譯方式。
? ? ? ?Makefile 的格式:
? ? ?
| 目標項 | 依賴項列表 |
| [target] : | ?file1? ?file2? ?file3 ... |
| ? | 規則 |
| <tab> | command1 |
| <tab> | command2 |
| ... | ... |
?
? ? ? ?target是一個目標文件,也可以是Object File,也可以是執行文件。還可以是一個偽目標。這是一個文件的依賴關系,target這一個或多個的目標文件依賴于 依賴項列表中的文件,其生成規則定義在command中。說白一點就是說,依賴項列表中如果有一個以上的文件比target文件要新或者target文件不存在的話,command所定義的命令就會被執行,如果依賴不存在或者更舊,那么就會執行生成依賴的對應target。如果依賴列表中的偽目標總是會被執行,相對于子程序段一樣,先從左開始判斷依賴列表,如果依賴時文件則判斷是否要更新,如果是偽目標則直接執行。偽目標所依賴的偽目標也會被跟著執行。為了避免偽目標和文件名沖突,可以顯示指定偽目標,關鍵字為.PHONY:
? ? ? 依賴項就是,要生成那個target所需要的文件或是目標。
? ? ? ?command也就是make需要執行的命令,通常是shell命令
? ?
例如
在一個文件 mysum.c中寫入如下代碼
在主程序 helloword.c 寫入如下代碼 ,可以看出 主程序中引用到了 mysum.c?
?
如果要編譯 以上兩個文件,那么要在Makefile中寫上
output: helloworld.c mysum.c #格式 目標頭: 依賴文件列表gcc -o output helloworld.c mysum.c #格式 每行開始必須是tab制表符執行? make? 或者? make -f? Makefile 進行編譯? 。 其中 -f? 指定一個編譯過程的文件名(默認是Makefile,編譯命令格式 make [目標名,默認值為第一個偽目標]?-f [makefile文件名]。當連續執行第二次時,make就不會再構建沒被更改的目標。
? ? ? Makefile的編寫也可以作些改進,例如把一些關鍵命令定義成變量,寫在文件頭,例如gcc ,假如之后要改用g++ 來編譯呢,難不成要在全文一個個找出gcc再替換成g++?其實把關鍵命令定義成變量就可以應對編譯方式的變更操作了。如果編譯的文件太多達到幾百個怎么辦?可以用include 關鍵字來引用其他文件內容,再其他文件中用變量來接所有要編譯的文件名。由于命令執行失敗會自動中斷make,可以再命令前加 ‘-’ 符號,表示此命令如果執行失敗則無視報錯繼續執行往下的命令。
? ? 如果在makefile中匹配/查詢文件,如果在當前目錄未找到,可在(大寫)VPATH和其子目錄下繼續找。?關于(小寫)vpath語法,?vpath [過濾條件] [查詢目錄] , 例如 vpath %.c? /home/hu 表示?在makefile中匹配/查詢文件,如果在當前目錄未找到則可以在 /home/hu/目錄和子目錄下的所有 .c的后綴的文件名列表繼續找。
? ? ? Makefile 的自動變量
| $@ | 當前目標名 |
| $< | 第一個依賴項名 |
| $^ | 所有依賴項名 |
| $* | 不包含擴展名的當前依賴項名 |
| $? | 比當前目標新的依賴項列表 |
| $# | 依賴項個數 |
? ? ? C++項目型Makefile示例
? ? ??
#變量定義 LIB_NAME = libQuantLib.so -include ql_var.mk #這里面包含QL_SRC_DIR ,HEADER_DIR 等變量信息 CXX = g++ DEFIND = -DQL_ERROR_FUNCTIONS DEFIND += -DQL_ERROR_LINES CXXFLAGS = $(DEFINE) $(addprefix -I, $(HEADER_DIR)) -O2 -Wall -c -fmessage-length=0 -fpic -fno-strict-aliasing HEADER_DIR = "." HEADER_DIR += "$(BOOST_INCLUDE)" HEADER_DIR += "$(ZLOG_INCLUDE)" HEADER_DIR += "$(JAVA_HOME)/include" HEADER_DIR += "$(JAVA_HOME)/include/linux" SRC_DIR = $(QL_SRC_DIR) #源文件集合變量 ,定義在ql_var.mk DEP_DIR = $(QL_DEP) #依賴集合變量 ,定義在ql_var.mk vpath %.hpp $(HEADER_DIR) vpath %.cpp $(SRC_DIR)all: build_dir ql #執行make或者make all 相當于執行 make build_dir 和make ql$(BUILD_DIR)/%.o : %.cpp #生成在build目錄下的 .o文件的生成規則$(CXX) $(CXXFLAGS) -MMD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" -include $(DEP_FILE).PHONY: build_dir build_dir:@mkdir -p $(BUILD_DIR).PHONY: scan #執行 make scan 相當于先執行 make build_dir 再執行自身命令 scan: build_dir@echo Scanning Project ....@./scan.sh #執行shell,此shell的目的是創建ql_var.mk,并在此文件中定義要編譯的文件和其依賴ql: $(LIB_OBJ) $(QL_OBJ) # $(LIB_OBJ) $(QL_OBJ)為.o文件名集合,在ql_var.mk中被定義,如果發現依賴被更新則自動觸發 .o文件的生成規則$(CXX) -share -o $(LIB_NAME) $^ "$(ZLOG_LIB)/libzlog.a".PHONY: clean clean: @echo Clean Project-@rm -rf $(BUILD_DIR)-@rm -f ql_var.mk執行編譯順序
make clean #清空編譯目錄和刪除變量文件 make scan #創建編譯目錄和執行scan.sh ,從而創建變量文件 make #執行make all,創建編譯目錄 和鏈接目標文件(.o),需要鏈接的文件列表來源于變量文件中,如果依賴項缺失,則編譯出依賴文件?
Makefile全解可參考:?https://blog.csdn.net/weixin_38391755/article/details/80380786
總結
以上是生活随笔為你收集整理的Linux C : Makefile 的编写和示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 操作系统原理:全局页面置换算法、工作集页
- 下一篇: 操作系统原理:进程与线程、进程生命周期、