【问题标题】:Makefile for mixed C/C++ sources混合 C/C++ 源的 Makefile
【发布时间】:2018-03-03 09:44:45
【问题描述】:

假设我有以下设置

CPPSRC+=path1/foo.cpp
CPPSRC+=path2/main.cpp

CSRC+=path3/zoo.c
CSRC+=path4/bar.c

我想将所有目标文件.o 生成到build/ 文件夹中(所以我想同时需要pathsubst 和模式匹配)。

我还需要.cppg++ 和相关的CXXFLAGS 一起编译,而.c 需要与gcc 和更简单的CFLAGS 一起编译。

我已经走到这一步了:

CPPOBJ := $(CPPSRC:%.cpp=%.o)
COBJ := $(CSRC:%.c=%.o)
OBJ := $(COBJ) $(CPPOBJ)
BUILTOBJ := $(addprefix $(BUILD_PATH)/,$(notdir $(OBJ)))

$(APP): $(OBJ)
    [...]

$(CPPOBJ): %.o: %.cpp
    @echo "[g++" $(BUILD_PATH)$(notdir $@)"]"
    $(SILENT)$(GPP) $(CXXFLAGS) $(INCLUDES) -c $< -o $(BUILD_PATH)$(notdir $@)

$(COBJ): %.o: %.c
    @echo "[gcc " $(BUILD_PATH)$(notdir $@)"]"
    $(SILENT)$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $(BUILD_PATH)$(notdir $@)

但无法达到$(COBJ): %.o: %.c 先决条件(简而言之,.c 源不会被编译)。

怎么做?

【问题讨论】:

    标签: c++ c makefile


    【解决方案1】:

    您尝试使用 gmake 的模式规则实现的目标是不可能的,因为当您从目标文件中剥离源子目录时,您会丢失路径信息。 所以像%.o: %.cpp 这样的通用模式规则永远不会知道要编译build/foo.o 它需要查看path1/foo.cpp。 更不用说增加命名冲突的可能性了。

    可以通过重新创建build/下的子目录结构来解决,即将path1/foo.cpp编译成build/path1/foo.o等。

    一旦排序完成,gmake 就足够聪明,可以解决看似模棱两可的规则,即编译 .c.cpp 文件的混合完全没有问题,如下例所示:

    APP = app
    BUILD_PATH = build
    CPPOBJ := $(CPPSRC:%.cpp=%.o)
    COBJ := $(CSRC:%.c=%.o)
    OBJ := $(COBJ) $(CPPOBJ)
    BUILTOBJ := $(addprefix $(BUILD_PATH)/,$(OBJ))
    
    $(APP): $(BUILTOBJ)
        $(CXX) $(CPPFLAGS) -o $@ $(BUILTOBJ) $(LDLIBS)    
    
    $(BUILD_PATH)/%.o: %.cpp
        mkdir -p $(@D)
        $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@
    
    $(BUILD_PATH)/%.o: %.c
        mkdir -p $(@D)
        $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
    

    【讨论】:

      【解决方案2】:

      我真是太天真了..因为我确实在原始路径中有 .o 文件(不在 build/ 中),而我的 clean: 只删除了 build/ 路径,.c 先决条件从未被调用和.o 未生成也未放置在 build/ 文件夹中。

      确实,我的伎俩试图愚弄 make,让它在与定义的先决条件不同的位置生成 .o 文件。

      次要插件:我不需要使用单独的 C/C++ 源列表登陆生成文件;我可以通过以下方式实现分离:

      CPPSRC:=$(filter %.cpp,$(SRC))
      CSRC:=$(filter %.c,$(SRC))
      CPPOBJ:= $(CPPSRC:%.cpp=%.opp)
      COBJ:= $(CSRC:%.c=%.o)
      OBJ:= $(COBJ) $(CPPOBJ)
      BUILTOBJ:= $(addprefix $(BUILD_PATH)/,$(notdir $(OBJ)))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-07
        • 1970-01-01
        • 1970-01-01
        • 2015-01-04
        相关资源
        最近更新 更多