Linux學習:Makefile簡介及模板

1、基本概念介紹:ide

   Makefile 文件就是告訴make命令須要怎麼樣的去編譯和連接程序。
  編寫Makefile的基本規則:
  1.若是這個工程沒有編譯過,那麼咱們的全部C文件都要編譯並被連接。
  
2.若是這個工程的某幾個C文件被修改,那麼咱們只編譯被修改的C文件,並連接目標程序。
  3.若是這個工程的頭文件被改變了,那麼咱們須要編譯引用了這幾個頭文件的C文件,並連接目標程序。
post

  $@--目標文件,$^--全部的依賴文件,$<--第一個依賴文件。ui

1 直觀方式spa

 舉個例子:一個工程有3個頭文件,和8個C文件,根據規則編寫Makefile以下:code

edit : main.o kbd.o command.o display.o insert.o search.o files.o utils.o
       cc -o edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o

main.o : main.c defs.h
       cc -c main.c

kbd.o : kbd.c defs.h command.h
       cc -c kbd.c

command.o : command.c defs.h command.h
       cc -c command.c

display.o : display.c defs.h buffer.h
       cc -c display.c

insert.o : insert.c defs.h buffer.h
       cc -c insert.c

search.o : search.c defs.h buffer.h
       cc -c search.c

files.o : files.c defs.h buffer.h command.h
       cc -c files.c

utils.o : utils.c defs.h
       cc -c utils.c
clean :
       rm edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o

  在這個makefile中,目標文件(target)包含:可執行文件 edit 和 中間目標文件(*.o),依賴文件(prerequisites)就是冒號後面的那些 .c 文件和 .h文件。每個 .o 文件都有一組依賴文件,而這些 .o 文件又是執行文件 edit 的依賴文件。blog

  輸入make指令後的執行內容以下:字符串

  1.   make會在當前目錄下找名字叫「Makefile」或「makefile」的文件。
  2.   若是找到,它會找文件中的第一個目標文件(target),在上面的例子中,他會找到「edit」這個文件,並把這個文件做爲最終的目標文件。
  3.   若是edit文件不存在,或是edit所依賴的後面的 .o 文件的文件修改時間要比edit這個文件新,那麼,他就會執行後面所定義的命令來生成edit這個文件。
  4.   若是edit所依賴的.o文件也存在,那麼make會在當前文件中找目標爲.o文件的依賴性,若是找到則再根據那一個規則生成.o文件。(這有點像一個堆棧的過程)
  5.   固然,C文件和H文件確定存在,因而make會生成 .o 文件,而後再用 .o 文件聲明make的終極任務,也就是執行文件edit了。

 

1.1 進階1:使用變量 get

 在上面的例子中,能夠看到[.o]文件的字符串被重複了兩次,若是工程須要加入一個新的[.o]文件,須要在各個依賴了該[.o]文件的地方添加,若是工程比較複雜會很麻煩,因此爲了makefile的易維護,在makefile中可使用變量。
 好比,聲明一個變量叫objects,也就叫 OBJECTS, objs, OBJS, obj, 或是 OBJ,只要可以表示obj文件就行。在makefile一開始就這樣定義:it

objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o

 因而,在makefile中以「$(objects)」的方式來使用這個變量了。
 進階版本1:
io

objects = main.o kbd.o command.o display.o insert.osearch.o files.o utils.o 
edit : $(objects) cc
-o edit $(objects) main.o : main.c defs.h cc -c main.c kbd.o : kbd.c defs.h command.h cc -c kbd.c command.o : command.c defs.h command.h cc -c command.c display.o : display.c defs.h buffer.h cc -c display.c insert.o : insert.c defs.h buffer.h cc -c insert.c search.o : search.c defs.h buffer.h cc -c search.c files.o : files.c defs.h buffer.h command.h cc -c files.c utils.o : utils.c defs.h cc -c utils.c clean : rm edit $(objects)

 因而若是有新的 .o 文件加入,只需添加到 objects 變量中便可。

1.2 進階2:讓make自動推導

 GNU的make很強大,它能夠自動推導文件以及文件依賴關係後面的命令,因而咱們就不必去在每個[.o]文件後都寫上相似的命令,只要make看到一個[.o]文件,它就會自動的把[.c]文件加在依賴關係中,而且 cc -c xx.c 也會被推導出來。
 進階版本2:

objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o edit : $(objects) cc -o edit $(objects) main.o : defs.h kbd.o : defs.h command.h command.o : defs.h command.h display.o : defs.h buffer.h insert.o : defs.h buffer.h search.o : defs.h buffer.h files.o : defs.h buffer.h command.h utils.o : defs.h .PHONY : clean clean : rm edit $(objects)

 這種方法,也就是make的「隱晦規則」。上面文件內容中,「.PHONY」表示,clean是個僞目標文件。

    即然make能夠自動推導命令,那堆[.o]和[.h]的依賴一樣能夠收攏起來。進階2.1:

objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o edit : $(objects) cc -o edit $(objects) $(objects) : defs.h kbd.o command.o files.o : command.h display.o insert.o search.o files.o : buffer.h .PHONY : clean clean : rm edit $(objects)

  上面2.1的版本使makefile變得更簡單,但文件依賴關係就顯得有點凌亂,魚和熊掌不可兼得,各取所好。

清空目標文件的規則

   每一個Makefile中都應該寫一個清空目標文件(.o和執行文件)的規則,這不只便於重編譯,也很利於保持文件的清潔。通常的風格都是:
clean:   rm edit $(objects)

 更爲穩健的作法是:

.PHONY : clean clean : -rm edit $(objects)

 前面說過,.PHONY意思表示clean是一個「僞目標」,不聲明僞目標的話,若是當前目錄有個名爲clean的文件,就會認爲目標已存在,致使後面規則不執行了。而在rm命令前面加了一個小減號的意思就是,也許某些文件出現問題,但不要管,繼續作後面的事。

 

2、模板:

一、編譯動態庫

 ############################################################# # Makefile for shared library. # 編譯動態連接庫 ############################################################# #set your own environment option CC = g++ CC_FLAG = -D_NOMNG -D_FILELINE #set your inc and lib INC = LIB = -lpthread -L./ -lsvrtool #make target lib and relevant obj PRG = libsvrtool.so OBJ = Log.o #all target all:$(PRG) $(PRG):$(OBJ) $(CC) -shared -o $@ $(OBJ) $(LIB) .SUFFIXES: .c .o .cpp .cpp.o: $(CC) $(CC_FLAG) $(INC) -c $*.cpp -o $*.o .PRONY:clean clean: @echo "Removing linked and compiled files......; rm -f $(OBJ) $(PRG) 

二、編譯靜態庫

 ############################################################# # Makefile for static library. # 編譯靜態連接庫 ############################################################# #set your own environment option CC = g++ CC_FLAG = -D_NOMNG -D_FILELINE #static library use 'ar' command AR = ar #set your inc and lib INC = LIB = -lpthread -L./ -lsvrtool #make target lib and relevant obj PRG = libsvrtool.a OBJ = Log.o #all target all:$(PRG) $(PRG):$(OBJ) ${AR} rv ${PRG} $? .SUFFIXES: .c .o .cpp .cpp.o: $(CC) $(CC_FLAG) $(INC) -c $*.cpp -o $*.o .PRONY:clean clean: @echo "Removing linked and compiled files......" rm -f $(OBJ) $(PRG) 

三、可執行程序

 ########################################### #Makefile for simple programs ########################################### INC= LIB= -lpthread CC=CC CC_FLAG=-Wall PRG=threadpooltest OBJ=CThreadManage.o CThreadPool.o CThread.o CWorkerThread.o threadpooltest.o $(PRG):$(OBJ) $(CC) $(INC) $(LIB) -o $@ $(OBJ) .SUFFIXES: .c .o .cpp .cpp.o: $(CC) $(CC_FLAG) $(INC) -c $*.cpp -o $*.o .PRONY:clean clean: @echo "Removing linked and compiled files......" rm -f $(OBJ) $(PRG) 
相關文章
相關標籤/搜索