makefile - 是否可以将延迟评估的变量导出到子 Makefile?
问题描述
我有以下目录结构:
.
├── Makefile
├── src
│ └── Makefile
└── test
└── Makefile
我的顶级 Makefile 只$(MAKE)
在src/
和test/
子目录上运行:
TOP_DIR := $(shell pwd)
export PRJ_LIBS = $(wildcard $(TOP_DIR)/build/*)
all: src test
@echo $(PRJ_LIBS)
src:
@$(MAKE) -C $@
test:
@$(MAKE) -C $@
.PHONY: src test
我的src/
Makefile 在 peer 子目录中创建一个文件build/
:
all:
@mkdir -p ../build
@touch ../build/libfoo.so
我希望我的test/
Makefile 能够访问build/
目录的更新内容:
all:
@echo $(PRJ_LIBS)
上面的 Makefile 没有做到这一点:
$ rm -rf ./build/ && make
make[1]: Entering directory '/path/to/src'
make[1]: Leaving directory '/path/to/src'
make[1]: Entering directory '/path/to/test'
make[1]: Leaving directory '/path/to/test'
$
我发现一个问题是我在顶级 Makefile中导出。 $(PRJ_LIBS)
将其设为非导出变量会稍微改善一些情况:子目录的更新内容build/
在顶级 Makefile 的all
配方中可见,但仍不在test/
目录的 Makefile 中:
...
#export PRJ_LIBS = $(wildcard $(TOP_DIR)/build/*)
PRJ_LIBS = $(wildcard $(TOP_DIR)/build/*)
...
$ rm -rf ./build/ && make
make[1]: Entering directory '/path/to/src'
make[1]: Leaving directory '/path/to/src'
make[1]: Entering directory '/path/to/test'
make[1]: Leaving directory '/path/to/test'
/path/to/build/libfoo.so
根据我的业余估计,看起来我在这里有相互竞争的目标:我想“导出”我的惰性求值变量,以便顶级 Makefile 和子 Makefile 都“知道”它,但导出变量似乎有即时/预先评估的效果。
一个明显的解决方法是依赖对 shell 命令的显式调用:
#export PRJ_LIBS = $(wildcard $(TOP_DIR)/build/*)
#PRJ_LIBS = $(wildcard $(TOP_DIR)/build/*)
export PRJ_LIBS = $(shell find $(TOP_DIR)/build -type f)
$ rm -rf ./build/ && make
find: ‘/path/to/build’: No such file or directory
make[1]: Entering directory '/path/to/src'
make[1]: Leaving directory '/path/to/src'
make[1]: Entering directory '/path/to/test'
/path/to/build/libfoo.so
make[1]: Leaving directory '/path/to/test'
/path/to/build/libfoo.so
$
虽然这实现了我的目标,但导出变量具有预先评估的令人不快的副作用,导致find
stderr 令人眼花缭乱的失败。不导出变量与上面的第二次试验具有相同的效果:在顶级all
配方中根据需要评估变量,但不在test/
子目录的all
配方中。
对于 Makefile 的更专业的人来说,对于我想要实现的目标,最好或“众所周知”的解决方案是什么:在顶级 Makefile 中定义一个可以在子级 Makefile 中延迟评估的变量?最好没有像前期 shell 命令失败这样的副作用。(实际上,在顶级 Makefile 中评估变量并不重要——这只是帮助我理解事物的调试工具)
解决方案
我想从无指导的实验结果中提供一种解决方案:
我无法在顶级 Makefile 中导出我的惰性变量,然后将其作为参数传递给子 make,如下所示:
TOP_DIR := $(shell pwd)
PRJ_LIBS = $(wildcard $(TOP_DIR)/build/*)
all: src test
@echo $(PRJ_LIBS)
src:
@$(MAKE) -C $@
test:
@$(MAKE) PRJ_LIBS=$(PRJ_LIBS) -C $@
.PHONY: src test
$ rm -rf ./build/ && make
make[1]: Entering directory '/home/amenon/code/fubar/src'
make[1]: Leaving directory '/home/amenon/code/fubar/src'
make[1]: Entering directory '/home/amenon/code/fubar/test'
/home/amenon/code/fubar/build/libfoo.so
make[1]: Leaving directory '/home/amenon/code/fubar/test'
/home/amenon/code/fubar/build/libfoo.so
$
我很好奇 Makefile 专家对这个解决方案的看法——这被认为是解决这个问题的好方法吗?
推荐阅读
- css - 如何使我的单选按钮看起来像带有 ngFor 的切换按钮?
- c++ - OpenGL窗口未打开在eclipse cdt上终止的进程
- android - Flutter,AndroidManifest.xml 的可见性配置 API >= 30
- python - 自定义过滤器在 django rest 框架中不起作用
- ldap - Oracle APEX,将字段填充为 ldap 当前用户
- java - 在 Gremlin 上的 ForEach 步骤
- c# - c#复制(不仅仅是重定向)一个进程的stdout,使用连接线程不工作
- mongodb - mongo db 聚合中 $set 的动态字段路径
- javascript - 在js中播放ffmpeg加密的视频文件
- flutter - 单个文件中多个测试用例的 Flutter 集成测试失败