如何修改此 Makefile 以分别构建 c 和 cxx 文件?

Posted

技术标签:

【中文标题】如何修改此 Makefile 以分别构建 c 和 cxx 文件?【英文标题】:How to modify this Makefile to build c and cxx files separately? 【发布时间】:2018-05-09 19:23:34 【问题描述】:

以下 Makefile 在 C 项目中运行良好,但是当我们遇到包含 .cpp 文件的目录时,我们发现第一个模式规则正在用于 .cpp 文件。我已经尝试了 3 或 4 次更改以获得预期的效果,但我似乎找不到方法。我想知道是否可以对以下规则进行任何小的改动,以便使用COMPILE_CXX_COMMAND 构建.cpp 文件。

C_EXT             ?= c
CXX_EXT           ?= cpp
OBJ_EXT           ?= o

C_SRCS := \
src/RT_Socket.c \
src/products.c

CXX_SRCS := \
src/BurnedInAddress.cpp \
src/DiskID.cpp \


C_OBJ_FILES       += $(C_SRCS:.$(C_EXT)=.$(OBJ_EXT))
CXX_OBJ_FILES     += $(CXX_SRCS:.$(CXX_EXT)=.$(OBJ_EXT))


$(ARCHIVE_FILENAME) :   $(C_OBJ_FILES) $(CXX_OBJ_FILES)
    $(CREATE_ARCHIVE_COMMAND)

$(LIBRARY_FILENAME) :   $(ARCHIVE_FILENAME)
    $(CREATE_LIBRARY_COMMAND)

%.$(OBJ_EXT)        :   $(C_SRCS)
    $(COMPILE_C_COMMAND)

%.$(OBJ_EXT)        :   $(CXX_SRCS)
    $(COMPILE_CXX_COMMAND)

编辑: 我想补充一点,我尝试用OBJ 文件列表替换模式目标,它可以工作。

$(C_OBJ_FILES)      :   $(C_SRCS)
    $(COMPILE_C_COMMAND)

$(CXX_OBJ_FILES)    :   $(CXX_SRCS)
    $(COMPILE_CXX_COMMAND)

但是,这会产生一个新问题。我们必须使用一些不同版本的 Make,当没有 .cpp 文件时,其中一个会失败并出现以下错误:

依赖行上没有目标。停下来。

它引用了这一行:$(CXX_OBJ_FILES) : $(CXX_SRCS)

Gnu make 似乎对这种情况没有问题,我们的另一个(OPUS Make)。谁能想到解决方法?

【问题讨论】:

我个人建议使用 cmake 而不是 make。它会为您处理诸如此类的细节。 感谢推荐,这里没有选择。 创建%.$(OBJ_EXT) : $(C_SRCS)这样的规则确实不对。这告诉 make 每个单独的目标文件都有每个源文件作为先决条件。这意味着如果您更改任何一个源文件,每个目标文件都将被重建。这不是你想要的。 同意,我以后可能会找时间制定更精确的规则。我不喜欢当事情出错但仍然有效时。目前,这是可行的,因为在每次构建之前将所有源文件复制到一个新目录(因为它是由 CI 构建的),因此 Make 的“更改检测”机制是无关紧要的。可悲的是,我认为更精确/正确的 Makefile 会更复杂。主要是因为我们需要规则来处理生成的 $(C_SRCS) 并包含来自任意数量的子目录的文件:path1/file1.c path2/file2.c。如果您对此有一个优雅的建议,那就太好了! 【参考方案1】:

你可以使用suffix rules:

CC = gcc
CFLAGS = -O2 -Wall
CXX = g++
CXXFLAGS = -std=c++11 -O3 -Wall

OBJS = cobj1.o cobj2.o cppobj1.o

.c.o:
        $(CC) $(CFLAGS) -c $< -o $@

.cpp.o:
        $(CXX) $(CXXFLAGS) -c $< -o $@

【讨论】:

我对这种方法非常乐观,并且后缀规则似乎确实对 GNU make 产生了预期的效果,但是我收到 OPUS MAKE 的错误:> 不知道如何制作 'src /行动.o'。停止。 哦,我以为你有两个不同版本的 GNU make。这种语法可能是 GNU 特有的。 是的,看起来是这样。仍在寻找解决问题的替代 make 语法。 其实在OPUS make中好像应该支持这个语法,我再重温一下错误:opussoftware.com/tutorial/TutMakefile.htm 无法让它工作。相反,我对 C++ 文件中的目标文件使用了不同的扩展名,从而消除了目标之间的歧义。【参考方案2】:

添加

CXX_OBJ_EXT           ?= obj

替换

CXX_OBJ_FILES         += $(CXX_SRCS:.$(CXX_EXT)=.$(OBJ_EXT))
CXX_OBJ_FILES         += $(CXX_SRCS:.$(CXX_EXT)=.$(CXX_OBJ_EXT))

替换

%.$(OBJ_EXT)          :   $(CXX_SRCS)
%.$(CXX_OBJ_EXT)      :   $(CXX_SRCS)

【讨论】:

以上是关于如何修改此 Makefile 以分别构建 c 和 cxx 文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用子目录中的源代码为 C 和 C++ 创建 makefile

如何让 Makefile 自动重建包含修改后的头文件的源文件? (在 C/C++ 中)

入门C/C++自动构建利器之Makefile

修改 makefile 以包含外部编译的对象

如何将 C makefile 移植到 C++ makefile?

第三部分Makefile介绍