我有以下 Makefile 示例:
BUILD = build
PATH_POT3 = src/pot/pot3/
MPIFC = mpiifort
FFLAGS = -O3
MOL_LIST = $(shell find $(PATH_POT3) -mindepth 1 -maxdepth 1 -type d)
$(foreach MOL,$(MOL_LIST), \
$(eval LIST_MOL := $(shell find $(MOL) -name "*.f90")) \
$(info Fortran files: $(LIST_MOL)) \
$(foreach SRC,$(LIST_MOL), \
$(eval OBJ := $(BUILD)/$(notdir $(SRC:.f90=.o))) \
$(OBJ): $(SRC) ; \
$(info Compiling: $(SRC)) \
$(info Output: $(OBJ)) \
$(MPIFC) $(FFLAGS) -c $(SRC) -o $(OBJ) \
) \
)
all: $(foreach MOL,$(MOL_LIST),\
$(foreach SRC,$(shell find $(MOL) -name "*.f90"),\
$(BUILD)/$(notdir $(SRC:.f90=.o))\
)\
)
这里我想PATH_POT3
以顺序的方式(一个接一个地)编译每个子目录的(递归)内容。遗憾的是,这种构造并没有提供预期的结果,因为它只编译列表中的第一个目标文件,而跳过了所有其他目标文件。Makefile 为我的测试用例打印了以下信息:
Fortran files: src/pot/pot3/ar3/pot_ar3.f90 src/pot/pot3/ar3/ar43/pot_ar43.f90
Compiling: mpiifort -O3 -c src/pot/pot3/ar3/pot_ar3.f90 -o build/pot_ar3.o
Output: build/pot_ar3.o
Compiling: mpiifort -O3 -c src/pot/pot3/ar3/ar43/pot_ar43.f90 -o build/pot_ar43.o
Output: build/pot_ar43.o
Fortran files: src/pot/pot3/ar33/pot_ar33.f90 src/pot/pot3/ar33/pot_ar333.f90 src/pot/pot3/ar33/ar53/pot_ar53.f90
Compiling: mpiifort -O3 -c src/pot/pot3/ar33/pot_ar33.f90 -o build/pot_ar33.o
Output: build/pot_ar33.o
Compiling: mpiifort -O3 -c src/pot/pot3/ar33/pot_ar333.f90 -o build/pot_ar333.o
Output: build/pot_ar333.o
Compiling: mpiifort -O3 -c src/pot/pot3/ar33/ar53/pot_ar53.f90 -o build/pot_ar53.o
Output: build/pot_ar53.o
make: 'build/pot_ar3.o' is up to date.
一切似乎都设置正确,但编译仅针对执行build/pot_ar3.o
。
我应该如何更改此文件以获得所需的行为?
问题在于您尝试在
foreach
循环内创建规则定义的方式。您的信息语句显示所有内容均已正确检测,但仅编译了第一个目标文件。发生这种情况是因为 Make 无法按照您期望的方式处理循环内动态定义的规则。这是一个可行的解决方案:
这里的关键在于
eval
如何从函数中创建正确的 Make 规则make-depend
。您最初的方法是在解析阶段打印命令,但并没有正确设置实际规则。它的工作原理是预先查找所有源文件,并使用
eval
该make-depend
函数为每个文件创建适当的规则。该|
符号确保构建目录在编译开始之前就已存在。希望这对你有用。
** 编辑 **
以下是我们在聊天中讨论的内容: