(一)為什麼要編寫Makefile
我們自己平常在linux下編譯源文件時,當然可以使用gcc -Wall -g main.c -o main這樣的命令一個一個編譯,但是一個工程中的源文件不計其數,其按類型、功能、模塊分別放在若干個目錄中,我們一個個編譯是極其花費時間的,也是不可取的。
makefile帶來的好處就是——“自動化編譯”,一旦寫好,只需要一個make命令,整個工程完全自動編譯,極大的提高了軟件開發的效率。
makefile定義了一系列的規則來指定,哪些文件需要先編譯,哪些文件需要後編譯,哪些文件需要重新編譯,甚至於進行更復雜的功能操作,因為 makefile就像一個Shell腳本一樣,其中也可以執行操作系統的命令。
(二)Makefile的基本規則
Mackfile基本規則
Target ...: Dependencies ...
Command ...
說明:
1)目標(TARGET):即最終想要產生的文件,如:可執行文件,目標文件或中間文件等;目標也可以是要執行的動作,如clean,也稱為偽目標(用.PHONY指定偽目標)。
2)依賴(DEPENDENCIES):為了產生目標文件而依賴的文件列表,一個目標通常依賴於多個文件。
3)命令(COMMAND):是make執行的動作(shell命令或是可在shell下執行的程序,如echo)。注意:每個命令行的起始字符必須為TAB字符!
如果DEPENDENCIES中有一個或多個文件更新的話,COMMAND就要執行,這就是Makefile最核心的內容。
(三)簡單Makefile的編寫
1.單級目錄下的Makefile編寫
我們只需要使用vi Makefile命令創建一個新的Makefile文件,等我們編寫好後,只需要使用make 命令就可執行編譯操作。這裡我們創建兩個.c文件,使用他們生成目標文件:
[cpp]view plaincopy
.PHONY:clean
OBJECTS=01.o02.o
main:$(OBJECTS)
gcc-Wall-g$^-o$@
01.o:01.c
gcc-Wall-g-c$02.o:02.c
gcc-Wall-g-c$clean:
rm-fmain$(OBJECTS)上面是相對簡練的寫法,我們一個個來解釋:
1.使用變量來代替01.o 02.o ,方便後文使用。
2.使用自動化變量簡化一些操作
$@ 規則的目標文件名
$< 規則的第一個依賴文件名
$^ 規則的所有依賴文件列表
3.使用make clean 命令即可執行刪除操作
2.多級(二級)目錄生成可執行文件的Makefile的編寫
01 02 文件夾下分別有01.c 02.c ,並且和文件夾同級目錄的有03.c,main是由這三個.c文件共同生成的,如何編寫?
[cpp]view plaincopy
.PHONY:cleanall
CC=gcc
CFLAGS=-Wall-g
BIN=main
SUBDIR=$(shellls-d*/)
ROOTSRC=$(wildcard*.c)
SUBSRC=$(shellfind$(SUBDIR)-name'*.c')
SUBOBJ=$(SUBSRC:%.c=%.o)
$(BIN):$(ROOTOBJ)$(SUBOBJ)
$(CC)$(CFLAGS)$(ROOTOBJ)$(SUBOBJ)-o$(BIN)
.c.o:
$(CC)$(CFLAGS)-c$clean:
rm-f*.o$(BIN)$(ROOTOBJ)$(SUBOBJ)1.SUBDIR=$(shell ls -d */) 使用shell命令,將當前目錄下所有的子目錄賦給SUBDIR
2.ROOTSRC=$(wildcard *.c) ROOTSRC代表當前目錄下符合匹配模式的所有文件
3.SUBOBJ=$(SUBSRC:%.c=%.o) 生成.c對應的.o文件
以上就是這三個內嵌函數的使用方式。
3.多級(二級)目錄下生成多個可執行文件
緊接上例,01文件下生成01可執行文件,02文件夾下生成02可執行文件,要求使用Makefile一個make命令完成。
這就需要我們在每個文件夾下編寫自己的Makefile文件,最後使用文件夾目錄的Makefile完成操作。
[cpp]view plaincopy
01文件夾下的Makefile
CC=gcc
BIN=01
OBJS=01.o
.PHONY:allcleanprint
all:print$(BIN)
print:
@echo"----makeallin$(PWD)-----"
#$(BIN):$(OBJS)
#$(CC)$(OBJS)-o$@
%.o:%.c
$(CC)-c$clean:
@echo"----makecleanin$(PWD)---"
rm-f$(BIN)$(OBJS)[cpp]view plaincopy
02文件夾下的Makefile
(這裡02文件夾下為.cpp文件)
CXX=g++
BIN=02
OBJS=02.o
CPPFLAGS=-Wall-g
.PHONY:allcleanprint
all:print$(BIN)
print:
@echo"-----makeallin$(PWD)----"
$(BIN):$(OBJS)
$(CXX)$(CPPFLAGS)$(OBJS)-o$@
%.o:%.cpp
$(CXX)-c$clean:
@echo"----makecleanin$(PWD)----"
rm-f$(BIN)$(OBJS)[cpp]view plaincopy
文件夾同級目錄下的Makefile文件
SUBDIRS=0102
.PHONY:defaultallclean$(SUBDIRS)
default:all
allclean:
$(MAKE)$(SUBDIRS)TARGET=$@
$(SUBDIRS):
$(MAKE)-C$@$(TARGET)
上面兩個很好理解,最後的這個Makefile文件中,$(MAKE)代表make命令,TARGET默認是第一個即all,$(MAKE)-C(大寫)代表進入到0102的Makefile中,執行參數為TARGET的操作。
當我們執行makeclean時,TARGET即為clean
閱讀更多 IT生涯 的文章