I am currently developing a little C++ package with small code examples for teaching purposes. I managed to write a Makefile like the following that will compile all *.cpp files to *.o files an link them to executables:
CC=gcc
CFLAGS=-g
LDFLAGS= -lstdc++
ECHO = echo
SILENT = @
MODULES = example1 example2 example3
all: $(MODULES)
#a generic rule to create .o files from .cpp files (e.g. example1.cpp -> example1.o)
%.o: %.cpp
$(SILENT) $(ECHO) "--- Compiling $< ---"
$(SILENT) $(CC) -c $(CFLAGS) $<
#define targets and their dependencies
example1: example1.o
$(SILENT) $(ECHO) "--- Linking $@ ---"
$(SILENT) $(CC) $^ -o $@ $(LDFLAGS)
example2: example2.o
$(SILENT) $(ECHO) "--- Linking $@ ---"
$(SILENT) $(CC) $^ -o $@ $(LDFLAGS)
example3: example3.o
$(SILENT) $(ECHO) "--- Linking $@ ---"
$(SILENT) $(CC) $^ -o $@ $(LDFLAGS)
clean:
$(SILENT) $(ECHO) "--- Removing object files and binaries ---"
$(SILENT) rm -f *.o
$(SILENT) rm -f $(MODULES)
.PHONY: clean
So far so good, this works well. It will take example1.cpp, example2.cpp and example3.cpp and compile / link it to 3 executables "example1 example2 example3".
But since every executable has the same name as the object (e.g. "example1.o" will be linked to executable "example1"), I wonder if there is a way to use a generic rule as well.
I tried several things like:
%: %.o
$(SILENT) $(ECHO) "--- Linking $@ ---"
$(SILENT) $(CC) $^ -o $@ $(LDFLAGS)
From my understanding, this rule should take all object files and create an executable with the same name as the object file, but I could not get it working! Does anyone have a hint how to achieve this?
Here is the solution:
In the examples above I do not make Use of the $(LDLIBS) variable, which is used by the built-in default rule. If I change my Makefile to use $(LDLIBS) instead of $(LDFLAGS), everything is fine!
Solution #1: (built-in rule)
CC=gcc
CFLAGS=-g -fopenmp
LDFLAGS=
LDLIBS = -lstdc++ -lgomp
ECHO = echo
SILENT = @
MODULES = example1 example2 example3
all: $(MODULES)
clean:
$(SILENT) $(ECHO) "--- Removing object files and binaries ---"
$(SILENT) rm -f *.o
$(SILENT) rm -f $(MODULES)
.PHONY: clean
Solution #2: (user defined rules)
CC=gcc
CFLAGS=-g -fopenmp
LDFLAGS=
LDLIBS = -lstdc++ -lgomp
ECHO = echo
SILENT = @
MODULES = example1 example2 example3
all: $(MODULES)
#disable built-in rule
%: %.cpp
#rule for *.cpp -> *.o
%.o: %.cpp
$(SILENT) $(ECHO) "--- Compiling $< ---"
$(SILENT) $(CC) -c $(CFLAGS) $(LDFLAGS) $<
#rule for object -> exectutable
%: %.o
$(SILENT) $(ECHO) "--- Linking $@ ---"
$(SILENT) $(CC) $^ $(LDLIBS) -o $@
clean:
$(SILENT) $(ECHO) "--- Removing object files and binaries ---"
$(SILENT) rm -f *.o
$(SILENT) rm -f $(MODULES)
.PHONY: clean