相信大家在使用Linux环境编程的时候,一定接触过Makefile这个玩意。Makefile在搭建自定义的编译环境,尤其是自动化编译、多功能一键编译等功能上,还是发挥了很大的作用。如果接触过Linux内核编译的童鞋,一定会看到编译内核中的各级Makefile中,有很多地方都会有 FORCE 这样的字段出现,那么这个 FORCE 究竟是何方神圣呢?本文将给你答案,通过阅读本文,你讲了解到以下内容:

  • Makefile的基本规则
  • FORCE 在Makefile的含义
  • FORCE在实际工程中的应用

Makefile的基本规则


Makefile的基本形式如下所示:

TARGET : DEPENDENCESCMD# TARGET:生成的目标,可以是一个文件,也可以是一个虚拟符号(非真实文件)
# DEPENDENCES: 生成目标的所有依赖,它是一个集合,可以只有一个文件,或者很多文件;也可以是虚拟符号
# CMD:把所有依赖生成目标的执行命令,其中CMD前面是一个TAB键,而不能是空格

Makefile的基本规则,归纳起来就是一句话:【当一个TARGET (欲生成的目标)比它的任何一个DEPENDENCES(依赖的文件)旧时,这个TARGET就要重新生成】。

这句话读起来很简单,就是Makefile在执行编译的时候,会先去判断TARGET和其依赖文件的时间,如果TARGET的时间比较旧,意味着依赖文件有更新了,所以TARGET要重新生成;反之,如果TARGET的时间比较新,意味着在TARGET生成后,依赖文件是没有改变过的,自然就不用重新去生成TARGET。


FORCE 在Makefile的含义


有了上一小节中介绍的Makefile基本概念后,我们来进一步分析下Makefile中的FORCE,以下是FORCE在Makefile中出现的最简化版本:

file = test.txtall: generate-a-filegenerate-a-file: $(file) $(file):@echo "Force to generate a test file for every make ..."rm -rf $(file) && echo `date "+%Y-%m-%d %H:%M:%S"` > $(file)FORCE:
.PHONY: FORCE

这个Makefile不是用于真正的编译工程,而是提供一个很简单的功能,生成一个test.txt,并且这个test.txt的内容是记录每次编译的时间。但是使用这个makefile执行make时,发现只有第一次make的时候,才会生成test.txt,而其他时候只要test.txt还存在都不会重新生成,如下所示:

很明显,它没有达到我们期望的“每次编译都重新生成test.txt”。这个时候 FORCE 就发挥作用了,我们在 test.txt目标的后面添加 FORCE作为它的依赖试试看,即如下所示:

file = test.txtall: generate-a-filegenerate-a-file: $(file) $(file): FORCE  #FORCE表示每次这段都要执行@echo "Force to generate a test file for every make ..."rm -rf $(file) && echo `date "+%Y-%m-%d %H:%M:%S"` > $(file)FORCE:
.PHONY: FORCE

执行输出如下所示: 我们可以看到,这达到了我们的目的,每次test.txt都是重新生成了,它记录了每次make的时间。

这个就是要归功于 FORCE 的功劳了。我们来分析下,为何加了 FORCE 就能实现这样的功能。

我们可以注意到FORCE这个目标,它的DEPENDENCES是空的,CMD部分也是空的;这个比较特殊了,在Makefile里,像这样依赖为空、执行命令也为空的TARGET,则需要每次都重新生成,而这个TARGET不一定是一个文件,可以是任意的符号,而 FORCE 只是我们最常用的符号,理论上它可以换成任意符号,比如NO-FORCE、SOMETHING等等。


FORCE在实际工程中的应用


上一小节,我们讲到可以用Makefile配合shell命令来自动生成一些文件,自然我们很容易想到,在我们实际的编译工程中,往往需要动态生成一些配置项,然后嵌入到代码中,比如编译版本号、编译时间等。

假设我们有以下一个main.c:

#include <stdio.h>
#include "build_info.h"  #这个头文件需要每次编译时自动生成int main(int argc, const char *argv[])
{printf("%s >>> APP_TIME=%s\n", __func__, APP_TIME);return 0;
}

示例代码很简单,就是再main函数中打印一个 build_info.h中的一个宏定义APP_TIME,这个build_info.h要求每次编译的时候都重新生成。我们给出的Makefile示例如下:

##拷贝时,注意tab键
SHELL           = /bin/bash #指定shell使用/bin/bash,否则echo -e可能会出问题
ECHO            = echo
BIN             = test
BUILG_INFO_H    = build_info.h
SRC-C-y         = main.c
SRC-O           = $(patsubst %.c, $(O)%.o, $(SRC-C-y))all: gen_build_info $(BIN)$(BIN) : $(SRC-O)gcc -o $(O)"$@" $(SRC-O)%.o : %.cgcc -c "$<" -o "$@"gen_build_info: $(BUILG_INFO_H)$(BUILG_INFO_H): FORCE     #强制生成build_info.h@$(RM) $@@$(ECHO) '  GEN     $@'@$(ECHO) -e   " #ifndef __BUILD_INFO_H__\n"\"#define __BUILD_INFO_H__\n"\"#define APP_TIME          \"`date "+%Y-%m-%d %H:%M:%S"`\"\n"\"#endif"  > $@FORCE:
.PHONY: FORCE

make执行输出测试如下:

从输出的测试,我们可以看出,make的每次执行都触发了生成build_info.h,但是运行编译出来的test可执行程序,我们发现并不是每次生成的build_info.h的内容都传递到了test里面;也就是当build_info.h改变的时候,test没有被重新编译。这里先留下点疑问,为何会产生这样的问题。博主将会在后续的文章中解决这个问题。


不管怎么样,经过对上文的学习,我们至少掌握了 FORCE的基本用法,而在实际项目工程中,我们也见证了它的威力;那么,你学会了吗?如果还有疑问,欢迎在评论席提出你的问题和看法,博主定会尽力解决你的困惑。

版权申明:本文为博主原创文章,转载请注明出处!【Linux + Makefile】十分钟教你学会Makefile的FORCE_架构师李肯-CSDN博客

原创作者:recan

电子邮箱:recan.szu@foxmail.com


延伸阅读:

【Linux + Makefile】Makefile的高阶用法:解决C文件包含的头文件修改了,但C文件不重新编译的问题

【Linux + Makefile】十分钟教你学会Makefile的FORCE相关推荐

  1. 一分钟教你学会python_十分钟教你学会python编写小游戏

    原标题:十分钟教你学会python编写小游戏 看过,估计大家都已经精通了吧,好的,话不多说,今天就活学活用,用python来编写纸牌游戏21点,江湖人称黑杰克,BLACK JACK-(注意法式卷舌). ...

  2. python编写小游戏17_十分钟教你学会python编写小游戏

    原标题:十分钟教你学会python编写小游戏 看过,估计大家都已经精通了吧,好的,话不多说,今天就活学活用,用python来编写纸牌游戏21点,江湖人称黑杰克,BLACK JACK-(注意法式卷舌). ...

  3. origin做相关性分析图_高分文章的相关性热图,十分钟教你学会无代码复现

    相关性热图可以便捷的显示多个变量之间的相关性,因此在组学数据分析中得到广泛应用,例如基因的共表达分析.样本重复检验.微生物群落的共发生网络分析等. 在昨天推文下就有人问热图怎么画?画热图最常规的办法自 ...

  4. 十分钟教你学会打包APP

    我们打包APP需要用到HBuilder,所以先讲解如何安装使用 HBuilder的下载与安装 HBuilder的官网下载地址:https://www.dcloud.io/ 点击DOWNLOAD后会弹出 ...

  5. 十分钟教你开发EOS智能合约

    十分钟教你开发EOS智能合约 在CSDN.柏链道捷(PDJ Education).HelloEOS.中关村区块链产业联盟主办的「EOS入门及最新技术解读」专场沙龙上,柏链道捷(PDJ Educatio ...

  6. 十分钟教你配置frp实现内网穿透

    十分钟教你配置frp实现内网穿透 一.frp的作用 利用处于内网或防火墙后的机器,对外网环境提供 http 或 https 服务. 对于 http, https 服务支持基于域名的虚拟主机,支持自定义 ...

  7. java连接数据库 oracle,Oracle数据库之一分钟教你学会用java连接Oracle数据库

    本文主要向大家介绍了Oracle数据库之一分钟教你学会用java连接Oracle数据库,通过具体的内容向大家展现,希望对大家学习Oracle数据库有所帮助. package java_jdbc; // ...

  8. 元件怎么反转_电气图纸怎么看?三分钟教你学会看懂,受用一生

    图纸一般用于设计方面,设计师绘制出图纸,我们再根据图纸进行操作,尤其是电气图纸,上面有很多符号,很难看懂,下面通过三分钟教你学会看懂电气图纸. 一.什么是电气图 用电气图形符号.带注释的围框或简化外形 ...

  9. python批量删缩进_鬼畜小姐姐+野狼disco,十分钟教你如何用Python剪辑一个牛逼的抖音小视频?...

    鬼畜小姐姐+野狼disco,十分钟教你如何用Python剪辑一个牛逼的抖音小视频? 前言 半个月前,后台有个小伙伴问我,如何将视频中的音频提取出来,并且将声音转成文字写入到 word 中,正好接下来的 ...

最新文章

  1. torch量化其他功能(量化、反量化)
  2. python project_GitHub - DeqianBai/Python-Project: A series of python projects
  3. js字符串的各种格式的转换 ToString,Format
  4. 盯紧那群养生的年轻人,他们的焦虑值300亿
  5. 搭建hypervisor类型为VMWare的cloudstack环境
  6. CentOS-6.0下安装配置Cacti
  7. 华为动态NAT小实验演示
  8. html三元运算符 模板,AngularJS模板中的三元运算符
  9. 【OpenCV】OpenCV函数精讲之 -- 通道合并:merge()函数
  10. 被灵魂问倒:这个BUG为什么没测出来?
  11. 题解【luogu2045 方格取数游戏加强版】
  12. vs2017安装完成,但有错误。
  13. BrainOS —最像大脑的AI
  14. 417.太平洋大西洋水流问题
  15. c语言一些简单的程序
  16. Jetson nano : PWM风扇调速。
  17. 【毕业设计/课程设计】企业员工绩效考评APP的设计与实现
  18. 对标阿里P6-P7高级Java程序员的进阶技术路线
  19. 用c语言录入3组学生数据编程,学生信息管理系统C语言编程
  20. 2021年德阳2中高考成绩查询,2021年德阳高中录取分数线是多少及高中排名榜

热门文章

  1. 男人一生必须做好的10件事
  2. 完全备份、差异备份和增量备份的区别
  3. iOS-申请邓白氏编码的超详细流程介绍--申请苹果公司开发者账号流程所需
  4. 超实用:英语打电话N种说法
  5. python与bim_BIM轻量化之路(二)
  6. Spring Boot文档阅读笔记-Validating Form Input解析
  7. 专访|这家传统保险中介如何借力大数据优化“卖保险”流程?
  8. IT王老五的情感自白书
  9. 【计算机网络学习笔记(一)】之 OSI参考模型,网络传输方式分类,网络设备分类,网络组成结构
  10. 零基础怎么学习嵌入式?怎样学习嵌入式更有效率?