GNU make系列之写Makefile文件(1)

这篇具有很好参考价值的文章主要介绍了GNU make系列之写Makefile文件(1)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.欢迎来到我的酒馆

      在本章节介绍如何写Makefile文件。

二.Makefile包含了什么

      2.1 Makefile包含了5种类型:显式的规则,隐式的规则,变量的定义,指令和注释。变量和指令会在之后的章节介绍。

  • 显式的规则。一个显式的规则表明了如何重新编译一个或多个文件。先决条件列出了target所有依赖的文件,而且同样会提供一个配方用来创建或更新target。

  • 隐式的规则。一个隐式的规则表明了如何重新编译一些文件,一个隐式的规则描述了一个target如何依赖一个文件,并且提供一个配方来创建或更新一个target。

  • 变量的定义。可以对一个变量指定文本字符串,并且在稍后的文本中替换这个文本字符串。

  • 指令。当make程序读取Makefile的时候,根据指令执行特定的操作,这些指令包括:

    • 读取另外一个Makefile文件。
    • 决定是否不执行一部分Makefile。
    • 从包含多行的逐字字符串定义变量。
  • “#” 表示注释所在行。注释行的剩余部分不会被执行。

#这是单行注释。
 
#这是 \
 多行 \
 注释 \

2.2 分割长的行
      Makefile使用基于行的语法,其中换行符是特殊的,用来标记语句的结尾。GNU make对于一行语句的长度没有限制,这取决于你电脑的内存大小。
但是,如果一行语句太长的话,这很难读懂。因此,你可以格式化Makefile,增强Makefile的可读性。可以在换行的末尾加一个 " \ " 反斜杠。
2.3 不添加空格来分割行
      如果你想要拆分一行但不希望添加空格,可以使用一个技巧:用$符号,反斜杠和换行符替换反斜杠。

var := one$\
		word

在make程序移出反斜杠重新组成一行,它和下面的是等效的:

var := one$ word

make程序会执行变量。变量引用 “$” 会引用一个空格符 " " 。给出最终版本,等效于:

var := oneword

2.4 Makefile可以取哪些名字
      默认的,当make程序寻找Makefile的时候,它会按照:GNUmakefile,makefile,Makefile的顺序来找。通常,你可以把Makefile文件叫成makefile或Makefile,但是推荐将使用Makefile这个名字,因为它在罗列的目录列表里更靠前。GNUmakefile这个名字不推荐使用,当一个makefile文件不能被其他版本的make程序执行的时候,你可以将一个makefile文件指定为GNU make。其它版本的make程序只会搜索名字为makefile,Makefile的文件,而不会使用名字为GNUmakefile。
      如果make程序没有找到名字为makefile,Makefile,GNUmakefile,那么make程序不会做任何操作。因此你必须通过使用命令行参数指定一个目标,之后make程序会尝试重新编译。
      如果你想要使用一个不好理解的名字作为Makefile的名字,你可以使用" -f " 或 “–file” 指定特定的Makefile文件。“-f name"或”–file=name" 会告诉make程序把一个文件当成Makefile文件来读取。如果你使用了一个或多个"-f" “–file” 选项,你可以指定多个Makefile文件。所有的Makefile都按指定的顺序有效链接。如果你使用了参数:“-f " 或” --file ",这个时候make程序不会自动检查默认的名字,如makefile,Makefile和GNUmakefile。

当一个Makefile的文件名字,不是makefile、Makefile、GNUmakefile的时候,在当前目录下执行make命令,会报:

make: *** No targets specified and no makefile found.  Stop.

这个时候,你可以使用参数选项:" -f “、” --file "

make -f file_name

make --file=file_name

三.引入其它的Makefile文件

      include指令告诉make程序暂停读取当前的Makefile文件,并读取一个或多个其它Makefile文件,然后再继续。这个include指令在Makefile文件中,如下:

	include filename ...

filename可以是一个shell文件,如果filename是空的,不会引入任何文件且不会打印错误。
      在include指令的开头不能敲tab键,因为如果一行的开头敲了一个tab键,make程序会把这一行当成是一个配方(recipe)。在include和filename之间需要敲一个空格,filename之间也需要敲一个空格,include所在的行的多余的空格不会被执行。"#"符号表示注释一行。
例如,假定你有3个.mk文件,a.mk,b.mk,和c.mk,下面的例子:

include *.mk

等效于:

include a.mk b.mk c.mk

      当make程序执行include指令的时候,它会暂停读取Makefile文件,转而读取每个被引入的文件,当读取引入的文件完成后,make程序会继续在上次暂停的地方读取Makefile文件。
      include指令的一个引用场景是:当有多个不同的应用程序,在不同的目录有不同的Makefile文件需要使用一组共同的变量。另一个应用场景是:当你想要从源文件自动生成先决条件。
      当GNU make在MS-DOS/MS-Windows支持的路径下编译时,如果这个指定的名字不以斜杆(" / “)或盘符( C: )开始,并且这个文件不在当前目录。首先,make程序会从” -I “或” --include-dir " 目录下搜索,然后会按顺序搜索:

prefix/include(/usr/local/include), /usr/gnu/include, /usr/local/include,/usr/include.

下面演示include指令:
继续使用cJSON项目为例子,如果还没有下载,点击这里下载cJSON源程序
下载后解压文件:

tar -zxvf cJSONSourceFiles.tar.gz

进入cJSON目录,文件如下:
GNU make系列之写Makefile文件(1),gnu,服务器
在当前目录新建一个Makefile文件,内容如下:

#include指令用于引入一个文件。
include tmp.mk
#objects=cJSON.o test.o

all: test

test: ${objects}
	cc -W -Wall -o test ${objects} -lm
cJSON.o: cJSON.h

test.o:

.PHONY: clean
clean:
	rm -rf ${objects} test

在目录:

/usr/local/include

下新建一个文件,名为tmp.mk,tmp.mk的内容如下:

objects=cJSON.o test.o

GNU make系列之写Makefile文件(1),gnu,服务器
现在回到cJSON目录,也就是Makefile文件所在的目录,执行命令:

make

输出:

cc    -c -o cJSON.o cJSON.c
cc    -c -o test.o test.c
cc -W -Wall -o test cJSON.o test.o -lm 

      在当前目录下生成了一个可执行文件:test。可以看到在Makefile里使用了include指令,引入了一个文件:tmp.mk,make程序在读取Makefile文件的时候,当读取到include指令的时候,他会去目录 “/usr/local/include” 找 "tmp.mk"文件,并把tmp.mk文件里面的内容导入到Makefile文件中。
      在使用make程序的时候,可以指定要包含的目录:

make -I /usr/local/include
或:
make --include-dir /usr/local/include

      变量:.INCLUDE_DIRS包含了一组目录,这组目录显示了make程序默认会去哪些目录引入文件。通过在执行make程序的时候指定include目录,可以使用选项 “-I”,这样可以避免make程序去默认目录找include文件。如果在默认目录里找不到要包含的文件,这时并不会报错。它会继续处理包含include的makefile文件。当make程序读取makefile文件完成后,make程序会尝试重新编译旧的、需要生成的文件。仅仅在make程序不能在makefile中找到一个执行单元来编译文件的时候,或者找到一个规则时但没有配方,make程序才会判断这个缺失的makefile有错误。
      如果你想让make程序忽略错误,当引入的包含文件不存在时或不能执行重新编译时,可以使用:

-include filenames

例如,当tmp.mk文件不存在时,这时候引入tmp.mk文件,

include tmp.mk

会报:

Makefile:2: tmpq.mk: No such file or directory
make: *** No rule to make target `tmp.mk'.  Stop.

使用 “-include tmp.mk” 就会忽略这个错误。为了和其它版本的make程序兼容,可以使用 “sinclude”。

四.MAKEFILES变量

      如果定义了环境变量MAKEFILES,make程序会把MAKEFILES变量的值看作为一项名字的列表,这些名字使用空格分隔开,这些名字代表了额外的makefile文件,make会首先读取它。这个功能和Include指令很像,它会从不同的目录寻找这些makefile文件。此外,默认目标永远不会从这些makefile中获取,如果罗列在MAKEFILES里的文件没有找到也不会报错。
      MAKEFILES的主要用途是在递归调用make的时候进行通信。通常不希望在顶级调用make之前设置环境变量,因为通常最好不要在外部把makefile搞混淆。然而,如果你在运行make程序的时候没有指定makefile文件,MAKEFILES里罗列的makefile文件在内置隐式规则很有用,例如定义搜索路径。
      一些用户会尝试着在登录的时候自动设置MAKEFILES环境变量。make程序会按照预期的步骤执行。但是这并不是一个好的解决方案,因为如果makefile文件是由其它人运行的话,他将会失效。因此在makefile文件里写include指令会更好。
      这里出现了一个问题,在Makefile文件里写了MAKEFILES变量,make程序把MAKEFILES当成了一个普通的变量,并没有去读取MAKEFILES里面指定要读取的文件:

MAKEFILES= tmp1.mk

在这里,写上上面的一句代码,make程序并不会读取tmp1.mk文件,而是把这行代码看成了一个变量的声明。这和上面讲的行不通了。现在还不知道原因是什么。

五.如何重新制作Makefile

      有时,Makefile可以从其它的文件,例如RCS和SCCS文件被重新制作。如果一个Makefile可以从其它的文件被重新制作,你可能想要make程序获取一个makefile的最新版本用来读取。
      出于这层目的,make程序在读取完所有的Makefile文件之后,它会将每一个读取的makefile都看成是一个target,按照它们被处理的顺序,并且尝试去更新它。如果开启了并行构建,则makefile也将并行构建。
      如果makefile有一个如何更新的规则,如果必要的话,它将会更新。在所有的makefile已经被检查过了,如果有任何地方被修改过了,make将会从头开始并且重新读取所有的makefile,每一次重新读取都会导致特殊变量MAKE_RESTARTS更新。
      如果你知道你的一个或多个makefile无法重新制作,并且你希望避免make对它们执行隐式规则搜索。可能出于执行效率的原因,你可以使用任何防止隐式规则查找的常规方法来执行此操作。例如,你可以在makefile里写一个显示的规则来作为目标,并且将配方置为空。
      如果makefile指定了一个双冒号的规则用来重新制作一个文件,这个规则有配方,但没有先决条件,这样的makefile文件总是会被重新制作。在这种情况下的makefile,有一个双冒号的规则,但没有写先决条件,每当make程序运行的时候它总是会被重新制作,在make程序执行结束后,make程序又会再次读取makefile,这会造成一个死循环,make程序会不停地重新制作makefile并且重新启动,不会做任何别的事情。因此,为了避免这种情况,当一个target有双冒号并带有配方但没有写先决条件的时候,make程序将不会重新制作makefile。
      phony target有同样的效果。当一个文件被标记为phony的时候将会导致make程序不停地重启。为了避免这种情况,当makefile文件被标记为phony,make程序不会尝试着重新制作makefile。
      借助这个优点,可以优化make程序地启动时间。如果你知道你的makefile不必重新制作,你可以防止make程序尝试重新制作通过添加:

.PHONY: Makefile

或者:

Makefile:: ;

      如果没有使用参数 “-f” 或 “–file” 指定任何需要读取的makefile,make程序将会尝试读取默认的makefile名字文章来源地址https://www.toymoban.com/news/detail-684024.html

到了这里,关于GNU make系列之写Makefile文件(1)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [SDR] GNU Radio 系列教程(十四) —— GNU Radio 低阶到高阶用法的分水岭 ZMQ 的使用详解

    目录 1、前言 2、ZMQ 块的类型 3、ZMQ 块的使用 4、DEMO 4.1 同一台电脑上的两个流程图 4.2 不同电脑上的两个流程图 4.3 作为 REQ/REP 服务器的 Python 程序 4.4 作为 PUSH/PULL 服务器的 Python 程序 4.5 处理流程图数据的 Python 程序 参考链接 学会使用 GNU Radio 中的 ZMQ,是从低阶使用者向高阶

    2023年04月26日
    浏览(37)
  • 【ARM 嵌入式 编译系列 10.3 -- GNU elfutils 工具小结】

    请阅读 【ARM GCC 编译专栏导读】 上篇文章:【ARM 嵌入式 编译系列 10.2 – 符号表与可执行程序分离详细讲解】 下篇文章:【ARM 嵌入式 编译系列 11 – GCC attribute ((packed))详细介绍】 GNU elfutils是一个开源的工具集,用于处理 ELF (Executable and Linkable Format)格式的可执行文件、

    2024年02月13日
    浏览(52)
  • [QT编程系列-33]:科学计算 - 开源数值计算库GNU Scientific Library(简称GSL)

    目录 第1章 简介 1.1 概述 1.2 主要功能 1.3 C++接口 1.4 在QT中使用GSL的步骤 第2章 GSL C++函数库 2.1 功能概述 2.2 代码示例 GNU Scientific Library(简称GSL)是一个开源数值计算库,旨在提供各种数学和科学计算的功能。它用于解决 数学、物理、工程和计算科学中的复杂问题,并提供了

    2024年02月11日
    浏览(42)
  • 【Linux】使用Bash和GNU Parallel并行解压缩文件

    在本教程中,我们将学习如何使用Bash脚本和GNU Parallel实现高效并行解压缩多个文件。这种方法在处理大量文件时可以显著加快提取过程。 先决条件 确保系统上已安装以下内容: Bash GNU Parallel 你可以使用以下命令在不同Linux系统上安装它们: 在Ubuntu上安装 在CentOS上安装 想象

    2024年02月04日
    浏览(41)
  • 【Linux系列P6】自动化构建工具-make/Makefile详解

     前言 大家好吖,欢迎来到 YY 滴 Linux系列 ,热烈欢迎! 本章主要内容面向接触过Linux的老铁,主要内容含 欢迎订阅 YY 滴Linux专栏!更多干货持续更新!以下是传送门!  订阅专栏阅读:YY的《Linux》系列 ❀❀❀❀❀ 【Linux系列-P1】 Linux环境的搭建 【Linux系列-P2】Linux的基本知

    2024年02月16日
    浏览(38)
  • Linux系统下cpython-37m-x86_64-linux-gnu.so文件ImportError

    ) 在查找答案的过程中遇到了几种回答,大多评论都表示有用 库的版本不兼容 多数遇到的是这种,但因为库比较难发现哪个不匹配等等原因,继续寻找其它回答…(当然,如果出现numpy或是pillow库的问题,还是及时解决比较好) 我运行的是UA-CMDet,如果有类似的可以作为简单

    2024年02月19日
    浏览(44)
  • 【闪击Linux系列P6】自动化构建工具-make/Makefile详解

     前言 大家好吖,欢迎来到 YY 滴 Linux系列 ,热烈欢迎! 本章主要内容面向接触过Linux的老铁,主要内容含 欢迎订阅 YY 滴Linux专栏!更多干货持续更新!以下是传送门!  订阅专栏阅读:YY的《Linux》系列 ❀❀❀❀❀ 【Linux系列-P1】 Linux环境的搭建 【Linux系列-P2】Linux的基本知

    2024年02月13日
    浏览(39)
  • 00.嵌入式笔记——初识make工具和Makefile文件

    make是解决大工程编译的工具,描述哪些文件需要编译、哪些需要重新编译的文件就叫做 Makefile,Makefile 就跟脚本文件一样,Makefile 里面还可以执行系统命令。我们使用的时候只需要一个make命令即可完成整个工程的自动编译,极大的提高了软件开发的效率。 Makefile 的引入 如果

    2024年02月08日
    浏览(50)
  • Linux gpg命令(gpg指令、gpg加密工具)(GNU Privacy Guard、GnuPG)文件压缩加密、文件加密、文件解密、文件压缩密码、解压密码、GPG密钥、数字签名、非对称加密

    GNU Privacy Guard (GnuPG或GPG) 是一个完全免费的开源实现,用于OpenPGP标准的数据加密和解密。这种加密方式可以用于保护敏感数据,确保其在传输过程中不被截获或篡改。本文将介绍在Linux环境中如何使用GPG加密工具。 安装gpg 在大多数Linux发行版中,GPG已经预先安装了。 如果未安

    2024年02月03日
    浏览(86)
  • GNU Tools使用笔记

    选项 作用 -Og 优化调试体验 -Wall选项 作用:使能所有的警告。 -g选项 作用:生成操作系统原生格式的调试信息,GDB能够与这些调试信息协同工作。 -gdwarf-version选项 作用:生成DWARF格式的调试信息。 示例:-gdwarf-2。 -c选项 作用:指示编译器仅编译或汇编源文件,但不进行链

    2024年02月02日
    浏览(68)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包