如何将不同目录中的源代码编译成一个目录(Makefile)中的目标文件?
How to compile sources in different directories into object files all in a single directory (Makefile)?
我有这样的布局:
project/
Makefile
core/
a.cpp
a.hpp
utl/
b.cpp
b.hpp
obj/
而且我想将所有 .o 文件都放在 obj 文件夹中,这样我就可以从这些目标文件创建一个共享库。但是由于我的 .cpp 文件位于不同的目录中,所以我不知道如何自动执行此操作。不仅有这两个目录,还有多个目录。任何提示表示赞赏。
我的尝试失败了,因为我假设 Make automatic rule for .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
您可以从目标文件创建碎片库,即使它们位于不同的目录中。所以这并不是将它们放在其他地方的真正理由。
然而,更好的理由是保持源目录整洁并使其易于清理(只需删除 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 $@ $<
我有这样的布局:
project/
Makefile
core/
a.cpp
a.hpp
utl/
b.cpp
b.hpp
obj/
而且我想将所有 .o 文件都放在 obj 文件夹中,这样我就可以从这些目标文件创建一个共享库。但是由于我的 .cpp 文件位于不同的目录中,所以我不知道如何自动执行此操作。不仅有这两个目录,还有多个目录。任何提示表示赞赏。
我的尝试失败了,因为我假设 Make automatic rule for .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
您可以从目标文件创建碎片库,即使它们位于不同的目录中。所以这并不是将它们放在其他地方的真正理由。
然而,更好的理由是保持源目录整洁并使其易于清理(只需删除 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 $@ $<