Looping makefile with multiple main functions - c++

I am trying to write a makefile that can create one executable per main function.
I have a list of files: main1.cpp, main2.cpp, and main3.cpp. They each contain an int main() function. Obviously I can't build these into one exec, which is not the goal here, so how can I build each one of these into its own executable? This is one solution:
main1: main1.cpp
$(CC) -o $# $^
main2: main2.cpp
$(CC) -o $# $^
main3: main3.cpp
$(CC) -o $# $^
But there MUST be a better way to do this. Is there some type of looping feature to makefiles that will make this process easier? Like a for loop?

A mixture of wildcard, patsubst and static pattern rules, plus the standard make variables for C++ compilation and linking:
SRCS := $(wildcard main*.cpp)
EXES := $(patsubst %.cpp,%,$(SRCS))
$(EXES): %: %.cpp
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $# $< $(LDLIBS)
But as make knows already how to make all this you could as well get rid of your Makefile and just type make main1...

While it's not a very sophisticated makefile, your solution is fine for three simple programs. You could make it more generic and support building all three targets at the same time with an "all" target.
all: main1 main2 main3
main1: main1.cpp
$(CC) -o $# $^
main2: main2.cpp
$(CC) -o $# $^
main3: main3.cpp
$(CC) -o $# $^

Related

How can I use different rules in Makefile for two groups of files?

I have one Makefile to build an executable and a library. Executable consists of a lot of source files and library consists of one .cpp file. The difference between compilation of executable and library is -fPIC option.
There is a compilation rule:
%.o : %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $#
all: $(TARGET) $(TARGET_LIB)
$(TARGET): $(OBJS)
$(CXX) $(LDFLAGS) -o $# $^
$(TARGET_LIB): $(LIBOBJS)
$(CXX) $(LDFLAGS) -fPIC -shared -o $# $^
I tried to add compilation rule for library and got this:
lib.o : lib.cpp
$(CXX) -fPIC -c $(CXXFLAGS) $< -o $#
%.o : %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $#
all: $(TARGET) $(TARGET_LIB)
$(TARGET): $(OBJS)
$(CXX) $(LDFLAGS) -o $# $^
$(TARGET_LIB): $(LIBOBJS)
$(CXX) $(LDFLAGS) -fPIC -shared -o $# $^
Unfortunately, only lib is compiled in this case. Second rule is omitted.
How can I use a rule for one file and different rule for group of other files?
If you just run make without a target, the first target gets built. So just put all back at the top and it should work fine.

Do the flags get called when I make this program?

I recently got feedback that my Makefile doesn't call the required flags. This is a snippet of my Makefile.
CXX = g++
CXXFLAGS = -Wall
all: testFacility testCode testRunway testSiteNumber airport distance
testFacility: testFacility.cpp Facility.o gcdistance.o
$(CXX) -o $# $^
Does the flag "-Wall" get called when I type Make?
No, it needs to be referenced directly:
$(CXX) $(CXXFLAGS) -o $# $^
You probably want to define something to compile all those .cpp files too:
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $# $<
testFacility: testFacility.o Facility.o gcdistance.o
$(CXX) $(CXXFLAGS) -o $# $^

Process all files in variable separatly in Makefile

I have multiple source files in a directory, which some are responsible for a main executable, and some are responsible for a shared library, which then in turn is needed for the main executable. Thus I wrote the makefile in the following way:
CC=gcc
CXX=g++
CFLAGS=-I$(DIR) -fPIC -c -fopenmp
CXXLFLAGS=-I$(DIR) -fopenmp -O3 -g -march=native -std=gnu++17 -fPIC -c
CXXFLAGS=-I$(DIR) -fopenmp -O3 -g -march=native -std=gnu++17 -c
LDFLAGS=-lfftw3 -lgomp -lm -larmadillo -lpthread -lX11 -lboost_system -lboost_program_options -L/opt/intel/mkl/lib/intel64 -lmkl_rt
LDMAINFLAGS=-lfftw3 -lgomp -lm -larmadillo -lpthread -lX11 -lboost_system -lboost_program_options -L/opt/intel/mkl/lib/intel64 -lmkl_rt -lpulse_propagation
LIBSOURCES=source/image_processing.cpp source/pulse_propagation.cpp
LIBOBJECTS=source/image_processing.o source/pulse_propagation.o
MAINSOURCES=source/fftw.cpp source/fftw++.cc
MAINOBJECTS=source/fftw.o source/fftw++.o
EXECUTABLE=fftw
LIBRARY=libpulse_propagation.so
.PHONY: default all clean
default: all
all: $(LIBRARY) main
main: $(LIBRARY) $(MAINOBJECTS)
$(CXX) $(LDFLAGS) $(MAINOBJECTS) -o $(EXECUTABLE)
$(LIBRARY): $(LIBOBJECTS)
$(CXX) $(LDFLAGS) -shared $^ -o $#
$(LIBOBJECTS): $(LIBSOURCES)
$(CXX) $(CXXLFLAGS) $^ -o $#
$(MAINOBJECTS): $(MAINSOURCES)
$(CXX) $(CXXFLAGS) $^ -o $#
clean_compile:
rm -f source/*.o
clean:
rm -f source/*.o $(EXECUTABLE) $(LIBRARY)
with everything labeled with a MAIN belonging to the main executable and everything else to the library. I would like to loop over the files in LIBSOURCES/MAINSOURCES and compile each of them. I would prefer if I do not have to use the .cpp.o:-macro, after there are different flags depending if it is a library file or a main file. I tried using $<, which executed the compilation twice (ok), but always used the first value from the variable list. When using $^ instead, both files are used at once, also resulting in an error. How could I else do that?
Your source/fftw++.cc instead of source/fftw++.cpp makes everything uselessly complex. If you can rename it, then the following should do what you want:
$(LIBOBJECTS): CXXFLAGS := $(CXXLFLAGS)
$(LIBOBJECTS) $(MAINOBJECTS): %.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $#
The first line defines the value of variable CXXFLAGS for the $(LIBOBJECTS) targets. The following rule is a static pattern rule that translates into as many rules with one target and one prerequisite only. It is completely different from your rules that declares all source files of one kind as prerequisites of all corresponding object files. Not what you want normally.
If you cannot rename source/fftw++.cc you can split your sources and objects lists:
MAINCPPSOURCES=source/fftw.cpp
MAINCCSOURCES=source/fftw++.cc
MAINCPPOBJECTS=source/fftw.o
MAINCCOBJECTS=source/fftw++.o
$(LIBOBJECTS): CXXFLAGS := $(CXXLFLAGS)
$(LIBOBJECTS) $(MAINCPPOBJECTS): %.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $#
$(MAINCCOBJECTS): %.o: %.cc
$(CXX) $(CXXFLAGS) $< -o $#
Finally, it would probably be better (easier to maintain) if you were computing what can be, instead of hard-wiring it in your Makefile:
MAINCPPOBJECTS = $(patsubst %.cpp,%.o,$(MAINCPPSOURCES))
MAINCCOBJECTS = $(patsubst %.cc,%.o,$(MAINCCSOURCES))
...

How can I make this Makefile more generic?

I'm brushing up on C++ by completing many small programs, each contained in a single cpp file. I also want to learn a little bit more about Makefiles, and decided to write a Makefile that will compile all of my little programs and produce an executable per program. With my current Makefile, I have to:
Append the name to the end of "BINARIES"
Copy the repeated target and replace the target name with the binary name
How can I edit this Makefile to be even more generic, so that I can simply append the name of my new program to the end of "BINARIES" and not have to continue to copy and paste the repeated targets?
BIN=./bin/
SOURCE=./src/
CXX=g++
CXXFLAGS=-g -c -Wall
BINARIES=sums-in-loop sum-in-loop sum-of-two
RM=rm -f
all: sums-in-loop sum-in-loop sum-of-two
sums-in-loop:
$(CXX) $(CXXFLAGS) $(SOURCE)$#.cpp -o $(BIN)$#
sum-in-loop:
$(CXX) $(CXXFLAGS) $(SOURCE)$#.cpp -o $(BIN)$#
sum-of-two:
$(CXX) $(CXXFLAGS) $(SOURCE)$#.cpp -o $(BIN)$#
clean:
$(RM) $(BIN)*
The usual way is to use pattern rules:
BIN=bin
SOURCE=src
CXX=g++
CXXFLAGS=-g -Wall
BINARIES=sums-in-loop sum-in-loop sum-of-two
RM=rm -f
all: $(addprefix $(BIN)/,$(BINARIES))
$(BIN)/%: $(SOURCE)/%.cpp
$(CXX) $(CXXFLAGS) $< -o $#
clean:
$(RM) $(BIN)/*
With loops in Makefile, you can do something like :
$(foreach bin,$(BINARIES),$(CXX) $(CXXFLAGS) $(SOURCE)$(dir).cpp -o $(BIN)$dir;)
You can find some info --> http://www.gnu.org/software/make/manual/make.html#Foreach-Function

GNU makefile rules and dependencies

I've been doing a lot of reading on how to write makefiles to build an application on Linux but I'm massively confused about the many different ways to apparently achieve the same goal.
This is what I have come up with so far to build an archive.
SHELL = /bin/sh
CXX = g++
DEBUG = -g
CXXFLAGS = -std=c++11 -Wall -pedantic #-Wextra
CPPFLAGS = -I. \
-I./include
SOURCES = foo1.cpp \
foo2.cpp \
foo3.cpp
OBJECTS = $(SOURCES:.cpp=.o)
The following rule successfully compiles each source file into an object file and then creates an archive:
libfoo.a: $(OBJECTS)
ar rvcs $# $(OBJECTS)
%.o: src/%.cpp ./include/%.h
$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $# $<
This also does the same thing:
libfoo.a: $(OBJECTS)
ar rvcs $# $(OBJECTS)
$(OBJECTS) : %.o:src/%.cpp
$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $# $<
However, this fails with an error that there is no rule to make target 'foo1.o:%.h
libfoo.a: $(OBJECTS)
ar rvcs $# $(OBJECTS)
$(OBJECTS) : %.o:src/%.cpp %.o:%.h
$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $# $<
Can someone please explain why it doesn't work and which approach is best?
The first option lists the header files as dependencies but the second option doesn't. That is my motivation for the third option.
How do I list the headers as dependencies using options 2 or 3?
TIA
The feature you're using in try #2 and try #3 is static pattern rules and the syntax looks like this:
<targets...> : <target-pattern> : <prerequisites...>
There can only be two colons, not three. You should write your try #3 above as:
$(OBJECTS) : %.o : src/%.cpp %.h
$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $# $<
Note one critical thing: this rule will FAIL if you ever create any .cpp file which does not have an associated .h file. Just sayin'.