user972014
user972014

Reputation: 3856

Compiling C++ and C files in one makefile

I have a makefile that looks like this:

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.

Any idea?

Upvotes: 2

Views: 8694

Answers (2)

Luis Colorado
Luis Colorado

Reputation: 12708

suppose you have a.cc, b.cc and c.cc, and on the other side, d.c, e.c and 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.

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

.SUFFIXES: .a .b .o

and then use the following rules to compile them to .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.

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

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:

%.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)

Upvotes: 2

Chnossos
Chnossos

Reputation: 10486

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:

Do not write anything to compile your object files.

That said, you should now remove those two variables: $(GXX) and $(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.

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

Upvotes: 0

Related Questions