Makefile快速入門

   Make是一個可擴展性極強的編譯構建工具,將它和相關語言的編譯器結合起來,我們幾乎可以用它來 編譯構建任何編程語言程序。

Makefile的基本語法結構

   make主要是通過默認的 Makefilemakefile 的配置文件(下文統一稱 makefile )中的規則來構建項目的。 makefile 其實是有無數的規則組成的。 我們可以用這些規則來編譯,鏈接,以及運行相關命令和腳本。這些規則的語法大概是這樣的:

target(規則生成的目標文件或者make執行的規則命令名) … : prerequisitse(規則的輸入文件,或源文件) …
    recipe(make執行的規則命令)
    …
    …

   recipe(規則命令)必須有一個製表符(TAB)。並且如果一旦任何一個源文件變化了,規則命令都會重新執行,否則不會。 make 檢測文件的是否修改是通過文件的上次修改時間來確定的

一個典型的 ~makefile~ 的例子
IDIR=../include  
CC=gcc     
CFLAGS=-I$(IDIR) 
ODIR=obj 
LDIR=../lib
LIBS=-Im
_DEPS=hellomake.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))

_OBJ=hellomake.o hellofunc.o
OBJ=$(patsubst %,$(ODIR)/%,$(_OBJ))

$(ODIR)/%.o:%.c $(DEPS)
    $(CC) -c -o $@ $< $(CFLAGS)

hellomake: $(OBJ)
    $(CC) -o $@ $^ ${CFLAGS} $(LIBS)


.PHONY: clean


clean:
    rm -f $(ODIR)/*.o *~core $(INCDIR)/*~

文件結構

├── include
│   └ hellomake.h
├── lib
└── src
    ├── hellofunc.c
    ├── hellomake
    ├── hellomake.c
    ├── makefile
    └── obj
    ├── hellofunc.o
    └── hellomake.o

   這個makefile文件會做如下工作

  1. src 目錄下的 hellofunc.chellomake.c 的源文件編譯到 obj 目錄下,分別生成 hellofunc.ohellmake.o 目標文件
  2. 利用 obj 目錄下的 hellofunc.ohellomake.o 的目標文件和 include 目錄下的 hellomake.h 文件,以及 math 庫鏈接在 src 目錄下生成 hellomake 可執行程序

   等價於運行以下程序

gcc -c -o obj/hellofunc.o  hellofunc.c -I ./include
gcc -c -o obj/hellomake.o  hellomake.c -I ./include
gcc -o hellomake hellomake.o hellofunc.o  -I ./include -Im
makefile規則

   makefile 中的規則分爲模式規則和標準規則。標準規則是make已經定義好的規則,比如 allinstall , 我們下面會介紹,標準規則可以不提供源文件。 比如:

clean:
    rm -f $(ODIR)/*.o *~core $(INCDIR)/*~

   模式規則,通常包含通配符。模式規則裏面必須包含源文件。 比如:

$(ODIR)/%.o:%.c $(DEPS)
    $(CC) -c -o $@ $< $(CFLAGS)

hellomake: $(OBJ)
    $(CC) -o $@ $^ ${CFLAGS} $(LIBS)
makefile中的標準規則

   makefile 中定義了許多標準規則,我們可以直接在 makefile 中使用。

  • all

   all 會編譯整個程序,同 make all 命令。在 makefile 中一個構建是由多個規則節點構成。 all 是一個僞規則,它本質上並不做任何工作。它只表示,它會依賴文件或子規則來 完成整個程序的構建工作。我們既可以爲 all 指定子規則,也可以忽略。下面兩個例子說明這兩種用法的區別。

all: execuatble1 execuatlbe2

   上面的規則表示, all 的整個構建任務是生成 executable1executable2 兩個可執行程序。也可整個構建任務是依賴 executable1executable2 另個文件的。

*對 executable1.cppexecutable2.cpp 分別採用如下規則:*

$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<

   這裏 all 並沒有指定子規則生成 executable1executable2 文件。那麼 make 將會調用默認的規則來生成這兩個文件。

**我們也可以指定相應的子規則來生成相應的依賴文件。

all: execuatble1 execuatlbe2
executable1: executable1.cpp
   $(CC) $(CFLAGS) $(LDFLAGS) -o  ./bin/$@  $<
executable2: executable2.cpp
   $(CC) $(CFLAGS) $(LDFLAGS) -o  ./bin/$@  $<

   這裏我們指定了相應子規則來生成相應的可執行文件。

一般 make 只會執行生成一個可執行文件,然後就會停止, 我們通常可以將 all 作爲第一個規則,用它來爲多個源文件分別生成多個可執行文件。

InterviewProblems: InterviewProblems.cpp
    $(CC) $(LDFLAGS) -o $(BINDIR)$@  $^
InterviewProblems_claimed_correct: InterviewProblems_claimed_correct.cpp
    $(CC) $(LDFLAGS) -o $(BINDIR)$@  $^

   這裏, make 只會生成 InterviewProblems 後就停止。

生成多個源文件分別生成多個可執行文件
CC=g++
BINDIR=./bin/
LDFLAGS=-std=c++11
OBJ=InterviewProblems.cpp InterviewProblems_claimed_correct.cpp
EXECUTABLE=InterviewProbles InterviewProblems_claimed_correct


all:  InterviewProblems  InterviewProblems_claimed_correct

InterviewProblems: InterviewProblems.cpp
    $(CC) $(LDFLAGS) -o $(BINDIR)$@  $^
InterviewProblems_claimed_correct: InterviewProblems_claimed_correct.cpp
    $(CC) $(LDFLAGS) -o $(BINDIR)$@  $^

文件目錄結構

├── bin
│   ├── InterviewProblems
│   └── InterviewProblems_claimed_correct
├── InterviewProblems_claimed_correct.cpp
├── InterviewProblems.cpp
├── makefile

   該 makefile 分別將 InterviewProblems.cppInterviewProbles_claimed_correct.cpp 編譯成 bin 目錄下的 InterviewProblemsInterviewProblems_claimed_correct 可執行文件。

發佈了58 篇原創文章 · 獲贊 43 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章