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

时间:2022-04-10 22:49:22

I have a makefile that looks like this:

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

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

I want to create a single rule to compile them all. But the only option I can think of is this:

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

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

But of course it doesn't work because some of the object files don't have a matching C++ source file.

当然,它不能工作,因为一些对象文件没有匹配的c++源文件。

Any idea?

任何想法?

2 个解决方案

#1


2  

suppose you have a.cc, b.cc and c.cc, and on the other side, d.c, e.c and f.c

假设您有一个。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)

You don't need anything more, as make will automatically detect which files are c++ and which ones are plain c and will select the proper compiler.

您不需要任何东西,因为make将自动检测哪些文件是c++,哪些是纯c,并将选择合适的编译器。

in case you want something special, not included in makefile, you can add some suffixes (file types) with the rule:

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

.SUFFIXES: .a .b .o

and then use the following rules to compile them to .o

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

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

and let makefile select the proper compiler (the one stored in variables COMPILER_A or COMPILER_B) to do the work.

让makefile选择合适的编译器(存储在变量compile er_a或compile er_b中的编译器)来完成这项工作。

Of course, you can compile something to a .o file with an explicit rule, as in:

当然,您可以使用显式规则将某些内容编译为.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

Note #1:

Some sugestions have been made on GNU make % pattern to construct implicit rules for targets. Below is a rewritting of the implicit rules above to do the same thing:

对GNU make %模式进行了一些改进,以构造目标的隐式规则。下面是对上面的隐式规则的重写,以做同样的事情:

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

As always, $@ means the target of the rule and $< (you can use also $* for the file name without any matching suffixes) the left needed file. For a complete list of automatic variables that can be used, I suggest you to read your make manual. Take into account that the old suffix syntax is reversed from the new one (the target suffix appears last in the old syntax, the new syntax being more similar to a normal makefile rule with the target on the left side of the colon)

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

#2


0  

I want to create a single rule to compile them all.

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

As Etan Reisner said in the comment section, make already has implicit rules to compile .c and .cpp file, so the real answer to your question is:

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

Do not write anything to compile your object files.

不要编写任何代码来编译对象文件。

That said, you should now remove those two variables: $(GXX) and $(GXXFLAGS).

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

To provide flags to cc or gcc one should use the CFLAGS built-in variable.
To provide flags to g++ one should use the CXXFLAGS built-in variable.
To provide flags to the preprocessor (cpp) one should use the CPPFLAGS variable.

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

Since you're mixing C and C++ source files, you should use the CXX variable as the linker command.

由于您混合了C和c++源文件,所以应该使用CXX变量作为链接器命令。

#1


2  

suppose you have a.cc, b.cc and c.cc, and on the other side, d.c, e.c and f.c

假设您有一个。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)

You don't need anything more, as make will automatically detect which files are c++ and which ones are plain c and will select the proper compiler.

您不需要任何东西,因为make将自动检测哪些文件是c++,哪些是纯c,并将选择合适的编译器。

in case you want something special, not included in makefile, you can add some suffixes (file types) with the rule:

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

.SUFFIXES: .a .b .o

and then use the following rules to compile them to .o

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

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

and let makefile select the proper compiler (the one stored in variables COMPILER_A or COMPILER_B) to do the work.

让makefile选择合适的编译器(存储在变量compile er_a或compile er_b中的编译器)来完成这项工作。

Of course, you can compile something to a .o file with an explicit rule, as in:

当然,您可以使用显式规则将某些内容编译为.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

Note #1:

Some sugestions have been made on GNU make % pattern to construct implicit rules for targets. Below is a rewritting of the implicit rules above to do the same thing:

对GNU make %模式进行了一些改进,以构造目标的隐式规则。下面是对上面的隐式规则的重写,以做同样的事情:

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

As always, $@ means the target of the rule and $< (you can use also $* for the file name without any matching suffixes) the left needed file. For a complete list of automatic variables that can be used, I suggest you to read your make manual. Take into account that the old suffix syntax is reversed from the new one (the target suffix appears last in the old syntax, the new syntax being more similar to a normal makefile rule with the target on the left side of the colon)

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

#2


0  

I want to create a single rule to compile them all.

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

As Etan Reisner said in the comment section, make already has implicit rules to compile .c and .cpp file, so the real answer to your question is:

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

Do not write anything to compile your object files.

不要编写任何代码来编译对象文件。

That said, you should now remove those two variables: $(GXX) and $(GXXFLAGS).

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

To provide flags to cc or gcc one should use the CFLAGS built-in variable.
To provide flags to g++ one should use the CXXFLAGS built-in variable.
To provide flags to the preprocessor (cpp) one should use the CPPFLAGS variable.

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

Since you're mixing C and C++ source files, you should use the CXX variable as the linker command.

由于您混合了C和c++源文件,所以应该使用CXX变量作为链接器命令。