GNU make 总结 (一)
make的执行依赖于一个makefile文件,该文件告诉make应该如何执行编译和链接操作。make通过比较对应文件的最后修改时间来决定哪些文件需要更新。make工具主要用来进行工程编译和程序链接操作。当使用make时,工程中的如下几种文件会被重新编译:
- 所有从未被编译过的源文件
- 执行make后,修改过的源文件
- 执行make后,修改过头文件,则包含该头文件的源文件都需要重新编译
2.1 makefile简介
Target : Prerequisites
command
...
...
Target: 目标
Prerequisites: 依赖
Command: 命令
一条规则可以有command,每个command占一行。command必须以Tab开头。command用于在prerequisites改变后重建target。make程序根据规则的依赖关系来决定是否执行所定义的command,这个过程我们称之为执行规则。
可以使用\来断行,但是\后边不能有空格。
makefile文件中没有依赖项而只有command的目标称为“伪目标”。
执行make时,将执行第一个定义的target。
注意:所有的command行都必须以Tab开始,但并不是所有以Tab开始的行都是command,make把出现在第一条规则之后的所有以Tab开始的行都作为command来处理。
头文件和源文件如下:
1 // benxin.h
void print_benxin(); 4 // benxin.c
#include <stdio.h> void print_benxin()
{
printf("benxin ");
} 12 // tuzi.h
void print_tuzi(); 15 // tuzi.c
#include <stdio.h> void print_tuzi()
{
printf("tuzi !\n");
}
1 // makefile
main : main.o \
benxin.o tuzi.o
gcc -o main main.o benxin.o tuzi.o
main.o : main.c benxin.h tuzi.h
gcc -c main.c
benxin.o : benxin.c benxin.h
gcc -c benxin.c
tuzi.o : tuzi.c tuzi.h
gcc -c tuzi.c
clean :
rm main main.o benxin.o tuzi.o
执行:make
执行:./main
2.2 指定变量
可以指定一个变量表示所有的文件列表,如下:
OBJECTS = main.o benxin.o \
tuzi.o \
使用变量:
main : $(OBJECTS)
gcc –o main $(OBJECTS)
clean :
rm main $(OBJECTS)
2.3 Makefile组成
makefile文件中可能包含以下5个内容:显式规则、隐式规则、变量定义、提示符、注释。
- 显式规则:规则中明确指定目标文件、依赖文件列表、更新目标所需的命令。
- 隐式规则:make程序根据目标文件名自动产生目标依赖文件列表,并使用默认的命令更新目标。
- 变量定义:定义一个变量表示一系列文件列表。
- 指示符:包含文件、条件执行、多行定义。
- 包含文件:include -----> 一个makefile文件中可以使用include包含另一个makefile文件中的内容,其告诉make程序,暂停执行当前makefile,而先去include指定的makefile,然后继续执行。书写include时独立占据一行,但是不能以Tab键开始,格式如下:include FILENAMES...,其中,FILENAMES是shell所支持的文件名,可以使用通配符表示。如果被include的文件中存在变量或者函数,那么将会在包含它们的makefile中被展开。
- include的应用:
<1> 多个不同目录下的makefile文件都使用一组同样的变量或者模式规则,此时可以将这些共性的内容定义在一个文件中,然后在不同的makefile文件中include该文件。
<2> 当根据源文件自动产生依赖时,可以将这些依赖关系保存到一个特定的文件中,然后在makefile文件中include这个特定的文件,这样可以减少错误。
- 注释:用#表示注释,因此如果需要在makefile的非注释行中使用#时,需要加上转义字符\,表示为”\#”。
2.4 makefile文件的指定规则
make程序默认会执行名为makefile或者Makefile的文件。否则需要通过-f或者—file选项来指定makefile文件,具体格式为:-f FILENAME或者—file=FILENAME。当然,也可以直接指定make的目标,只要当前文件夹下存在该目标的依赖文件列表即可。
2.5 MAKEFILES
如果当前环境中定义了MAKEFILES变量,那么make程序执行时,首先将此变量的值作为需要读入的makefile文件。但是区别如下:
MAKEFILES变量指定的makefile文件中的“目标”不会被当作make执行的“终极目标”。
MAKEFILES变量指定的文件列表中的文件是否存在,make都不会提示错误。
make程序执行时,首先读取MAKEFILES变量,然后才是当前工作目录下的makefile文件。
2.6 MAKEFILE_LIST
make程序在读取多个makefile文件时,比如,MAKEFILES变量、命令行、makefile、include等,在对这些文件进行解析之前,make读取到的文件名会被自动加到MAKEFILE_LIST中。如此,我们可以通过判断MAKEFILE_LIST变量的最后一块内容来获取当前make程序正在处理的makefile文件名。
2.7 特殊变量.VARIABLE
make包含一个特殊的变量,不能通过任何途径给它赋值,其被展开后是makefile文件中当前点之前的所有全局变量列表,包括:空变量和make的内嵌变量。
2.8 makefile文件的重载
如果两个makefile文件中拥有相同的目标,但是依赖与规则却不同,此时使用include命令显然行不通。此时需要使用“所有匹配模式 %”。%可以匹配任何一个目标,其依赖项假设为force,而force却使用空命令。这是为了防止make程序试图寻找一个规则去创建目标force时,又使用到% : force,这样就陷入死循环了。
2.9 make解析makefile
<1>依次读取变量MAKEFILES定义的makefile文件列表
<2> 读取当前目录中的makefile文件
<3> 读取当前目录makefile文件中使用的include包含的文件
<4> 查找重建所有已读取的makefile文件的规则
<5> 初始化变量值并展开那些需要立即展开的变量和函数,同时根据预设条件确定执行分支
<6> 根据“终极目标”以及其他目标的依赖关系建立依赖关系链表
<7> 执行除“终极目标”以外的所有的目标规则
<8> 执行“终极目标”更新规则
附注知识点:
编译: |
将高级语言程序转换为机器码的过程,结果为中间目标文件,linux中以后缀名.o标识目标文件。 |
链接: |
将多个.o文件以及库文件链接称为可执行文件。链接器并不检查函数所在的源文件,只检查.o文件中定义的符号,将.o文件中使用的函数和库文件中的函数进行合并,然后对合并后的符号重新排序,并链接上系统相关文件,最终生成可执行程序,Linux中的可执行程序为ELF格式。 |
静态库: |
又名归档文件,其是多个.o文件的集合,库中不同的.o文件之间没有特殊的关系。Linux中静态库后缀名为.a,使用工具ar管理。 |
共享库: |
也是多个.o文件的集合,但是这些.o文件是由编译器按照某种特殊方式生成的。Linux中,共享库格式通常为ELF,即该类型库具备可执行条件。 |
GNU make 总结 (一)的更多相关文章
- 感悟 GNU C 以及将 Vim 打造成 C/C++ 的半自动化 IDE
C 语言在 Linux 系统中的重要性自然是无与伦比.不可替代,所以我写 Linux 江湖系列不可能不提 C 语言.C 语言是我的启蒙语言,感谢 C 语言带领我进入了程序世界.虽然现在不靠它吃饭,但是 ...
- 使用 GCC 和 GNU Binutils 编写能在 x86 实模式运行的 16 位代码
不可否认,这次的标题有点长.之所以把标题写得这么详细,主要是为了搜索引擎能够准确地把确实需要了解 GCC 生成 16 位实模式代码方法的朋友带到我的博客.先说一下背景,编写能在 x86 实模式下运行的 ...
- 在 Linux 中使用 Eclipse 和 Gnu Autotools 管理 C/C++ 项目
在我该系列的之前的所有随笔中,都是采用 Linux 发行版自带的包管理工具(如 apt-get.yum 等)进行软件的安装和卸载,从来没有向大家展示使用源代码自行编译安装软件的方法.但是长期混迹于 U ...
- GNU Readline 库及编程简介
用过 Bash 命令行的一定知道,Bash 有几个特性: TAB 键可以用来命令补全 ↑ 或 ↓ 键可以用来快速输入历史命令 还有一些交互式行编辑快捷键: C-A / C-E 将光标移到行首/行尾 C ...
- GNU Radio Radar Toolbox
GNU Radio Radar Toolbox Install guide Change to any folder in your home directory and enter followin ...
- gnu coreutils-8.25 for win32 static - Beta
gnu.win32-coreutils-8.25.7z 2.7 Mb bc-1.06.tar.gz coreutils-8.25.tar.xz diffutils-3.5.tar.xz gawk-4. ...
- window下搭建c开发环境(GNU环境的安装)
一.在windows平台上安装GNU环境 windows操作系统不自带GNU环境,如果需要开发跨平台的C语言程序,那么需要给windows安装GNU环境 windows下的两款GNU环境:MinGW和 ...
- GNU make使用变量⑤变量的引用、定义等
在 Makefile 中,变量是一个名字(像是 C 语言中的宏),代表一个文本字符串(变量的值).在 Makefile 的目标.依赖.命令中引用变量的地方,变量会被它的值所取代(与 C 语言中宏引用的 ...
- (转)完全用GNU/Linux工作 by 王珢
完全用GNU/Linux工作 王珢 (看完这篇博文,非常喜欢王珢的这篇博客,也我坚定了学gnu/linux的决心,并努力去按照国外的计算机思维模式去学习编程提高自己.看完这篇文章令我热血沸腾 ...
- Gnu/Linux的学习探索
1.Gnu/Linux是一个基于POSIX和UNIX的多用户多任务 支持多线程多CPU的类UNIX的操作系统. 继承了UNIX以网络为核心的设计思想 是性能稳定的多用户网络操作系统. 1991年10月 ...
随机推荐
- TCP/IP详解学习笔记(7)-- 初识运输层
作为TCP和UDP协议的学习前奏,简单的介绍一下运输层的相关内容,方便对TCP,UDP的学习. 1.概述 运输层的任务主要是负责主机中两个进程之间的通信. 运输层的基本功能: 复用 ...
- Android入门之GridView(表格控件)
GridView是一个表格控件,可以在每个单元格中显示自定义的View或者字符串.在这里我们要实现一个图标下方有文字的效果. 1.首先我们应自定义布局文件image_text.xml.代码如下: &l ...
- CSS3之圆角
CSS3圆角border-radius也是比较常用的,有了圆角,可以少很多图片了:) 语法: border-radius : none | <length>{1,4} [/ <len ...
- jenkins smtp设置调试
- WWF3控制流程类型活动<第二篇>
一.顺序工作流 顺序活动是WWF工作流中最基本.最简单的容器类型的活动.顺序活动可以作为很多其他活动的分支. 代码: private void CodeExecute1(object sender, ...
- MFC创建对话框组件对应变量并进行设置值(VS2010)
m_path = strFolderPath; UpdateData(FALSE);
- 从手机获取图片让WebView支持本地上传图片
一,从本地获取相册中的图片,并获取图片的URI 从本地选择图片上传到服务器时,首先要打开本地图片或文件管理器选择要上传的文件,代码如下 Intent intent =newIntent(Intent. ...
- libharu 源码编译 VS2010
最近项目中接过了一个libharu PDF 开源库的锅,哈哈.于是就自己编译了一套libharu 的MFC下的静态库和动态库. 编译libharu需要用到zlib库和libpng库,libpng库又依 ...
- Filestream读取或写入文件
using System.IO;//引用 System.IO namespace filestream { public partial class Form1 : Form { public For ...
- IE中console的正确使用方法
本文出处原文链接 转载请注明出处 http://www.cnblogs.com/havedream/p/4519538.html 问题来源:最近在学习easyui,观看的视频教程是孙宇的<EAS ...