首页 文章

如何为GNU Make的不同文件名编写不同的隐式规则

提问于
浏览
1

我有一个目录,我不断添加不同的C源文件和通用的Makefile来编译它们 . 这是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 $@

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

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

g++ file_main.cxx file.cxx -o file_main.out

要编译这样的文件,到目前为止我一直在Makefile中添加显式规则:

file_main.out: file_main.cxx file.cxx

file.out: file_main.out
    @echo "Skipping $@"

但是现在我的Makefile有很多明确的规则,我想用一个更简单的隐式规则替换它们 .

知道怎么做吗?

2 回答

  • 4

    首先,这种将几个源文件直接编译成可执行文件的方法并不是一个非常好的主意 . 更常见的compile-then-link方法将节省大量不必要的编译 .

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

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

    如果您只想将其他源文件添加到特定目标,则不必执行此操作:

    g++ file_main.cxx file.cxx -o file_main.out
    

    你可以通过添加一个先决条件(单独一行)来获得效果:

    file_main.out: file.cxx
    

    如果您有多个具有该模式的目标,则可以使用模式规则:

    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
    

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

  • 1

    您似乎将多个不同程序的源代码放在同一个文件夹中,这确实是您问题的根源 . 如果将库和程序的源代码分离到单独的文件夹(或者更好的是单独的项目),那么您可以根据给定文件夹中的所有源文件来解决此问题 . 当你把所有东西混合在一起时,有必要明确 .

    也就是说,如果您的依赖项具有一致的,可预测的名称,那么可以通过使用eval function来消除此冗余 . 例如,基于上面的示例:

    #
    # 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))))
    

    此外,只是一些建议...你应该附加到CXXFLAGS而不是覆盖它,你最好使用标准文件扩展名(".cpp"用于C源文件,".o"用于目标文件,没有可执行文件的扩展名) . 请参阅我的Makefile tutorial,了解如何使Make更容易(没有双关语) .

相关问题