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