是否可以将延迟计算的变量导出到子Makefile?
这个问题很有希望是我从和开始提出的最后一个问题 我有以下目录结构:是否可以将延迟计算的变量导出到子Makefile?,makefile,gnu-make,lazy-evaluation,Makefile,Gnu Make,Lazy Evaluation,这个问题很有希望是我从和开始提出的最后一个问题 我有以下目录结构: . ├── Makefile ├── src │ └── Makefile └── test └── Makefile 我的顶级Makefile只在src/和test/子菜单上运行$(MAKE): TOP_DIR := $(shell pwd) export PRJ_LIBS = $(wildcard $(TOP_DIR)/build/*) all: src test @echo $(PRJ_LI
.
├── Makefile
├── src
│ └── Makefile
└── test
└── Makefile
我的顶级Makefile只在src/
和test/
子菜单上运行$(MAKE)
:
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在对等子目录build/
中创建一个文件:
all:
@mkdir -p ../build
@touch ../build/libfoo.so
我希望我的test/
Makefile能够访问build/
目录的更新内容:
all:
@echo $(PRJ_LIBS)
上述生成文件无法实现这一点:
$ 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/*)
...
根据我的业余估计,我在这里似乎有竞争的目标:我想“导出”我的惰性评估变量,以便顶级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)
虽然这实现了我的目标,但导出变量会产生不愉快的副作用,即预先计算会导致stderr的查找失败不导出变量与上述第二次试验具有相同的效果:在顶级all
配方中按需要评估变量,但不在test/
子目录的all
配方中评估变量
对于更精通Makefile的人来说,我想要实现的最好或“众所周知”的解决方案是什么:在顶级Makefile中定义一个变量,该变量可以在子级Makefile中惰性地进行评估?最好没有像前端shell命令失败这样的副作用。(实际上,在顶级Makefile中评估变量并不重要——这更像是一种帮助我理解事情的调试工具)我想从非指导性实验的结果中提供一种解决方案: 我可以不导出顶级Makefile中的lazy变量,然后将其作为参数传递给子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
我很好奇Makefile专家如何看待这个解决方案——这被认为是解决这个问题的好方法吗
$ 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
$
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
$