在多个目录和多个可执行文件中带有源代码的 C++ Makefile

问题描述

我有一个学校的小项目,我想写一个像样的 Makefile,我已经看到了一些将 Makefile 与多个源目录和多个可执行文件一起使用的例子,但仍然无法将它正确地实现到我的 Makefile 中。

目录结构如下:

.
├── bin (this is where i want the executables)
├── build (this is where i want the .o)
├── extern
│   └── doctest.h
├── include
│   ├── file1.hpp
│   └── file2.hpp
├── src
│   ├── file1.cpp
│   └── file2.cpp
├── tests
│   ├── file1-test.cpp
│   └── file2-test.cpp
└──  Makefile

PS:我使用 doctest 进行单元测试(我无法更改)。

这是我目前的 Makefile:

BIN_DIR = ./bin/
BUILD_DIR = ./build/
EXTERN_DIR = ./extern/
INCLUDE_DIR = ./include/
SOURCE_DIR = ./src/
TESTS_DIR = ./tests/

CXX = clang++-7
CXXFLAGS = -Wall -std=c++11 -g -O3 -I$(INCLUDE_DIR)

EXEC_FILES = file1 file2
BIN = $(addprefix $(BIN_DIR),$(EXEC_FILES))

all: $(BIN)

$(BIN_DIR) $(BUILD_DIR):
    mkdir -p $@

$(BUILD_DIR)%.o: $(SOURCE_DIR)%.cpp | $(BUILD_DIR)
    $(CXX) $(CXXFLAGS) -c -o $@ $^

$(BUILD_DIR)%.o: $(TESTS_DIR)%.cpp | $(BUILD_DIR)
    $(CXX) $(CXXFLAGS) -I$(EXTERN_DIR) -c -o $@ $^

$(BIN_DIR)file1-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file1-test.o | $(BIN_DIR)
    $(CXX) -o $@ $^

$(BIN_DIR)file2-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file2.o $(BUILD_DIR)file2-test.o | $(BIN_DIR)
    $(CXX) -o $@ $^

clean:
    rm -f $(BIN_DIR)* $(BUILD_DIR)*

它运行良好,但我觉得它在做无用的事情,我可以通过 Makefile 艺术中的更多知识来避免这些事情,遗憾的是我没有太多时间。

我的目标:

  • 我想运行 make 并编译所有单元测试(.cpp 目录中的所有 tests/)和主程序(参见下面的 PS)。>

  • 我想要 bin/ 目录中的所有可执行文件build/ 目录中的所有二进制文件

PS:我还没有我的主要可执行文件,但它应该存储在最后的 src/ 目录中(并且在运行 make 时也进行编译)。

编辑 1:

基本上,我的问题是:我如何编写通用规则来防止为我的项目中的每个新可执行文件复制这个(见下文)?

$(BIN_DIR)file2-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file2.o $(BUILD_DIR)file2 test.o | $(BIN_DIR)
    $(CXX) -o $@ $^

编辑 2:

经过一些更改后,我得到了这样的结果:

BIN_DIR = ./bin/
BUILD_DIR = ./build/
EXTERN_DIR = ./extern/
INCLUDE_DIR = ./include/
SOURCE_DIR = ./src/
TESTS_DIR = ./tests/

vpath %.cpp $(SOURCE_DIR) $(TESTS_DIR)

CXX = clang++-7
CXXFLAGS = -Wall -std=c++11 -g -O3 -I$(INCLUDE_DIR) -I$(EXTERN_DIR)

EXEC_FILES = file1-test file2-test
BIN = $(addprefix $(BIN_DIR),$(EXEC_FILES))

all: $(BIN) | $(BIN_DIR)

$(BUILD_DIR)%.o: %.cpp | $(BUILD_DIR)
    @$(CXX) $(CXXFLAGS) -c -o $@ $^

# The problem is here
$(BIN_DIR)%: $(BUILD_DIR)%.o
    @$(CXX) -o $@ $^

$(BIN_DIR) $(BUILD_DIR):
    @mkdir -p $@

clean:
    -@rm -f $(BIN_DIR)* $(BUILD_DIR)*

我这样理解这条规则(见下文):将 EXEC_FILES 中的每个目标编译到 bin/ 目录中,来自 .o 中的等价 build/ (obj) 1}} 目录

$(BIN_DIR)%: $(BUILD_DIR)%.o
    @$(CXX) -o $@ $^

但实际上我需要一个规则:将 EXEC_FILES 中的每个目标编译到 bin/ 目录中,从 {{ 1}} 目录。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)