复习(二)—— Makefile工具使用
人們通常利用 make 工具來自動完成編譯工作。這些工作包括:如果僅修改了某幾個源文件,則只重新編譯這幾個源文件;如果某個頭文件被修改了,則重新編譯所有包含該頭文件的源文件。利用這種自動編譯可大大簡化開發工作,避免不必要的重新編譯。
Makefile
make 工具通過一個稱為 makefile 的文件來完成并自動維護編譯工作。makefile 需要按照某種語法進行編寫,其中說明了如何編譯各個源文件并連接生成可執行文件,并定義了源文件之間的依賴關系。當修改了其中某個源文件時,如果其他源文件依賴于該文件,則也要重新編譯所有依賴該文件的源文件。
Makefile基本規則
target...:prerequisites...command...目標(target):程序產生的文件,如可執行文件和目標文件;目標也可以是要執行的動作,如“clean”。
依賴(prerequisites):是用來產生目標的輸入文件,一個目標通常依賴于多個文件。
命令(command):是make執行的動作,一個可以有多個命令,每個占一行。注意:每個命令行的起始字符必須為TAB字符!
如果prerequisites中有一個或多個文件更新的話,command就要執行,這就是Makefile最核心的內容
最簡單的Makefile例子
源文件有:
main.c
swap.h
#ifndef _SWAP_H_ #define _SWAP_H_void Swap(int *a,int *b);#endifswap.c
#include "swap.h"void Swap(int *a,int *b){int *temp = a;a = b;b = temp;}將源文件放到同一位置后,用vi Makefile (這里M可以不用大寫)命令創建Makefile文件并添加內容如下:
main:main.o swap.ogcc main.o swap.o -o main //注意空一個tab main.o:main.c swap.hgcc -c main.c -o main.o swap.o:swap.c swap.hgcc -c swap.c -o swap.o clean:rm -f main main.o swap.o添加完并保存后,用 make 編譯執行而后生成一個 main 文件,用./main執行。
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了。
常見偽目標.PHONY
all: target1 target2 Target1:執行make all install執行make install Clean執行make cleanMakefile使用偽目標:
main:main.o swap.o gcc main.o swap.o -o main main.o:main.c swap.hgcc -c main.c -o main.o swap.o:swap.c swap.hgcc -c swap.c -o swap.o .PHONY:clean clean:rm -f main main.o swap.o(注意:同樣是寫到Makefile文件里,然后執行make,最后執行生成的可執行文件,下文操作方法都一樣。)
Makefile自動化變量
| $@ | 規則的目標文件名 |
| $< | 規則的第一個依賴文件名 |
| $^ | 規則的所有依賴文件列表 |
makefile中使用變量
objects=main.o swap.o main:$(objects)gcc $(objects) -o main main.o:main.c swap.hgcc -c main.c -o main.o swap.o:swap.c swap.hgcc -c swap.c -o swap.o .PHONT:clean clean:rm -f main main.o swap.omake自動推導
GNU的make很強大,它可以自動推導文件以及文件依賴關系后面的命令,于是我們就沒必要去在每一個[.o]文件后都寫上類似的命令,因為,我們的make會自動識別,并自己推導命令。
只要make看到一個[.o]文件,它就會自動的把[.c]文件加在依賴關系中,如果make找到一個whatever.o,那么 whatever.c,就會是whatever.o的依賴文件。并且 gcc -c whatever.c 也會被推導出來。
缺點:一旦新增加源文件就要修改
示例:
objects= main.o swap.o main:$(objects)gcc $(objects) -o main $(objects): .PHONY:clean clean:rm -f main *.oMakefile中常見函數
1、wildcard函數:當前目錄下匹配模式的文件
例如:
2、notdir函數:去除路徑
例如:
3、patsubst函數:模式匹配替換
例如:
4、shell函數:執行shell命令
例如:
優點:不需要修改makefile就能適應
示例:
ELF=main CC=gcc src=$(wildcard *.c) objects=$(src:.c=.o) $(ELF):$(objects)$(CC) $^ -o $@ $(objects): clean:rm -f $(objects) $(ELF)多級目錄Makefile
ELF=main CC=gcc src=$(find -name '*.c') objects=$(src:.c=.o) $(ELF):$(objects) .c.o:$(CC) –c $< -o $@ #$(objects): clean:rm -f $(objects) $(ELF)在頂層目錄中編寫一個Makefile
CC=gcc SUBDIR=$(shell ls -d */) ELF = main ROOTSRC=$(wildcard *.c) ROOTOBJ=$(ROOTSRC:%.c=%.o) SUBSRC=$(shell find $(SUBDIR) -name '*.c') SUBOBJ=$(SUBSRC:%.c=%.o)$(ELF):$(ROOTOBJ) $(SUBOBJ)$(CC) -o $(ELF) $(ROOTOBJ) $(SUBOBJ) .c.o:echo $(@D) $(<F) $(@F)$(CC) -c $(@D)/$(<F) -o $(@D)/$(@F) clean:rm $(ELF) $(ROOTOBJ) $(SUBOBJ)總結
以上是生活随笔為你收集整理的复习(二)—— Makefile工具使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 复习笔记(九)——C++中的容器(STL
- 下一篇: SQLite3单例模式(C++)