如何将来自不同目录的源文件编译成目标文件并放入单独的一个目录中?需要使用Makefile实现。

24

我正在使用UnitTest++为一些C++代码创建单元测试(该代码应在Linux或Mac OS X上构建)。我的目录结构如下:

src
- Foo.cpp
- Bar.cpp
test
- FooTest.cpp
- BarTest.cpp
- Main.cpp
- Makefile
UnitTest++
- libUnitTest++.a

这个Makefile(从UnitTest++的Makefile改编而来)非常好用(适用于GNU make):

test = TestFooAndBar

src = ../src/Foo.cpp \
    ../src/Bar.cpp

test_src = Main.cpp \
    FooTest.cpp \
    BarTest.cpp

lib = ../UnitTest++/libUnitTest++.a

objects = $(patsubst %.cpp,%.o,$(src))
test_objects = $(patsubst %.cpp,%.o,$(test_src))


.PHONY: all
all: $(test)
    @echo Running unit tests...
    @./$(test)

$(test): $(lib) $(test_objects) $(objects)
    @echo Linking $(test)...
    @$(CXX) $(LDFLAGS) -o $(test) $(test_objects) $(objects) $(lib)

.PHONY: clean
clean:
    -@$(RM) -f $(objects) $(test_objects) $(test) 2> /dev/null

%.o : %.cpp
    @echo $<
    @$(CXX) $(CXXFLAGS) -c $< -o $(patsubst %.cpp,%.o,$<)

我想把所有的 .o 文件放在 "test" 目录下的 "obj" 子目录中。如何修改这个 Makefile 实现?

我尝试将 "objects" 和 "test_objects" 变量添加 "obj/",但我无法弄清楚如何修改 %.o 规则使其知道 .o 文件所在位置并引用正确的 .cpp 文件。我需要创建两个不同的规则,一个用于每组 .cpp 文件吗?

如果我不定义 "src" 和 "test_src" 变量,而是让 Makefile 为所有 .cpp 文件构建一个 .o(位于 obj/ 中),是否会更简单?

1个回答

37

有很多方法可以做到这一点,但这是一个相当不错的方法(我真的应该把它设置为热键)。

vpath %.cpp ../src

src = Foo.cpp Bar.cpp 
test_src = Main.cpp FooTest.cpp BarTest.cpp 

objects = $(patsubst %.cpp,obj/%.o,$(src)) 
test_objects = $(patsubst %.cpp,obj/%.o,$(test_src)) 

$(objects): | obj

obj:
  @mkdir -p $@

obj/%.o : %.cpp
  @echo $< 
  @$(CXX) $(CXXFLAGS) -c $< -o $@

7
$(objects): | obj这行代码中,"|"代表"先决条件"。也就是说,目标文件($(objects))在被构建之前,必须要先构建obj这个目录。 - Anton Daneyko
16
@mezhaka,它表示接下来的前提条件(在这种情况下是 obj)是仅限顺序前提条件。这意味着如果必须构建任何 $(objects),则必须先构建 obj,但是如果 obj 已过期(或不存在),那么并不强制构建 $(objects) - Beta
哎呀,这太密集了...vpath 的结果去哪里了?我怎么才能访问它的内容?这到底是什么意思?“objects = $(patsubst %.cpp,obj/%.o,$(src))” - MarcusJ
1
@MarcusJ 我也是Makefile的新手,所以我不知道vpath的问题...我自己也在想。objects=... 部分查看源文件字符串中的每个文件名,并将所有 %.cpp 的出现替换为 obj/%.o,其中 % 是通配符。您可以在patsubst函数手册中找到有关此用法的良好解释。另请参阅GNU make手册 - drmuelr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接