Makefile 具有子目录的通用生成文件

Makefile 具有子目录的通用生成文件,makefile,gnu-make,makefile-project,Makefile,Gnu Make,Makefile Project,我目前拥有以下Makefile: 在运行它的目录中查找所有*.f 在指定的子目录中查找匹配的*.o(如Objets\U dir中定义的) 汇编和链接 代码: # Paths # ----- # Where to put the *.o Objets_dir = temp\Win # Where to check for the *.o VPATH = $(Objets_dir) # Where to put the resulti

我目前拥有以下Makefile:

  • 在运行它的目录中查找所有*.f
  • 在指定的子目录中查找匹配的*.o(如Objets\U dir中定义的)
  • 汇编和链接
代码:

    # Paths
    # -----

    # Where to put the *.o
    Objets_dir = temp\Win

    # Where to check for the *.o
    VPATH = $(Objets_dir)

    # Where to put the resulting binary
    Executable = D:\Documents\out.exe

    # List of needed objects
    Objets = $(patsubst %.f,%.o,$(wildcard *.f))

    # Rules
    # -----

    F_compilo = gfortran
    F_compilo_options = -O3 -ffpe-trap=invalid,zero,overflow -mfpmath=sse -fmax-errors=3
    Link = x86_64-w64-mingw32-gfortran
    Link_options =

    # Let's go
    # --------

    # Compile (generation of .o)
    %.o:%.f
        $(F_compilo) $(F_compilo_options) -c $< -o $(Objets_dir)\$@

    # Link (generation of .exe)
    $(Executable): $(Objets)
        $(Link) $(Link_options) -o $@ $(addprefix $(Objets_dir)\, $(Objets))
#路径
# -----
#在哪里放置*.o
Objets\U dir=temp\Win
#在哪里检查*.o
VPATH=$(对象目录)
#在哪里放置生成的二进制文件
可执行文件=D:\Documents\out.exe
#所需对象列表
对象=$(patsubst%.f、%.o、$(通配符*.f))
#规则
# -----
F_compileo=gfortran
F_compileo_options=-O3-ffpe陷阱=无效、零、溢出-mfpmath=sse-fmax错误=3
Link=x86_64-w64-mingw32-gfortran
链接选项=
#我们走吧
# --------
#编译(生成.o)
%.o:%.f
$(F_compileo)$(F_compileo_选项)-c$<-o$(对象目录)\$@
#链接(生成.exe)
$(可执行文件):$(对象)
$(链接)$(链接选项)-o$@$(添加前缀$(对象目录)\,$(对象目录))
作为参考,我使用mingw32 make来执行这个Makefile

我想对其进行编辑,以便可以指定一个子文件夹列表,在该列表中,除当前文件夹外,还可以查找源文件(*.f)。这将是一个有点不一般,但我会很好地与这一点

这个makefile是我几年前从互联网上检索到的东西,除了添加一些注释或编辑编译标志外,几乎从未接触过。 我想需要编辑的行是带有“通配符”调用的行,但我完全(完全)不知道Make语言


您能建议如何编辑它吗?

下面是一个在子目录列表中查找文件的示例:

基于此,我得出以下结论。我已经在linux系统上使用一些示例文件对此进行了测试,因此无法保证它在Windows上“开箱即用”,但应该不会太远

它在
dirs
中给出的目录中查找所有.f文件,然后像以前一样继续执行

# Paths
# -----

# Where to put the *.o
Objets_dir = temp\Win

# Where to put the resulting binary
Executable = D:\Documents\out.exe

# List of directories to search for .f files:
dirs := . a b c d

# Extra directories to check for dependencies
VPATH = a b c d

# Make a list of *.f source files found in dirs
Sources := $(foreach dir,$(dirs),$(wildcard $(dir)\*.f))

# List of needed objects
Objets = $(patsubst %.f,%.o,$(Sources))

# Objects with full path names to their location in temp dir.
TempObjets = $(addprefix $(Objets_dir)\, $(notdir $(Objets)))

# Rules
# -----

F_compilo = gfortran
F_compilo_options = -O3 -ffpe-trap=invalid,zero,overflow -mfpmath=sse -fmax-errors=3
Link = x86_64-w64-mingw32-gfortran
Link_options =

# Let's go
# --------

# Compile (generation of .o)
$(Objets_dir)\%.o:%.f
    $(F_compilo) $(F_compilo_options) -c $< -o $(Objets_dir)\$(notdir $@)

# Link (generation of .exe)
$(Executable): $(TempObjets)
    $(Link) $(Link_options) -o $@ $^

clean:
    rm -f $(TempObjets) $(Executable)
#路径
# -----
#在哪里放置*.o
Objets\U dir=temp\Win
#在哪里放置生成的二进制文件
可执行文件=D:\Documents\out.exe
#要搜索.f文件的目录列表:
目录:=。a、b、c、d
#检查依赖项的额外目录
VPATH=a b c d
#列出在目录中找到的*.f源文件
来源:=$(foreach dir,$(dirs),$(通配符$(dir)\*.f))
#所需对象列表
对象=$(patsubst%.f,%.o,$(源))
#具有指向临时目录中位置的完整路径名的对象。
TempObjets=$(addprefix$(Objets\u dir)\,$(notdir$(Objets)))
#规则
# -----
F_compileo=gfortran
F_compileo_options=-O3-ffpe陷阱=无效、零、溢出-mfpmath=sse-fmax错误=3
Link=x86_64-w64-mingw32-gfortran
链接选项=
#我们走吧
# --------
#编译(生成.o)
$(对象目录)\%.o:%.f
$(F\u compileo)$(F\u compileo\u选项)-c$<-o$(Objets\u dir)\$(notdir$@)
#链接(生成.exe)
$(可执行文件):$(TempObjets)
$(链接)$(链接选项)-o$@$^
清洁:
rm-f$(临时喷气式飞机)$(可执行文件)
请注意,它会将子目录从用于构建和链接的文件名中剥离,否则需要创建一组匹配的临时目录。因此,只需将所有.o文件转储到临时目录中就很方便了。但是,请注意,如果子目录中的某些.f文件共享相同的名称,则此操作将失败。在这种情况下,您需要将
VPATH
设置为临时目录列表(列表分隔符在Windows上为
,在其他系统上为
),并从生成和链接规则中删除
$(nordir…
子句)。但是,您需要在
temp\Win
中创建一个目录来匹配每个源目录


最后,应该注意的是,这并不是make的递归使用。为此,请参阅:

好的,一切正常。。。除此之外,每次都会重新编译子目录中的所有文件。我将
dirs
设置为
dirs:=。aaa
。正确找到当前目录中的所有.f,并且仅在需要时(如果修改)重新编译,这是预期的行为。但是
aaa
目录中的文件每次都会被重新编译。帮助?我做了一些编辑。希望你现在能做正确的事。谢谢。它似乎适用于最后几次编辑:虽然我在Windows上,但
源代码
行定义需要是
源代码:=$(foreach dir,$(dirs),$(wildcard$(dir)/*.f))
(注意
/
,而不是
\
),否则它找不到任何源文件并在那里停止。对
TempObjets=$(addprefix$(Objets\u dir)/,$(notdir$(Objets))
$(Objets\u dir)/%进行相同的修改。o:%.f
。另一个
\
很好:)另外,我更改了
VPATH=$(dirs)
以避免复制粘贴整个子目录列表。看起来很好用。