是否可以将延迟计算的变量导出到子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
$