乙個簡單的makefile教程

2021-07-10 13:32:40 字數 4550 閱讀 2331

寫makefile是乙個非常便利的編譯方法,由於以前習慣把所有的**都集中在乙個檔案中,體現不出make的優勢,當把源**拆分成若干個原始檔,makefile就顯得必要了。以下是乙份簡單的makefile的教程,參考自a ****** makefile tutorial。正如原文所說,這份教程只是打算讓初學者快速入門,寫自己的makefile,來維護中小型的專案。

乙個簡單的例子,用k&r c中4.5那個例子:主程式(main.c)、函式**(getop.c, stack.c, getch.c)、標頭檔案(calc.h)。

一般的,我們會使用

1

gcc -o calc main.c getch.c getop.c stack.c -i.

來編譯。-i.是指gcc在當前目錄(.)下尋找include檔案。如果不用makefile,在測試-修改-除錯過程中,如果我們不想重敲那條 編譯指令的話,我們必須不停地在終端中按上下鍵來尋找最後的那條編譯指令。不幸的是,這種編譯方法有兩個缺陷:1. 當你把編譯指令丟失或者換電腦的時候,這樣效率會很低;2. 當我們只修改了乙個.c檔案時,每一次都將必須重新編譯所有的檔案,這非常耗時,不划算。現在是切入主題的時候了

最簡單的makefile寫法:

version 1

1

2

calc: main.c getch.c getop.c stack.c

gcc -o calc main.c getch.c getop.c stack.c -i.

如果把這些語句寫入乙個叫makefile或者makefile的檔案,然後在終端中輸入make,她將會按你在makefile中要求地編譯。注 意:第一行中並沒有任何引數,只是在冒號(:)後列出編譯中所需的檔案,當第一行中的任何檔案中更改時,make就知道calc需要重新編譯了。現在我們 已經解決了問題1,不用上下按箭頭了,但是對於問題2依舊沒有很好地解決。注意,非常重要:gcc前面必須有乙個tab,在任何指令之前都要有乙個 tab,不然make就會罷工的。

讓事情變得更有效率一點:

version 2

1

2

3

4

5

cc = gcc

cflags = -i.

calc: main.c getch.c getop.c stack.c

$(cc) -o calc main.c getch.c getop.c stack.c $(cflags)

現在我們新定義了兩個常量cc和cflags。這些是與make交流的特殊的常量,讓make知道我們要怎麼編譯.c檔案。cc是c編譯器所使用的,cflags是編譯用的引數。make會先分別編譯.c檔案,然後生成可執行檔案calc。

這種形式的makefile在小專案中非常有效,但是有乙個遺憾:include檔案的變動。如果我們修改了calc.h檔案,make是不會重新 編譯.c檔案的,事實上我們需要重新編譯。為了解決這一問題,我們必須告訴make所有的.c檔案依賴於.h檔案。我們可以在makefile中增加一條 規則:

version 3

1

2

3

4

5

6

7

8

9

cc = gcc

cflags = -i.

deps = calc.h

%.o: %.c $(deps)

$(cc) -c -o $@ $< $(cflags)

calc: main.o getch.o getop.o stack.o

$(cc) -o calc main.o getch.o getop.o stack.o $(cflags)

首先巨集定義deps,宣告.c檔案所依賴的.h檔案。然後我們定義一條規則,為所有的.c檔案生成乙個.o檔案。規則描述:.o檔案依賴於.c檔案 和deps中宣告的.h檔案,為了產生.o檔案,make需要使用cc中宣告的編譯器來編譯.c檔案。-c 意味著產生object檔案,-o $@ 意思是編譯生成的檔案用上面的%.o來命名,$< 指依賴關係中的第一項(%.c)cflags的定義和之前一樣。

最後為了簡化,我們使用特殊的巨集定義 $@ 和 $^ ,分別表示冒號(:)的左右兩邊。為了讓make中所有的規則更具通用性,在version 4中,我們把所有的include檔案作為deps的一部分,所有的object檔案作為obj的一部分:

version 4

01

02

03

04

05

06

07

08

09

10

cc = gcc

cflags = -i.

deps = calc.h

obj = main.o getch.o getop.o stack.o

%.o: %.c $(deps)

$(cc) -c -o $@ $< $(cflags)

calc: $(obj)

$(cc) -o $@ $^ $(cflags)

如果我們想把.h檔案放在include目錄下,.c檔案放在src目錄下以及一些本地的庫放在lib目錄下,同時我們想把.o檔案整理一下,避免 整個目錄的凌亂。在version 5中,定義了include,lib的目錄,並把object檔案放到了src目錄下的obj子目錄,同時還包含了任何我們想要包含的庫(比如說math 庫-lm)。這份makefile將放在src目錄下。值得注意的是,在這一版本中新增了一條clean的規則,使make clean得以執行。目錄結構如下:

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

idir = ../include

cc = gcc

cflags = -i$(idir)

odir = obj

ldir = ../lib

libs = -lm

_deps = calc.h

deps = $(patsubst %,$(idir)/%,$(_deps))

_obj = main.o getch.o getop.o stack.o

obj = $(patsubst %,$(odir)/%,$(_obj))

$(odir)/%.o: %.c $(deps)

$(cc) -c -o $@ $< $(cflags)

calc: $(obj)

gcc -o $@ $^ $(cflags) $(libs)

.phony: clean

clean:

rm-f $(odir)/*.o *~ core $(idir)/*~

其中patsubst函式包含3個引數:需要匹配的式樣,用什麼來替換它,需要被處理的由空格分隔的字串。

現在我們已經有了乙個不錯的makefile,根據這個,我們能維護中小型的工程。當然我們能增加一些更複雜的規則;甚至創造一些規則。更多關於makefile和make請參考gnu make manual。

乙個簡單的makefile的編寫

標頭檔案 part.h cpp檔案 包含part.h part.cpp cpp檔案 包含part.h partmain.cpp makefile編寫如下 main partmain.o part.o g o main partmain.o part.o partmain.o partmain.cpp...

乙個最簡單的Makefile例子

1.hello.c include int main 2.makefile hello hello.o cc o hello hello.o hello.o hello.c cc c hello.c clean rm hello.o 說明 cc o hello hello.o前面是乙個tab的空格 ...

乙個最簡單的makefile示例

1.hello.c include int main 2.makefile hello hello.o cc o hello hello.o hello.o hello.c cc c hello.c clean rm hello.o 說明 cc o hello hello.o前面是乙個tab的空格 ...