在一个makefile中编译C ++和C文件

时间:2014-11-20 22:47:16

标签: linux unix gcc compilation makefile

我有一个看起来像这样的makefile:

CS := a.c b.c
CPPS := foo.cpp bar.cpp
SOURCES := $(CS) $(CPPS)
OBJS := $(CS:%.c=$(OBJSDIR)/%.o) $(CPPS:%.cpp=$(OBJSDIR)/%.o)

我想创建一个单独的规则来编译它们。但我能想到的唯一选择是:

$(OBJSDIR)/%.o: %.cpp
    $(GXX) $(GXXFLAGS) -c $< -o $@

但当然它不起作用,因为某些目标文件没有匹配的C ++源文件。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

假设你有a.cc,b.cc和c.cc,另一方面是d.c,e.c和f.c

program_objs = a.o b.o c.o d.o e.o f.o

program: $(program_objs)
    $(CC) $(LDFLAGS) -o $@ $(program_objs)

你不再需要任何东西了,因为make会自动检测哪些文件是c ++,哪些文件是普通c,并会选择合适的编译器。

如果你想要一些特殊的东西,不包含在makefile中,你可以用规则添加一些后缀(文件类型):

.SUFFIXES: .a .b .o

然后使用以下规则将它们编译为.o

.a.o:
    $(COMPILER_A) $(COMPILER_A_FLAGS) -c $@ -o $<
.b.o:
    $(COMPILER_B) $(COMPILER_B_FLAGS) -c $@ -o $<

让makefile选择合适的编译器(存储在变量COMPILER_A或COMPILER_B中的编译器)来完成工作。

当然,您可以使用显式规则将某些内容编译为.o文件,如:

a.o: a.cc
    g++ -o a.o -c a.cc
b.o: b.cc
    g++ -o b.o -c b.cc
c.o: c.cc
    g++ -o c.o -c c.cc
d.o: d.c
    gcc -o d.o -c d.c
e.o: e.c
    gcc -o e.o -c e.c
f.o: f.c
    gcc -o f.o -c f.c

注意#1:

已经对GNU make%模式进行了一些描述,以构建目标的隐式规则。下面是重写上面的隐含规则来做同样的事情:

%.o: %.a
    $(COMPILER_A) $(COMPILER_A_FLAGS) -c $@ -o $<
%.o: %.b
    $(COMPILER_B) $(COMPILER_B_FLAGS) -c $@ -o $<

与往常一样,$@表示规则的目标,$<(您也可以使用$*作为文件名,没有任何匹配的后缀)左侧需要的文件。有关可以使用的自动变量的完整列表,建议您阅读制作手册。考虑到旧的后缀语法与新的语法相反(目标后缀在旧语法中最后出现,新语法更类似于冒号左侧的目标的普通makefile规则)

答案 1 :(得分:0)

  

我想创建一个单独的规则来编译它们。

正如Etan Reisner在评论部分所说,make已经有隐式规则来编译.c.cpp文件,所以你问题的真正答案是:

不要写任何内容来编译您的目标文件

也就是说,您现在应该删除这两个变量:$(GXX)$(GXXFLAGS)

要向ccgcc提供标记,应使用CFLAGS内置变量。
要向g++提供标记,应使用CXXFLAGS内置变量 要向预处理器(cpp)提供标志,应使用CPPFLAGS变量。

由于您正在混合使用C和C ++源文件,因此应使用CXX变量作为链接器命令。