如何为GNU Make的不同文件名编写不同的隐式规则 我有一个目录,我不断地添加不同的C++源文件和通用的MaFaX文件来编译它们。这是Makefile的内容: .PHONY: all clean CXXFLAGS = -pipe -Wall -Wextra -Weffc++ -pedantic -ggdb SRCS = $(wildcard *.cxx) OBJS = $(patsubst %.cxx,%.out,$(SRCS)) all: $(OBJS) clean: rm -fv $(OBJS) %.out: %.cxx $(CXX) $(CXXFLAGS) $^ -o $@ file_main.out: file_main.cxx file.cxx file.out: file_main.out @echo "Skipping $@"

如何为GNU Make的不同文件名编写不同的隐式规则 我有一个目录,我不断地添加不同的C++源文件和通用的MaFaX文件来编译它们。这是Makefile的内容: .PHONY: all clean CXXFLAGS = -pipe -Wall -Wextra -Weffc++ -pedantic -ggdb SRCS = $(wildcard *.cxx) OBJS = $(patsubst %.cxx,%.out,$(SRCS)) all: $(OBJS) clean: rm -fv $(OBJS) %.out: %.cxx $(CXX) $(CXXFLAGS) $^ -o $@ file_main.out: file_main.cxx file.cxx file.out: file_main.out @echo "Skipping $@",makefile,gnu-make,Makefile,Gnu Make,注意:从上面可以明显看出,我使用*.out作为可执行文件扩展名,而不是对象文件扩展名 此外,还有一些文件是一起编译的: g++ file_main.cxx file.cxx -o file_main.out 为了编译这些文件,到目前为止,我一直在Makefile中添加显式规则: .PHONY: all clean CXXFLAGS = -pipe -Wall -Wextra -Weffc++ -pedantic -ggdb SRCS = $(wildcard *.cxx) OBJS = $

注意:从上面可以明显看出,我使用*.out作为可执行文件扩展名,而不是对象文件扩展名

此外,还有一些文件是一起编译的:

g++ file_main.cxx file.cxx -o file_main.out
为了编译这些文件,到目前为止,我一直在Makefile中添加显式规则:

.PHONY: all clean

CXXFLAGS = -pipe -Wall -Wextra -Weffc++ -pedantic -ggdb

SRCS = $(wildcard *.cxx)
OBJS = $(patsubst %.cxx,%.out,$(SRCS))

all: $(OBJS)

clean:
    rm -fv $(OBJS)

%.out: %.cxx
    $(CXX) $(CXXFLAGS) $^ -o $@
file_main.out: file_main.cxx file.cxx

file.out: file_main.out
    @echo "Skipping $@"
但是现在我的Makefile有很多显式规则,我想用一个更简单的隐式规则来代替它们


你知道怎么做吗?

看起来你正在把多个不同程序的源代码放在同一个文件夹中,这才是问题的根源。如果将库和程序的源代码分离到单独的文件夹中,或者更好地说,分离到单独的项目中,则可以通过依赖给定文件夹中的所有源文件来避免此问题。当你把所有的东西都混在一起时,就必须明确

也就是说,如果您的依赖项具有一致的、可预测的名称,那么可以通过使用来消除这种冗余。例如,基于上述示例:

#
# I'm going to use standard file extensions here,
# slightly deviating from your conventions. I am also
# assuming that there is a variable named PROGNAMES,
# which gives a list of all the programs to be built.
#
define ADD_EXECUTABLE
     $(1): $(1).o $(1)_main.o
         $(LINK.cc) $(1).o $(1)_main.o -o $(1)
endef

$(foreach progname,$(PROGNAMES),$(eval $(call ADD_EXECUTABLE,$(progname)))) 

还有,只是一些建议。。。您应该附加到CXXFLAG而不是覆盖它,而使用标准文件扩展名更好。C++的源文件,.O,用于对象文件,没有可执行文件的扩展。请参阅我的,以了解使用“无双关语”使事情变得更简单的技巧。

似乎您正在将多个不同程序的源代码放在同一文件夹中,而这正是问题的根源。如果将库和程序的源代码分离到单独的文件夹中,或者更好地说,分离到单独的项目中,则可以通过依赖给定文件夹中的所有源文件来避免此问题。当你把所有的东西都混在一起时,就必须明确

也就是说,如果您的依赖项具有一致的、可预测的名称,那么可以通过使用来消除这种冗余。例如,基于上述示例:

#
# I'm going to use standard file extensions here,
# slightly deviating from your conventions. I am also
# assuming that there is a variable named PROGNAMES,
# which gives a list of all the programs to be built.
#
define ADD_EXECUTABLE
     $(1): $(1).o $(1)_main.o
         $(LINK.cc) $(1).o $(1)_main.o -o $(1)
endef

$(foreach progname,$(PROGNAMES),$(eval $(call ADD_EXECUTABLE,$(progname)))) 

还有,只是一些建议。。。您应该附加到CXXFLAG而不是覆盖它,而使用标准文件扩展名更好。C++的源文件,.O,用于对象文件,没有可执行文件的扩展。请参阅我的,以了解使用Make no pun使事情变得更简单的技巧。

首先,这种将多个源文件直接编译成可执行文件的方法不是一个非常好的主意。更常见的编译-然后链接方法将节省大量不必要的编译

也就是说,用更简单的规则替换许多显式规则的方法取决于显式规则的共同点。您已经有一个模式规则:

%.out: %.cxx
    $(CXX) $(CXXFLAGS) $^ -o $@
file_main.out another_main.out a_third_main.out: %_main.out : %.cxx
如果您只想将另一个源文件添加到特定目标,则无需执行以下操作:

g++ file_main.cxx file.cxx -o file_main.out
您只需在一行中添加一个先决条件即可获得效果:

file_main.out: file.cxx
如果有多个具有该模式的目标,则可以使用模式规则:

%.out: %.cxx
    $(CXX) $(CXXFLAGS) $^ -o $@
file_main.out another_main.out a_third_main.out: %_main.out : %.cxx
如果有许多这样的目标,可以使用一个变量:

MAIN_THINGS = file another a_third a_fourth and_yet_another
MAIN_TARGETS = $(addsuffix _main.out, $(MAIN_THINGS))
$(MAIN_TARGETS): %_main.out : %.cxx

您还可以为其他目标集添加其他模式,甚至是重叠的目标集。这是否涵盖了您的情况?

首先,这种将多个源文件直接编译成可执行文件的方法不是一个非常好的主意。更常见的编译-然后链接方法将节省大量不必要的编译

也就是说,用更简单的规则替换许多显式规则的方法取决于显式规则的共同点。您已经有一个模式规则:

%.out: %.cxx
    $(CXX) $(CXXFLAGS) $^ -o $@
file_main.out another_main.out a_third_main.out: %_main.out : %.cxx
如果您只想将另一个源文件添加到特定目标,则无需执行以下操作:

g++ file_main.cxx file.cxx -o file_main.out
您只需在一行中添加一个先决条件即可获得效果:

file_main.out: file.cxx
如果有多个具有该模式的目标,则可以使用模式规则:

%.out: %.cxx
    $(CXX) $(CXXFLAGS) $^ -o $@
file_main.out another_main.out a_third_main.out: %_main.out : %.cxx
如果有许多这样的目标,可以使用一个变量:

MAIN_THINGS = file another a_third a_fourth and_yet_another
MAIN_TARGETS = $(addsuffix _main.out, $(MAIN_THINGS))
$(MAIN_TARGETS): %_main.out : %.cxx

您还可以为其他目标集添加其他模式,甚至是重叠的目标集。这是否涵盖了您的情况?

为什么不使用模式规则:$PROGNAMES:%:%.o%\u main.o$LINK.cc$^-o$@?我想你是指恩德夫。@Beta,谢谢。修正了endef。我认为我的版本更清晰,但您的建议也是有效的$LINK.cc$^-o$@?我想你是指恩德夫。@Beta,谢谢。修正了endef。我认为我的说法更清楚,但你的建议也是正确的。