在 Makefile 中处理多个扩展的优雅方式

Posted

技术标签:

【中文标题】在 Makefile 中处理多个扩展的优雅方式【英文标题】:An elegant way to handle multiple extensions in Makefile 【发布时间】:2017-11-07 03:04:31 【问题描述】:

我有一个由几个源头文件组成的小型 C++ 语言项目,我使用 Makefile 来构建我的项目。

最近我在我的项目中添加了一个 .c 文件,该文件最初只有 .cpp 文件。为了构建包括 .c 文件在内的整个项目,我修改了 Makefile,如下所示:

SRC_DIR     := src
INC_DIR     := include
BUILD_DIR   := build

C_EXT       := c
CPP_EXT     := cpp
SOURCES     := $(shell find $(SRC_DIR) -type f -name *.$(CPP_EXT))
               $(shell find $(SRC_DIR) -type f -name *.$(C_EXT))       # Added!

...

$(BUILD_DIR)/%.o: $(SRC_DIR)/%.$(CPP_EXT) $(INC_DIR)/%.h
    @mkdir -p $(BUILD_DIR)
                    $(CXX) $(CFLAGS) -I $(INC_DIR) -c -o $@ $<

$(BUILD_DIR)/%.o: $(SRC_DIR)/%.$(C_EXT) $(INC_DIR)/%.h                 # Added!
    @mkdir -p $(BUILD_DIR)                                             # Added!
                    $(CXX) $(CFLAGS) -I $(INC_DIR) -c -o $@ $<         # Added!

但我认为它有点难看,因为有重复的命令。有什么方法可以去除重复并改进这个 Makefile 命令?

【问题讨论】:

如果您要使用相同的编译器编译它们,请重命名文件 else change.c 以使用 $CC @Waslap 这也是一个至关重要的信息。谢谢:D 【参考方案1】:

Make 带有用于构建 C 和 C++ 的默认规则,因此对于基本用法,您不必担心这一点。由于您正在更改规则以创建更复杂的构建工具,因此您可能只想硬着头皮进行一些重复(在您的示例中并没有那么多)。您可以将这样的内容放在一个通用的 make include 文件中,并将其用于所有类似的项目——这样就不会弄乱您的项目特定的 makefile。


不过……

GNU make 确实提供了defining 和calling 函数,尽管它们可能不太清楚。

define do_compile
    @mkdir -p $(BUILD_DIR)
                    $(CXX) $(CFLAGS) -I $(INC_DIR) -c -o $@ $<
endef

$(BUILD_DIR)/%.o: $(SRC_DIR)/%.$(CPP_EXT) $(INC_DIR)/%.h
    $(call do_compile)

$(BUILD_DIR)/%.o: $(SRC_DIR)/%.$(C_EXT) $(INC_DIR)/%.h                 # Added!
    $(call do_compile)                                                 # Added!

相关:functions in makefiles?

【讨论】:

如果您想变得更高级,请查看 gcc 的 -MM 选项——它可以帮助您管理更具体的依赖关系树,因此您不必重新编译所有内容,因为任何包含文件已更改。不过请注意,这样做确实会带来一些新的挑战。

以上是关于在 Makefile 中处理多个扩展的优雅方式的主要内容,如果未能解决你的问题,请参考以下文章

使用优雅方式对参数验证进行处理

跳过 shpaml 的处理脚本标记的优雅方式

在 Watcom makefile 中扩展宏时 *$ 是啥意思?

spring-security-oauth2 中优雅的扩展自定义(短信验证码)登录方式【Part-0】

有没有更优雅的方式来“伪造”类继承?

makefile 双冒号规则