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开头请别忘记!!

自己写的案例:

 #include "integrate.h"

 float collect(float s,float t,int n,float (*p)(float x))
{
int i;
float f,h,x,y1,y2,area;
f=0.0;
h=(t-s)/n;
x=s;
y1=(*p)(x); for(i=;i<=n;i++)
{
x=x+h;
y2=(*p)(x);
area=(y1+y2)*h/;
y1=y2;
f=f+area;
}
return (f);
}
float fun1(float x)
{
float fx;
fx=x*x-2.0*x+2.0;
return(fx);
}
float fun2(float x)
{
float fx;
fx=x*x*x+3.0*x*x-x+2.0;
return(fx);
}
float fun3 (float x)
{
float fx;
fx=x*sqrt(+cos(*x));
return(fx);
}
float fun4(float x)
{
float fx;
fx=/(1.0+x*x);
return(fx);
} #include <stdio.h>
#include <math.h>
#include "integrate.h" int main()
{
int n,flag;
float a,b,v=0.0; printf("Input the count range(from A to B)and the number of sections.\n");
scanf("%f%f%d",&a,&b,&n);
printf("Enter your choice: '1' for fun1,'2' for fun2,'3' for fun3,'4' for fun4==>");
scanf("%d",&flag); if(flag==)
v=collect(a,b,n,fun1);
else if(flag==)
v=collect(a,b,n,fun2);
else if(flag==)
v=collect(a,b,n,fun3);
else
v=collect(a,b,n,fun4);
printf("v=%f\n",v);
return ;
} //------------integrate.h------------
#ifndef _INTEGRATE_H_
#define _INTEGRATE_H_ #include <stdio.h>
#include <math.h> float collect( float s, float t, int m, float (*p)(float x) );
float fun1(float x);
float fun2(float x);
float fun3(float x);
float fun4(float x); #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

  

makefile学习(1)的更多相关文章

  1. [转]Windows平台下Makefile学习笔记

    Windows平台下Makefile学习笔记(一) 作者:朱金灿 来源:http://blog.csdn.net/clever101 决心学习Makefile,一方面是为了解决编译开源代码时需要跨编译 ...

  2. makefile 学习归纳

    makefile 学习归纳 一直希望 好好整理下 makefile的写法,这在linux编程界是必备技能.下面就好好的说道说道. 可以参考的大神总结 整理 makefile是供make命令执行的 脚本 ...

  3. <转>Windows平台下Makefile学习笔记(二)

    本文转自:http://blog.csdn.net/clever101/article/details/8286066 上次我们学习了怎么用Makefile编译一个控制台工程.这次我们学习一下如何使用 ...

  4. (二)我的Makefile学习冲动&&编译过程概述

    前言 一 年轻的冲动 二 学习曲线 1 Makefile基本语法 2 bash基础 3 world 三 编译过程概述 1 主机预装工具 2 编译host工具 3 编译交叉工具链 4 编译内核模块 5 ...

  5. Makefile学习笔记

    ls -l 查看文件详细信息 1.gcc -E test.c -o test.i//预编译gedit test.i //查看:高级C 2.gcc -Wall -S test.i -o test.s// ...

  6. makefile学习笔记(多目录嵌套调用、变量使用)

    http://blog.csdn.net/leexiang_han/article/details/9274229   学习了几天的makefile的嵌套调用编写也有一些心得,先声明,我也是初学者写文 ...

  7. Makefile学习(一)变量

    鉴于之前有一些了解,还有自己的学习习惯,我一上来就看Makefile的变量这一章.主要脉络是根据GNU make中文手册. 第六章:Makefile中的变量 6使用变量 定义:变量是一个名字,代表一个 ...

  8. makefile 学习一

    近期在学习nginx,由于实在linux下,一些代码须要用makefile文件来编译,比較节省时间. 由于在nginx中加入一个新的模块假设用./configure方法来加入,特别是当你的代码有错时, ...

  9. Makefile学习总结

    Makefile用法分析     在linux开发中,应用程序的编译基本都采用GNU的make工具,而make搭配Makefile来实现工程代码的编译,在越是大型复杂的项目中,make的强悍之处越是明 ...

随机推荐

  1. Python踩坑之旅其一杀不死的Shell子进程

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 坑后扩展 1.4.1 扩展知识 1.4.1 技术关键字 1.5 填坑总结 1.1 踩坑案例 踩坑的程序是个常驻的Agent类管理进程 ...

  2. pat1079. Total Sales of Supply Chain (25)

    1079. Total Sales of Supply Chain (25) 时间限制 250 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHE ...

  3. 利用Java程序将字符串进行排序与拼接

    1.初始生成字符串的代码程序: package com.map.test; import java.util.ArrayList; import java.util.Collections; impo ...

  4. <checking for mysql_config not found>

    php 5.3.29编译安装排错: ./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --w ...

  5. 关于node中的板块问题

    最近自己在看node实战那本书,不过发现有一些书上不对的地方,罗列如下:1.connect服务自己有一些中间件可供使用,但是书上说的有cookie-parser.logger.favicon和body ...

  6. C#之razor

    学习的文章在这里:http://www.cnblogs.com/yang_sy/archive/2013/08/26/ASPNET_MVC_RAZOR_ENGINE.html 1.视图开始文件_Vie ...

  7. 将表格table作为execl导出

    有时候的需求是从后台获取数据,然后将数据变成execl,进行导出,下载成execl 解决的方法是 一,比较方便的是 这有个插件 可以直接用 https://www.npmjs.com/package/ ...

  8. pat乙级1059

    1.c++ 位数不够前面补零: printf("04d", i); 位数不够前面补空格(右对齐): printf("4d", i); 位数不够后面补空格(左对齐 ...

  9. UVA Live Achrive 4327 Parade (单调队列,dp)

    容易想到dp[i][j]表示在第i行j个路口的开始走最大高兴值. 每次可以向左走,或者向右边走,然后向北走.(或者直接往北) 向左走到,状态转移为dp[i][j] = dp[i][k] + happy ...

  10. Scanner和 Random类,控制语句的例题,商品管理(直接赋值)

    Scanner类的使用: import java.util.Scanner; class Demo02 { public static void main(String[] args) { //1.导 ...