Makefile中用foreach,eval,call实现将目标文件编译到指定目录
Makefile中用foreach,eval,call实现将目标文件编译到指定目录
临峰不畏 发表于1年前
Makefile中用foreach,eval,call实现将目标文件编译到指定目录
  • 发表于 1年前
  • 阅读 455
  • 收藏 3
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

摘要: 写了个Makefile,小总结一下经验,方便将来回顾。

博主要创建一个工程目录,希望将所有的.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

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

标签: Makefile
共有 人打赏支持
粉丝 206
博文 183
码字总数 96576
×
临峰不畏
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: