博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
makefile学习(1)
阅读量:4708 次
发布时间:2019-06-10

本文共 6466 字,大约阅读时间需要 21 分钟。

 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来源:简书简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

  

今天学习了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系统都对其提供支持。

Make一般将细节放在Makefile中,make命令会自动在当前文件夹下找到Makefile并执行,而Makefile的核心内容就是规则,它是Makefile的主要组成。每项规则可以由三部分组成:目标(target),必要条件(prerequisite),命令(command)。书写格式如下所示,目标和条件之间由冒号隔开,命令写在下一行,并以TAB开头,每条规则中可以有多个目标,多个条件以及多条命令。

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 
49 #include
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 else69 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
80 #include
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 mainmain.o: main.c integrate.h     gcc -c main.cintegrate.o: integrate.c integrate.h     gcc -c integrate.c

 

#为了避免这种情况,可以明确声明clean是"伪目标",写法如下。声明clean是"伪目标"之后,make就不会去检查是否存在一个叫做clean的文件,而是每次运行都执行对应的命令。像.PHONY这样的内置目标名还有不少,

.PHONY: clean
clean:
rm *.o *.exe
点击make后,显示如下命令:

gcc -c main.cgcc -c integrate.cgcc 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 $

  

$<,$@是自动变量,解释看上面的说明,

all:main可以在命令行中,等同于make,即make all等同于make。

显示结果:

 

gcc -c main.cgcc -c integrate.cgcc main.o integrate.o -o main

 

 版本三,更加难一点 

CC=gccCFLAGS=-I.DEPS = integrate.hOBJ = integrate.o main.o%.o: %.c $(DEPS)    $(CC) $(CFLAGS) -c $< -o $@main: $(OBJ)    $(CC) $(CFLAGS) $^ -o $@.PHONY: cleanall:mainclean:rm *.o *.exe

 参考自:http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/

Makefile 4

CC=gccCFLAGS=-I.DEPS = hellomake.hOBJ = 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 includevpath %.c srcvpath %.h includeCFLAGS = -I includemain: 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 allall:mainclean:rm *.o *.exe

  

版本五:隐含规则

就是make自带的内置规则,不是模式规则就是后缀规则。在我们没有为规则编写命令时,make会自动去内置规则中找是否有对应的规则,上面模式规则中举的例子就是一个隐含规则,利用该隐含规则,我们可以进一步简化我们的Makefile,

vpath %.c srcvpath %.h includeCFLAGS = -I includeCC=gccmain: main.o integrate.omain.o: integrate.hintegrate.o: integrate.h.PHONY: clean allall:mainclean:rm *.o *.exe

隐含规则的出现,使我们的Makefile一句命令都没有用就完成了编译,也简洁了很多,实在是十分强大。这个makefile格式真是比较厉害的。

 

gcc -I include   -c -o main.o src/main.cgcc -I include   -c -o integrate.o src/integrate.cgcc   main.o integrate.o   -o main

 

  

 

转载于:https://www.cnblogs.com/CodeWorkerLiMing/p/10890817.html

你可能感兴趣的文章
SQLite3 安装、基本操作
查看>>
MSIL解析一(转)
查看>>
redis-cluster
查看>>
eclipse常用快捷键整理
查看>>
android context详解
查看>>
Android 4.4 外置卡
查看>>
Lua 模块引入中 import 和 require 的差异
查看>>
js模块加载详解
查看>>
.net别样外观控件包DotNetBar
查看>>
C++ 对象间通信框架 V2.0 ××××××× 之(二)
查看>>
js禁止原生手机返回键(物理返回键)
查看>>
接口测试的两种方法(转自 http://www.blogjava.net/qileilove/archive/2012/05/31/379631.html )...
查看>>
20172328《程序设计与数据结构》第七周学习总结
查看>>
Android中内容观察者的使用---- ContentObserver类详解
查看>>
统计图表--第三方开源--MPAndroidChart(一)
查看>>
Leetcode: Multiply Strings
查看>>
java获取登录用户ip地址
查看>>
Tomcat安装与使用
查看>>
Java课程总结
查看>>
android如何用adb shell启动应用程序
查看>>