GNU Make / Makefile 學習資料node
GNU Make學習總結(一)
GNU Make學習總結(二)
這篇學習總結,從一個簡單的小例子開始,逐步加深,來說解Makefile的用法。
最後用上面總結過的知識,給出了一個通用的C/C++ Makefile
文中提到《GNU 項目管理》一書,有280頁。我以爲初學不必看這麼厚的書。豆瓣上對其評價也是不太實用。等之後有更深層次的需求時,再去看。
另外還有:
阮一峯-Make命令教程
這篇寫的很簡單,不過其中提到了一點很重要:每一行"命令"是獨立的Shell。第二篇《使用Make構建網站》不須要看,是針對node.js的。
陳皓-跟我一塊兒寫Makefile
這本讀起來很輕鬆,同時也比較全面。
徐海兵翻譯-GNU make手冊
官方文檔一般是深刻淺出的,很是推薦。就是比較羅嗦,也很厚,放最後看好了。
做者:Hexus
連接:https://www.jianshu.com/p/d63aff959d3d
來源:簡書
簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。
今天學習了makefile的基本語法,特此總結一下。函數
主要的學習網站:https://www.jianshu.com/p/d63aff959d3d
原文:
工具
GNU Make / Makefile 學習資料 GNU Make學習總結(一) GNU Make學習總結(二) 這篇學習總結,從一個簡單的小例子開始,逐步加深,來說解Makefile的用法。 最後用上面總結過的知識,給出了一個通用的C/C++ Makefile 文中提到《GNU 項目管理》一書,有280頁。我以爲初學不必看這麼厚的書。豆瓣上對其評價也是不太實用。等之後有更深層次的需求時,再去看。 另外還有: 阮一峯-Make命令教程 這篇寫的很簡單,不過其中提到了一點很重要:每一行"命令"是獨立的Shell。第二篇《使用Make構建網站》不須要看,是針對node.js的。 陳皓-跟我一塊兒寫Makefile 這本讀起來很輕鬆,同時也比較全面。 徐海兵翻譯-GNU make手冊 官方文檔一般是深刻淺出的,很是推薦。就是比較羅嗦,也很厚,放最後看好了。 做者:Hexus 連接:https://www.jianshu.com/p/d63aff959d3d
來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。
引用阮一峯的話:學習
代碼變成可執行文件,叫作編譯(compile);先編譯這個,仍是先編譯那個(即編譯的安排),叫作構建(build)。優化
Make是最經常使用的構建工具,誕生於1977年,主要用於C語言的項目。可是實際上 ,任何只要某個文件有變化,就要從新構建的項目,均可以用Make構建。網站
入門
簡介
Make是一種將源代碼轉換成可執行文件的自動化工具,經過Make語言,描述了源文件、中間文件、可執行文件之間的關係。與此同時,Make工具能夠對編譯過程進行優化,在從新編譯時會根據時間戳來決定哪些文件須要從新生成,在編譯大型工程時,這會省下很多時間(每次第一次編內核都是輸完Make後先睡一覺再說...)。Make有多種變種,其中GNU Make使用相對普遍,在大多Linux/UNIX系統都對其提供支持。ui
Make通常將細節放在Makefile中,make命令會自動在當前文件夾下找到Makefile並執行,而Makefile的核心內容就是規則,它是Makefile的主要組成。每項規則能夠由三部分組成:目標(target),必要條件(prerequisite),命令(command)。書寫格式以下所示,目標和條件之間由冒號隔開,命令寫在下一行,並以TAB開頭,每條規則中能夠有多個目標,多個條件以及多條命令。spa
target1 target2: prereq1 prereq2
command1
command2
tab開頭請別忘記!!命令行
本身寫的案例:翻譯
1 #include "integrate.h"
2
3 float collect(float s,float t,int n,float (*p)(float x)) 4 { 5 int i; 6 float f,h,x,y1,y2,area; 7 f=0.0; 8 h=(t-s)/n; 9 x=s; 10 y1=(*p)(x); 11
12 for(i=1;i<=n;i++) 13 { 14 x=x+h; 15 y2=(*p)(x); 16 area=(y1+y2)*h/2; 17 y1=y2; 18 f=f+area; 19 } 20 return (f); 21 } 22 float fun1(float x) 23 { 24 float fx; 25 fx=x*x-2.0*x+2.0; 26 return(fx); 27 } 28 float fun2(float x) 29 { 30 float fx; 31 fx=x*x*x+3.0*x*x-x+2.0; 32 return(fx); 33 } 34 float fun3 (float x) 35 { 36 float fx; 37 fx=x*sqrt(1+cos(2*x)); 38 return(fx); 39 } 40 float fun4(float x) 41 { 42 float fx; 43 fx=1/(1.0+x*x); 44 return(fx); 45 } 46
47
48 #include <stdio.h>
49 #include <math.h>
50 #include "integrate.h"
51
52 int main() 53 { 54 int n,flag; 55 float a,b,v=0.0; 56
57 printf("Input the count range(from A to B)and the number of sections.\n"); 58 scanf("%f%f%d",&a,&b,&n); 59 printf("Enter your choice: '1' for fun1,'2' for fun2,'3' for fun3,'4' for fun4==>"); 60 scanf("%d",&flag); 61
62 if(flag==1) 63 v=collect(a,b,n,fun1); 64 else if(flag==2) 65 v=collect(a,b,n,fun2); 66 else if(flag==3) 67 v=collect(a,b,n,fun3); 68 else
69 v=collect(a,b,n,fun4); 70 printf("v=%f\n",v); 71 return 0; 72 } 73
74
75 //------------integrate.h------------
76 #ifndef _INTEGRATE_H_ 77 #define _INTEGRATE_H_
78
79 #include <stdio.h>
80 #include <math.h>
81
82
83 float collect( float s, float t, int m, float (*p)(float x) ); 84 float fun1(float x); 85 float fun2(float x); 86 float fun3(float x); 87 float fun4(float x); 88
89 #endif
首先;三個文件都在一個目錄下
兩個C文件,一個h文件。
最簡單的makefile
main: main.o integrate.o gcc integrate.o main.o -o main main.o: main.c integrate.h gcc -c main.c integrate.o: integrate.c integrate.h gcc -c integrate.c
#爲了不這種狀況,能夠明確聲明clean是"僞目標",寫法以下。聲明clean是"僞目標"以後,make就不會去檢查是否存在一個叫作clean的文件,而是每次運行都執行對應的命令。像.PHONY這樣的內置目標名還有很多,
.PHONY: clean
clean:
rm *.o *.exe
點擊make後,顯示以下命令:
gcc -c main.c
gcc -c integrate.c
gcc integrate.o main.o -o main
這個比較簡單。
複雜一點:
#這一章主要對生成規則進行了詳細介紹,主要分爲具體規則、模式規則、靜態模式規則、隱含規則、後綴規則等等。在瞭解這些規則以前,首先了解一些其它的前提知識。
#變量及自動變量
#在Makefile中,使用x,$(xx)。關於變量的使用會在下一章詳細介紹,這裏主要說一下自動變量。自動變量通常用在命令中,會根據目標和條件自動替換成對應的內容。如下是幾個經常使用的自動變量:
#$@ 目標文件名
#$% 檔案文件成員,是指以a.o(b.o)這種形式做爲目標時,括號中的內容
#$< 第一個必要條件文件名
#$? 時間戳在目標文件以後的全部必要條件文件名,空格隔開
#$^ 全部必要條件的文件名,空格隔開,這份列表刪除了重複的文件名
#$+ 和$^同樣,只是未刪除重複的文件名
#$* 目標的主文件名(即不包括後綴)
#以上變量都有兩個變體,加D表示文件的目錄部分,加F表示文件的文件名部分,注意要加括號,如($F)等。
#咱們可使用自動變量來修改以前的Makefile,簡化命令部分的書寫
main: main.o integrate.o
gcc $^ -o $@
main.o: main.c integrate.h
gcc -c $<
integrate.o: integrate.c integrate.h
gcc -c $<
.PHONY: clean all
all:main
clean:
rm *.o *.exe
$<,$@是自動變量,解釋看上面的說明,
all:main能夠在命令行中,等同於make,即make all等同於make。
顯示結果:
gcc -c main.c
gcc -c integrate.c
gcc main.o integrate.o -o main
版本三,更加難一點
CC=gcc
CFLAGS=-I.
DEPS = integrate.h
OBJ = integrate.o main.o
%.o: %.c $(DEPS)
$(CC) $(CFLAGS) -c $< -o $@
main: $(OBJ)
$(CC) $(CFLAGS) $^ -o $@
.PHONY: clean
all:main
clean:
rm *.o *.exe
參考自:http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
Makefile 4
CC=gcc
CFLAGS=-I.
DEPS = hellomake.h
OBJ = hellomake.o hellofunc.o
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
hellomake: $(OBJ)
$(CC) -o $@ $^ $(CFLAGS)
前四行是內置變量,應該不難理解。
模式規則
在gcc編譯器中通常使用後綴表示文件類型,gcc會將x.c文件認爲是C源文件,並翻譯成對應的x.o,這種文件名的對應關係是模式規則的基礎,使得Makefile對於目標x.o會自動去尋找對應的x.c文件,所以對於不少規則,咱們均可以簡化。
在一個規則中,若是主文件名中包含了%就表示這是一個模式規則。所謂模式規則,是指對符合這個模式的目標都採用這個規則,注意%和通配符的不一樣,在Makefile中是可使用通配符的,*.c表示的是全部以c結尾的文件的集合,而%.c表示全部以c結尾的文件都匹配這條規則,必定要注意區分。
全部的內置規則都是模式規則,使用make -p能夠看到這些內置規則,用其中生成%.o的這一條做爲例子
%.o: %.c
#commands to execute (built-in): 這個是註釋
$(COMPILE.c) $(OUTPUT_OPTION) $<
全部c文件結合h文件都要編譯成相應的.o文件
%.o: %.c $(DEPS)
$(CC) $(CFLAGS) -c $< -o $@
版本四:多文件夾管理編譯
將h文件放在include下,將.c文件放在src下,Makefile文件與兩個文件同級,以下所示:
|-- integrate
\-- include
|-- integrate.h
\-- src
|-- integrate.c
|-- main.c
Makefile
#這時候再在InputSpeed目錄下執行make就會報找不到文件的錯誤,解決的方法之一是經過VPATH = src include將源文件加入到Make的搜索路徑中,但這樣並非最好的方法,由於不一樣的文件夾下可能有同名的文件,VPATH只會返回第一個找到的文件,並不必定是咱們想要的文件,咱們可使用vpath pattern directory的形式來指定在哪一個目錄下搜索哪一個文件,具體用法能夠看下面給出的Makefile,其中%相似於通配符,告訴Make在src下找.c文件,在include下找.h文件。如今make已經能夠找到全部的文件了,但還不行,由於gcc命令找不到函數的原型,咱們經過-I命令把頭文件的位置告訴GCC。修改後的Makefile文件以下所示
#VAPTH src include
vpath %.c src
vpath %.h include
CFLAGS = -I include
main: main.o integrate.o
gcc $^ -o $@
main.o: main.c integrate.h
gcc $(CFLAGS) -c $< -o $@
integrate.o: integrate.c integrate.h
gcc $(CFLAGS) -c $< -o $@
.PHONY: clean all
all:main
clean:
rm *.o *.exe
版本五:隱含規則
就是make自帶的內置規則,不是模式規則就是後綴規則。在咱們沒有爲規則編寫命令時,make會自動去內置規則中找是否有對應的規則,上面模式規則中舉的例子就是一個隱含規則,利用該隱含規則,咱們能夠進一步簡化咱們的Makefile,
vpath %.c src
vpath %.h include
CFLAGS = -I include
CC=gcc
main: main.o integrate.o
main.o: integrate.h
integrate.o: integrate.h
.PHONY: clean all
all:main
clean:
rm *.o *.exe
隱含規則的出現,使咱們的Makefile一句命令都沒有用就完成了編譯,也簡潔了不少,實在是十分強大。這個makefile格式真是比較厲害的。
gcc -I include -c -o main.o src/main.c
gcc -I include -c -o integrate.o src/integrate.c
gcc main.o integrate.o -o main