4、make工具使用(makefile) - 零基礎 到 通用makefile,看這一篇就夠了!

四、make工具使用(makefile)

1、Makefile

人們通常利用 make 工具來自動完成編譯工作。這些工作包括:如果僅修改了某幾個源文件,則只重新編譯這幾個源文件;如果某個頭文件被修改了,則重新編譯所有包含該頭文件的源文件。利用這種自動編譯可大大簡化開發工作,避免不必要的重新編譯。

make 工具通過一個稱爲 makefile 的文件來完成並自動維護編譯工作。makefile 需要按照某種語法進行編寫,其中說明了如何編譯各個源文件並連接生成可執行文件,並定義了源文件之間的依賴關係。當修改了其中某個源文件時,如果其他源文件依賴於該文件,則也要重新編譯所有依賴該文件的源文件。 會不會寫makefile,從一個側面說明了一個人是否具備完成大型工程的能力。

2、Makefile基本規則

taget... : dependencies...

	command

	...
  • target(目標): 程序產生的文件,如可執行文件目標文件;目標也可以是要執行的動作,如 " clean"。

  • dependencies(依賴):是用來產生目標的輸入文件,一個目標通常依賴於多個文件。

  • command(命令):是make執行的動作,一個可以有多個命令,每個佔一行。注意:每個命令行的起始字符必須爲TAB字符!

如果dependencies中有一個或多個文件更新的話,command就要執行,這就是Makefile最核心的內容

3、最簡單的Makefile例子

# 源文件:main.c add.c add.h sub.c sub.h

main:main.o add.o sub.o
	gcc main.o add.o sub.o -o main
main.o:main.c add.h sub.h
	gcc -c main.c -o main.o
add.o:add.c add.h
	gcc -c add.c -o add.o
sub.o:sub.c sub.h
	gcc -c sub.c -o sub.o
clean:
	rm -f main main.o add.o sub.o

4、make是如何工作的

1、make會在當前目錄下找名字叫“Makefile”或“makefile”

2、如果找到,它會找文件中的第一個目標文件(target),在上面的例子中,他會找到“main”這個文件,並把這個文件作爲最終的目標文件。

3、如果main文件不存在,或是main所依賴的後面的 .o 文件的文件修改時間要比main這個文件新,那麼,他就會執行後面所定義的命令來生成main這個文件。

4、如果main所依賴的.o文件也存在,那麼make會在當前文件中找目標爲.o文件的依賴性,如果找到則再根據那一個規則生成.o文件。

5、當然,你的C文件和H文件是存在的啦,於是make會生成 .o 文件,然後再用 .o 文件make的終極任務,也就是執行文件main了。

5、Makefile使用僞目標

常見的僞目標 .PHONY

  • all: target1 target2

  • target1 :

    執行make all

  • install

    執行make install

  • clean

    執行make clean

# 源文件:main.c add.c add.h sub.c sub.h
main:main.o add.o sub.o
	gcc main.o add.o sub.o -o main
main.o:main.c add.h sub.h
	gcc -c main.c -o main.o
add.o:add.c add.h
	gcc -c add.c -o add.o
sub.o:sub.c sub.h
	gcc -c sub.c -o suntract.o
.PHONY:clean
clean:
	rm -f main main.o add.o sub.o

6、makefile中使用變量

objects=main.o add.o sub.o
CC=gcc
main:$(objects)
	$(CC) $(objects) -o main
main.o:main.c add.h sub.h
	$(CC) -c main.c -o main.o
add.o:add.c add.h
	$(CC) -c add.c -o add.o
sub.o:sub.c sub.h
	$(CC) -c sub.c -o sub.o
.PHONT:clean
clean:
	rm -f main main.o add.o sub.o

7、make自動推導

  • GNU的make很強大,它可以自動推導文件以及文件依賴關係後面的命令,於是我們就沒必要去在每一個[.o]文件後都寫上類似的命令,因爲,我們的make會自動識別,並自己推導命令。
  • 只要make看到一個[.o]文件,它就會自動的把[.c]文件加在依賴關係中,如果make找到一個whatever.o,那麼 whatever.c,就會是whatever.o的依賴文件。並且 gcc -c whatever.c 也會被推導出來
objects=main.o add.o sub.o
main:$(objects)
	gcc $(objects) -o main
main.o:add.h sub.h
add.o:add.h
sub.o:sub.h
clean:
	rm -f main main.o add.o sub.o
objects=main.o add.o sub.o
main:$(objects)
	gcc $(objects) -o main
$(objects):	#甚至這行不要也可以
.PHONY:clean 
clean:
	rm -f *.o main

8、Makefile中常見函數

  • wildcard 函數
    • 當前目錄下匹配模式的文件。
    • 例如:src=$(wildcard *.c)
  • notdir 函數
    • 去除路徑
    • 例如:$(notdir $src)
  • patsubst 函數
    • 模式匹配替換
    • 例如:(patsubst(patsubst %.c,%o,src)
    • 等價於$(src:.c=.o)
  • shell函數
    • 執行shell命令
    • 例如:$(shell ls -d */)
    • 例如:$(shell find -name ‘*.c’)
選項名 作用
$@ 規則的目標文件名
$< 規則的第一個依賴文件名
$^ 規則的所有依賴文件列表
ELF=main
CC=gcc
src=$(wildcard *.c)
objects=$(src:.c=.o)
$(ELF):$(objects)
	$(CC) $^ -o $@
$(objects):
clean:
	rm -f $(objects) $(ELF)

9、多級目錄Makefile

ELF=main
CC=gcc
src=$(shell find -name '*.c')
objects=$(src:.c=.o)
$(ELF):$(objects)
$(objects):
clean:
	rm -f $(objects) $(ELF)

10、最終Makefile(通用) – C/C++版本

ELF=main
CC=gcc
CPPFLAGS=	#C++語言編譯器參數 例如:-g -Wall 
LDFLAGS=	#連接器參數 例如:-lpthread -lrt -lsqlite3
SRC=$(shell find -name '*.c')
OBJECT = $(SRC:.c=.o)
$(ELF):$(OBJECT)
	$(CC) $(CPPFLAGS) $(OBJECT) -o $(ELF) $(LDFLAGS)
$(OBJECT):
clean:
	rm -f $(OBJECT) $(ELF)

我在項目中用的makefile(C++版本) 如下

ELF=main
CC=g++
CPPFLAGS=-g -Wall 
LDFLAGS=-lpthread -lrt -lsqlite3
SRC=$(shell find -name '*.cpp')
OBJECT = $(SRC:.cpp=.o)
$(ELF):$(OBJECT)
	$(CC) $(CPPFLAGS) $(OBJECT) -o $(ELF) $(LDFLAGS)
$(OBJECT):
clean:
	rm -f $(OBJECT) $(ELF)
參數 描述
-g 生成供 gdb 使用的調試信息。
-Wall 編譯後顯示所有警告
-lpthread 通過pthreads庫加入對多線程的支持,pthread是POSIX指定的標準線程庫.
-lrt 一般含有#include<time.h>頭文件的代碼,編譯的時候需要加上-lrt
-lsqlite3 sqlite3數據庫

專欄 《linux網絡編程》 將持續更新中…
從linux 零基礎 到 高併發服務器架構

如果我的文章能夠幫到您,可以點個贊!
您的每次 點贊、關注、收藏 都是對我最大的鼓勵!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章