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

news2024/11/15 16:03:02

一.欢迎来到我的酒馆

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

目录

    • 一.欢迎来到我的酒馆
    • 二.Makefile包含了什么
    • 三.引入其它的Makefile文件
    • 四.MAKEFILES变量

二.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目录,文件如下:
在这里插入图片描述
在当前目录新建一个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

在这里插入图片描述
现在回到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 `tmpq.mk'.  Stop.

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

四.MAKEFILES变量

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/947987.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

There is already ‘xxxController‘ bean method的解决方法

报这个错的原因是因为你controller里的RequestMapping中的路径有重复!

嵌入式linux设备网口带宽-测试方法

iperf是一个基于Client/Server的网络性能测试工具,可以测试TCP、UDP和SCTP带宽质量,能够提供网络吞吐率信息,以及震动、丢包率,最大段和最大传输单元大小等统计信息,帮助我们测试网络性能,定位网络瓶颈。其…

keil5 报错no target connected

场景:用ST_Link V2 在 keil5 中下载stm32程序 原因:线路连接错误 正确连接 注意:江科大stm32和stlink的接线,一定要对齐,我买的一个不是按照顺序接线的,需要仔细查看

Arduino程序设计(五)按键中断+按键状态检测

按键中断按键状态检测 前言一、按键中断1、中断的基本概念2、外部中断3、示例代码4、按键中断实验 二、按键状态检测1、按键单击、双击和长按的工作原理2、按键状态检测实验 参考资料 前言 本文主要介绍两种按键检测实验,分别是:1、外部中断实现按键控制…

SQL-DQL

-----分组查询----- 1.语法: SELECT 字段列表 FROM 表名 [WHERE 条件 ] GROUP BY 分组字段名 [HAVING 分组后过滤条件]; 2.where与having区别 》执行时机不同:where是分组之前进行过滤,不满足where条件,不参与分组&…

docker常见面试问题详解

在面试的时候,面试官常常会问一些问题: docker是什么,能做什么?docker和虚拟机的区别是什么呢?docker是用什么做隔离的?docke的网络类型?docker数据之间是如何通信的?docker的数据保…

阿里云申请免费SSL证书的两种验证方式及配置服务器Tomcat升级HTTPS协议

通用教程,其他服务商的免费 SSL 证书也差不多是这个流程。(至少腾讯云的操作步骤和本文是一致,嘻嘻!) 申请 SSL 证书 首先在阿里云上创建并申请 SSL 证书,之后选择 DNS 验证的方式,一种是手动配…

读word模板批量生成制式文件

文章目录 1、Maven依赖2、.docx或.doc格式的word模板准备3、读word模板,批量替换代码域,生成文件,demo4、结果展示1、Maven依赖 <dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.core</artifactI…

在Linux系统中设置动态地址进行网络访问

在 Linux 系统中&#xff0c;配置动态地址可以帮助我们实现更安全、匿名或绕过某些限制的网络访问。本文将介绍几种常用的方法来配置和使用代理服务器&#xff0c;在 Linux 环境下轻松实现高效且可靠地通过HTTP进行网络访问。 1、使用环境变量设置 HTTP/HTTPS 在命令行界面执行…

洗地机选购指南!洗地机推荐

在清洁这件事情上&#xff0c;大多数人会选择先扫地再拖地&#xff0c;为了让大家高效的完成扫地和拖洗这件事情&#xff0c;许多清洁家居的厂家开始研究和思考&#xff0c;怎样让大家可以解放双手&#xff0c;提高效率呢。这时洗地机出现了&#xff0c;它帮助我们在清洁上面解…

如何写一个外设驱动?

我的圈子&#xff1a; 高级工程师聚集地 我是董哥&#xff0c;高级嵌入式软件开发工程师&#xff0c;从事嵌入式Linux驱动开发和系统开发&#xff0c;曾就职于世界500强企业&#xff01; 创作理念&#xff1a;专注分享高质量嵌入式文章&#xff0c;让大家读有所得&#xff01; …

AI聊天机器人平台Poe发布更新;自然语言理解课程概要

&#x1f989; AI新闻 &#x1f680; AI聊天机器人平台Poe发布更新 突破功能限制 增加企业级服务 摘要&#xff1a;知名问答网站Quora旗下的AI聊天机器人平台Poe发布了一系列更新&#xff0c;包括推出Mac应用、支持同时进行多个对话、接入Meta的Llama 2模型等功能。用户只需支…

通过HTTP进行并发的数据抓取

在进行大规模数据抓取时&#xff0c;如何提高效率和稳定性是关键问题。本文将介绍一种可操作的方案——使用HTTP代理来实现并发的网页抓取&#xff0c;并帮助您加速数据抓取过程。 1. 选择合适的HTTP代理服务供应商 - 寻找信誉良好、稳定可靠且具备较快响应时间的HTTP代理服务…

[递归] 自然数分解之方案数

一种递归式的非零自然数全分解方法_Weiming Chen的博客-CSDN博客 简单来说&#xff0c;就是单调不减&#xff0c;后一个数大于等于前一个数 像这样&#xff0c;那么我们只需给定前一个数和后一个数就可以进行递归操作 #include <cstdio> #include <algorithm> #i…

为什么海外专利申请含金量高?

为什么海外专利申请含金量高&#xff1f;通常&#xff0c;具有较大市场价值的发明才需要在国外申请专利保护&#xff0c;专利的海外申请数量是衡量经济和创新价值的重要指标&#xff0c;即专利全球性指标。我国海外专利申请量比重过低&#xff0c;说明专利的创造性未达到国外专…

2023年的今天,PMP项目管理认证还值得考吗?

首先我肯定它值得考&#xff0c;PMP认证的教材和考纲都会随着项目管理工具和市场趋势而更新&#xff0c;不用担心会过时。 PMP项目管理认证是什么&#xff1f; 英文全称是Project Management Professional&#xff0c;中文全称叫做项目管理专业人士资格认证。它是由美国项目管…

【docker】容器的运行、停止、查看等基本操作

容器与镜像的区别 image镜像 Docker image是一个read-only文件&#xff0c;位于磁盘上这个文件包含文件系统&#xff0c;源码&#xff0c;库文件&#xff0c;依赖&#xff0c;工具等一些运行application所需要的文件可以理解成一个模板docker image具有分层的概念 container…

【深入MaxCompute】人力家:用MaxCompute 事务表2.0主键模型去重数据持续降本增效

简介&#xff1a; MaxCompute新增Transaction Table2.0&#xff08;下文简称事务表2.0)表类型在2023年6月27日开始邀测&#xff0c;支持基于事务表2.0实现近实时的增全量一体的数据存储、计算解决方案。 作者&#xff1a; 石玉阳 人力家 高级数据研发工程师 业务简介 人力家…

【高阶产品策略】认识策略产品

文章目录 1、策略产品概述2、策略产品搭建流程3、如何成为一名策略产品经理 1、策略产品概述 2、策略产品搭建流程 3、如何成为一名策略产品经理

地铁+铁路系统防雷接地应用解决方案

地铁作为城市轨道交通的一种&#xff0c;是一种高效、安全、环保的公共交通方式。然而&#xff0c;地铁也面临着雷电灾害的威胁&#xff0c;尤其是在雷暴多发的地区。 雷电对地铁系统的影响主要有以下几个方面&#xff1a; 直接雷击&#xff1a;雷电直接击中地铁系统的设备或…