Makefile 簡單總結

準備

要看懂Makefile 首先得知道gcc怎麼用吧?根據gcc –h的的內容可以看出,編譯過各分爲4個步驟:

  1. 預處理(preprocess) ,使用-E 選項,替換宏定義和頭文件,默認輸出到標準輸出,不生成文件。
  2. 編譯(compile),使用-S選項,生成彙編文件。
  3. 彙編(assemble),使用-c選項,成生目標文件。
  4. 連接(link),不添加選項,生成可執行文件。

實際上gcc會調不同的處理程序來完成這些任務,但這裏不用管它。除了這些,還有一些常用的選項:

選項—————- 說明
-o 指定目標的名稱,上面4個步驟中,除了1,都有默認的名稱。如果想修改名稱,就可以使用這個選項,包 括指定預處理的目標
-g 給目標文件加上調試信息,只有這樣才能被GDB調試。如果是-ggdb的話,將儘可能的生成gdb的可以使用的調試信息
-v 顯示編譯器的版本信息
-I (大寫的i) 添加頭文件的搜索路徑
-L 添加庫文件的路徑,也可以修改環境變量LD_LIBRARY_PATH
-l(小寫的L) 在鏈接動態庫文件時,除了指定路徑,還需要指定其名字,編譯器查找動態庫時有隱含的命名規則,即在給出的名字前面加上lib,後面加上.so或者.a來確定庫的名稱,默認優先選擇.so,加-static時,只鏈接.a
-static 禁止使用共享連接
-shared 生成共享目標文件。通常用在建立共享庫時
-w 不生成任何警告信息
-Wall 生成所有警告信息
-werror 把所有的告警信息轉化爲錯誤信息,並在告警發生時終止編譯過程
-D 添加宏定義
-pthread 鏈接 POSIX thread 庫,相對於-lpthread,增加了_REENTRANT宏定義。推薦使用-pthread

符號

main: main.c util.c defs.h
    gcc -o $@ $^

$@ 代表目標文件main
$^ 代表所有的依賴文件main.c util.c defs.h
$< 代表第一個依賴文件main.c

函數

#這兩種方法都能得到指定目錄下的所有.c文件
SOURCES = $(shell ls *.c  ./sub/*.c)
SOURCES = $(wildcard *.c ./sub/*.c)

#去掉路徑信息
FILES = $(notdir $(SOURCES))

#更改後綴(只是爲了得到一組文件名,不會更改原文件)
PROGRAMS = $(FILES :.c=) #去掉後綴
OBJ=$(FILES :.c=.o) #更改
#或者使用patsubst函數
OBJ=$(patsubst *.c *.o $(FILES))

簡要說明

CFLAGS=-g
#定義變量
objects = main.o command.o
#第一個目標爲最後生成的目標
edit : $(objects)
    cc -o $@ $^ #cc是unix中常用編譯器,linux下指向gcc.

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

#.PHONY表示,clean是個僞目標文件,可以理解爲是一個動作,一般用來清除make生成的文件。也可以是其它名字,通過make xxx來執行。
.PHONY clean
clean :
    -rm edit $(objects) #減號表示忽略錯誤

make能自動推導和.o文件相同文件名的.c文件。於是可以簡化成這樣子:

objects = main.o command.o
edit : $(objects)
    cc -o edit $(objects)
main.o : defs.h
command.o :defs.h command.h
.PHONY clean
clean :
    -rm edit $(objects)

其中main.o 和 command.o都依賴了defs.h, 可以寫成這樣(不推薦這種寫法,易混亂):

objects = main.o command.o
edit : $(objects)
    cc -o edit $(objects)
main.o command.o : defs.h
command.o :command.h
.PHONY clean
clean :
    -rm edit $(objects)

單目錄下通用的Makefile

#for c
EXE=main
CC=gcc
SRC=$(wildcard *.c)
OBJ=$(SRC:.c=.o)
DEP=$(patsubst %.c,.%.d,$(SRC))
CFLAGS=-g
$(EXE):$(OBJ)
    $(CC) $^ -o $@

$(DEP):.%.d:%.c
    @set -e;\
    rm -f $@;\
    $(CC) -M $< > $@.$$$$;\
    sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@;\
    rm -f .*.d*

-include $(DEP)

clean:
    @rm $(EXE) $(OBJ) $(DEP) -f

#for c++
EXE=main
CC=g++
SRC=$(wildcard *.cpp)
OBJ=$(SRC:.cpp=.o)
DEP=$(patsubst %.cpp,.%.d,$(SRC))
CFLAGS=-g
$(EXE):$(OBJ)
    $(CC) $^ -o $@

$(DEP):.%.d:%.cpp
    @set -e;\
    rm -f $@;\
    $(CC) -MM $< > $@.$$$$;\
    sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@;\
    rm -f .*.d*

-include $(DEP)

clean:
    @rm $(EXE) $(OBJ) $(DEP) -f

其它細節

  1. make 支持的默認文件名:”GNUmakefile”、”makefile”、”Makefile”, 可以用make -f filename指定makefile.
  2. include foo.mk 包含其它makefile文件
  3. 默認會include 環境變量MAKEFILES 中的makefile,不建議設置這個變量。

參考鏈接

一個簡單的通用Makefile實現
自動處理依賴
Makefile的函數

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