【问题标题】:How to compile sources in different directories into object files all in a single directory (Makefile)?如何将不同目录中的源代码编译成一个目录(Makefile)中的目标文件?
【发布时间】:2021-05-10 16:28:56
【问题描述】:

我有这个布局:

project/
  Makefile
  core/
    a.cpp
    a.hpp
  utl/
    b.cpp
    b.hpp
  obj/

我想将所有 .o 文件放在 obj 文件夹中,这样我就可以从这些目标文件中创建一个共享库。但由于我的 .cpp 文件位于不同的目录中,我不知道如何自动执行此操作。不仅有这两个目录,还有多个目录。任何提示表示赞赏。

我的尝试失败了,因为我假设 .o 的自动规则(我想使用)希望 .cpp 位于 .o 应该在的同一目录中?

# grab all cpp files with their path that are in some DIRS list
SRC = $(wildcard *.cpp) $(foreach DIR,$(DIRS),$(wildcard $(DIR)/*.cpp))

# remove the path
SRC_WITHOUT_PATH = $(notdir $(SRC))

# stick the .obj/ directory before the .cpp file and change the extension
OBJ = $(SRC_WITHOUT_PATH:%.cpp=./obj/%.o)

# error is no rule to make target obj/a.o

【问题讨论】:

    标签: makefile compilation shared-libraries project gnu-make


    【解决方案1】:

    您可以从目标文件创建一个粉碎库,即使它们位于不同的目录中。所以这并不是将它们放在其他地方的真正理由。

    但是,更好的理由是保持源目录整洁并使其易于清理(只需删除 obj 目录)。

    将不同目录中的源文件中的目标文件放到一个目录中是有问题的:如果您有两个同名的源文件,它们将相互覆盖。解决此问题的一种常见方法是保留源文件的目录结构,但将其放在新的顶级目录之下; GNU make 很容易支持:

    # grab all cpp files with their path that are in some DIRS list
    SRC = $(wildcard *.cpp) $(foreach DIR,$(DIRS),$(wildcard $(DIR)/*.cpp))
    
    # stick the .obj/ directory before the .cpp file and change the extension
    OBJ = $(addprefix obj/,$(SRC:.cpp=.o))
    
    obj/%.o : %.cpp
            @mkdir -p $(@D)
            $(COMPILE.cpp) -o $@ $<
    

    如果您真的非常想将所有目标文件放在同一个目录中,您将不得不变得更有趣,因为 make 使用简单的字符串匹配目标,因此您必须为目标和目标的每个关系编写一个新规则先决条件名称不同:基本上这意味着每个单独的源目录都有一个新规则。

    您可以通过使用 GNU make 的the VPATH feature 来避免这种情况,如下所示:

    # grab all cpp files with their path that are in some DIRS list
    SRC = $(wildcard *.cpp) $(foreach DIR,$(DIRS),$(wildcard $(DIR)/*.cpp))
    
    # remove the path
    SRC_WITHOUT_PATH = $(notdir $(SRC))
    
    # stick the .obj/ directory before the .cpp file and change the extension
    OBJ = $(SRC_WITHOUT_PATH:%.cpp=obj/%.o)
    
    # Give all the source directories to make
    VPATH = $(sort $(dir $(SRC))
    
    obj/%.o : %.cpp
            $(COMPILE.cpp) -o $@ $<
    

    【讨论】:

    • 感谢您的帮助!在阅读后我也尝试过它并且它有效:vpath %.cpp DIRS
    猜你喜欢
    • 2011-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-26
    • 1970-01-01
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    相关资源
    最近更新 更多