文档章节

Makefile中用foreach,eval,call实现将目标文件编译到指定目录

临峰不畏
 临峰不畏
发布于 2016/08/10 22:22
字数 565
阅读 1088
收藏 3

博主要创建一个工程目录,希望将所有的.c文件都编译成.o并存放到out/目录下。如下:

.
├── d1
│   ├── aa.c
│   └── dd.c
├── main.c
├── Makefile
└── out

经过一晚上的尝试,最终使用了foreach函数实现了这个目标:

TARGET=test
ALL_SOURCES=$(shell find -name "*.c")

SOURCE_TO_OBJECT = ./out/$(subst .c,.o,$(notdir $(1)))
ALL_OBJECTS=$(foreach src,$(ALL_SOURCES),$(call SOURCE_TO_OBJECT,$(src)))

define CREATE_OBJECT_TARGET
$(call SOURCE_TO_OBJECT,$(1)) : $(1)
	gcc -c -o $$@ $$^
endef

all: $(TARGET)

clean:
	-rm $(ALL_OBJECTS)
	-rm $(TARGET)

$(TARGET):$(ALL_OBJECTS)
	gcc -o $@ $^

$(foreach src,$(ALL_SOURCES),$(eval $(call CREATE_OBJECT_TARGET,$(src))))

大概思路是这样的:
首先,ALL_SOURCES=$(shell find -name "*.c"),我将当前目录下的所有.c文件找到并赋值给ALL_SOURCE变量。
然后,ALL_OBJECTS=$(foreach src,$(ALL_SOURCES),$(call SOURCE_TO_OBJECT,$(src))),对每个一ALL_SOURCE中的源文件进行处理,将每个文件名去除路径,并将后缀.c替换成.o,再加上./out前缀就成了目标文件名。注意:函数调用中不能随意地加空格!!
SOURCE_TO_OBJECT是一个将源文件名转换成目标文件名的函数。上面用$(call ...) 对它进行调用。

然后,我想为每个目标文件建立依赖关系,如下:

./obj/main.o : main.c
    gcc -c -o $@ $^

./obj/aa.o : d1/aa.c
    gcc -c -o $@ $^

./obj/bb.o : d1/bb.c
    gcc -c -o $@ $^

文件个数少还好说,如果工程大了,上百个文件维护起来很吃力。于是想到要用 $(foreach ...) 函数来实现。创建这么一个函数,用于生成目标与文件依赖关系:

define CREATE_OBJECT_TARGET
$(call SOURCE_TO_OBJECT,$(1)) : $(1)
	gcc -c -o $$@ $$^
endef

转入的一个参数$(1)是源文件全路径。
注意:其中的 gcc -c -o $$@ $$^,是双 $ 符号。

再用如下的$(foreach ...)函数达到对每一个源文件都建立一个目标的目的:
$(foreach src,$(ALL_SOURCES),$(eval $(call CREATE_OBJECT_TARGET,$(src))))

其中用到的命令有:

  • notdir,从全路径的文件名,提取出文件名称。相当于shell的basename
  • subst,字符串替换
  • foreach,对数组中的每一个元数做处理
  • call,调用自定义宏
  • eval,将字串应用到Makefile上下文
  • shell,执行shell脚本

其它常用的函数还有:

  • dir
  • addprefix
  • patsubst
  • strip
  • sort
  • wildcard

如果大家还有别的什么更好的方法,欢迎留言。

© 著作权归作者所有

共有 人打赏支持
临峰不畏
粉丝 217
博文 187
码字总数 98583
作品 0
深圳
架构师
私信 提问
[转]Makefile 使用总结

Makefile 简介 Makefile 是和 make 命令一起配合使用的. 很多大型项目的编译都是通过 Makefile 来组织的, 如果没有 Makefile, 那很多项目中各种库和代码之间的依赖关系不知会多复杂. Makefil...

四彩
2016/02/28
119
0
一个通用的makefile写法,自动推导文件的依赖关系

今天看了一天的makefile的写法,东拼西凑,好不容易写出了一个makefile,颇有成就感,记录下来,以备温习之用。 假设有两个头文件目录 header1,header2;两个cpp文件目录,src1,src2,一个lib目...

AlphaJay
2010/11/23
0
0
makefile 一看就懂了

前言:没接触Linux下编译之前,觉得很神秘,特别是makefile,一个简单的make命令就能编译一个大型项目生成一个可执行文件,接下来跟大家分享下学习的makefile的知识。 目录: 1.makefile简介...

小小实习生
2016/10/22
39
0
C/C++ 通用 Makefile

Generic Makefile for C/C++ Program ================================================== Keywords: Makefile, make, Generic, C/C++ Author: whyglinux (whyglinux AT hotmail DOT com) D......

wdliming
2011/11/23
0
0
makefile(04)_函数

9.函数定义及调用 Makefile中支持函数的概念,make解析器提供了一系列函数供Makefile使用。同时可以自定义函数。 9.1.自定义函数 在Makefile中支持自定义函数的实现,并调用执行,通过defin...

三九感冒灵
2018/04/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

大数据教程(11.9)hive操作基础知识

上一篇博客分享了hive的简介和初体验,本节博主将继续分享一些hive的操作的基础知识。 DDL操作 (1)创建表 #建表语法CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name [(col_name ...

em_aaron
今天
4
0
OSChina 周四乱弹 —— 我家猫真会后空翻

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @我没有抓狂 :#今天听这个# 我艇牛逼,百听不厌,太好听辣 分享 Led Zeppelin 的歌曲《Stairway To Heaven》 《Stairway To Heaven》- Led Z...

小小编辑
今天
47
3
node调用dll

先安装python2.7 安装node-gyp cnpm install node-gyp -g 新建一个Electron-vue项目(案例用Electron-vue) vue init simulatedgreg/electron-vue my-project 安装electron-rebuild cnpm ins......

Chason-洪
今天
3
0
scala学习(一)

学习Spark之前需要学习Scala。 参考学习的书籍:快学Scala

柠檬果过
今天
3
0
通俗易懂解释网络工程中的技术,如STP,HSRP等

导读 在面试时,比如被问到HSRP的主备切换时间时多久,STP几个状态的停留时间,自己知道有这些东西,但在工作中不会经常用到,就老是记不住,觉得可能还是自己基础不够牢固,知识掌握不够全面...

问题终结者
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部