将项目目录树中的所有目标文件传递给 makefile 中的规则
我有一个看起来像这样的 makefile
CC=gcc
CFLAGS=-pedantic -ansi -Wall -O2
TARGET=assembler
SUBDIRS = utils preprocessor parser symbols
.PHONY: clean all subdirs $(SUBDIRS)
subdirs: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@
all: subdirs
clean:
for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir clean; \
done
我想添加
$(TARGET): subdirs $(TARGET).c
$(CC) $(CFLAGS) $(TARGET).c -o $@
但是然后我收到链接错误,因为找不到子目录中的对象文件。有没有办法传递项目根目录下的所有目标文件?
I have a makefile that looks like this
CC=gcc
CFLAGS=-pedantic -ansi -Wall -O2
TARGET=assembler
SUBDIRS = utils preprocessor parser symbols
.PHONY: clean all subdirs $(SUBDIRS)
subdirs: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@
all: subdirs
clean:
for dir in $(SUBDIRS); do \
$(MAKE) -C $dir clean; \
done
And I want to add
$(TARGET): subdirs $(TARGET).c
$(CC) $(CFLAGS) $(TARGET).c -o $@
But then I get linking error because the objects files from the subdirs aren't found. Is there a way to pass all object files under the project root directory?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
使用“pass”一词表明您对 makefile 和 make 操作的思维模型完全错误。 Makefile 是规范,而不是脚本,其中的规则不是函数,也不像函数那样操作。除此之外,显式规则的目标和先决条件是在解析 makefile 时确定的,而不是在(考虑)规则执行时动态确定的。
因此,您建议做的事情是完全行不通的,因为您不能依赖任何目标文件(它们是构建文件)在
make
启动时存在。你有一个先有鸡还是先有蛋的问题。我完全同意 @Andreas 的观点,即在 makefile 中使用 globbing 和类似的动态目标或先决条件检测是不好的。* 完全命名的目标和先决条件应该明确命名(不排除将它们分配给变量或使用替换引用或类似的)。但是,如果您仍然使用通配符或其他形式的动态检测来定位文件,那么您应该定位随项目分发的文件,而不是构建的文件。
如果您想保持递归
make
构建系统的模块化(即 无论如何都不是明显的胜利),那么一个合理的替代方案是每个子目录中的make
构建一个以目录名称命名的静态存档。那么顶层 makefile 就不需要知道子目录 make 的任何细节;它只包含链接中每个库生成的静态库。*造成这种情况的原因有多种,但它们与当前的问题无关。
Usage of the word "pass" suggests that you have altogether the wrong mental model of makefiles and
make
operation. Makefiles are specifications, not scripts, and the rules within are not functions and do not operate like functions. Among other things, the targets and prerequisites of explicit rules are determined when the makefile is parsed, not dynamically at the time of (consideration of) rule execution.It follows that what you propose to do is altogether unworkable, because you cannot rely on any of the object files -- they being built files -- to exist when
make
starts. You have a chicken and egg problem.I fully agree with @Andreas that using globbing and similar dynamic target or prerequisite detection in a makefile is bad.* Targets and prerequisites that are named at all should be named explicitly (not to preclude assigning them to a variable or using substitution references or similar). But if you nevertheless do use globbing or another form of dynamic detection to locate files, then you should be locating files distributed with the project, not built ones.
If you want to maintain the modularity of your recursive
make
build system (which is not by any means a clear win), then one reasonable alternative would be for themake
in each subdirectory to build a static archive named after the directory name. The top-level makefile then does not need to know any of the details of the subdirectorymake
s; it just includes the static library resulting from each one in the link.*There are multiple reasons for this, but they are tangential to the question at hand.