GNU Make seperate out some cpp and compile it differently - c++

CC=g++
CFLAGS=-I
GCCCOMPFLAGS=-Wall -Wextra -O -ansi -pedantic -fpic -shared -c
GCCLINKFLAGS=-shared
DEPS = ./src/a.h ./src/b.h
OBJ = a.o b.o
CPPOBJ = mycpp.cpp
%.o: ./src/%.cpp $(DEPS)
$(CC) -DTARGET_OS_LINUX $(GCCCOMPFLAGS) -o $# $<
final: $(OBJ)
$(CC) -DTARGET_OS_LINUX $(GCCLINKFLAGS) -o ./src/$#.so $^
<newtarget>:
$(CC) -std=gnu++0x ..... -o mycpp.o mycpp.cpp
How to compile mycpp.cpp with different gcc option and add it to "final" linking target
Now I want compile a new file "mycpp.cpp" with different GCC options and add it to the final target to link together.
%.o: ./src/%.cpp $(DEPS)
$(CC) -DTARGET_OS_LINUX $(GCCCOMPFLAGS) -o $# $<
final: $(OBJ) mycpp.o
$(CC) -DTARGET_OS_LINUX $(GCCLINKFLAGS) -o ./src/$#.so $^
mycpp.o:
compile ...
This will make mycpp getting handled by the wild card %.o
How do we separate this build targets ?

Target-specific variables are fully explained in the GNU make documentation, which you should consult for additional information. In the Makefile:
mycpp.o: VARIABLE=X
This sets a variable within the scope of a single target only. Using this you can override CPPFLAGS, or any other variables, when building a specific target only.
Finally, for situations where more than just a variable needs to be overridden, you can always specify an explicit rule:
mycpp.o: ./src/mycpp.cpp
[ build instructions ]
that will override the default rule for building .o from .cpp.

Related

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

Confused how my Makefile is remaking object files

My make file is failing to find my include directory when it tries to remake object files. For example, when I call make tests I get the output:
g++ -c -o sdl_class.o sdl_class.cpp
sdl_class.cpp:9:23: fatal error: sdl_class.h: No such file or directory
#include <sdl_class.h>
^
compilation terminated.
make: *** [sdl_class.o] Error 1
My Makefile is this:
#Originally from: http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
#But will be heavily modified
IDIR =../include
CC=g++
CFLAGS=-w -I$(IDIR)
#ODIR=obj
LDIR =../lib
LIBS=-lSDL2
_DEPS = sdl_class.h SDL_image.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
OBJ = sdl_class.o tests.o
#OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
%.o: %.cpp $(DEPS)
$(CC) -c -o $# $< $(CFLAGS) $(LIBS)
tests: sdl_class.o tests.o
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
all: $(OBJ)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f *.o *~ core $(IDIR)/*~
My understanding is that when I call make tests, that it should attempt to remake the sdl_class.o file. This should then call the %.o rule, which should try to make the object file by calling something like:
g++ -c -o sdl_class.o sdl_class.cpp -w -I../include -lSDL2
However, this is not the case as it looks like it is calling $(CC) -c -o $# $< $(CFLAGS) $(LIBS), as you can see from above.
Do I have a fundamental misunderstanding about how make builds its rules? Seems likely, this is my first Makefile. Perhaps I am confused on how compilation works in general, as I'm somewhat new to that as well.
I would say that the problem is that one or more of the files ../include/sdl_class.h or ../include/SDL_image.h does not exist. Because of that, make is deciding that your pattern rule does not match (because not all the prerequisites can be found or made) and it defaults to the built-in rule to create object files from .cpp files.
The built-in rules use the make variables CXX for the C++ compiler and CXXFLAGS for the C++ flags: the CC and CFLAGS variables are used for the C compiler. That's why your settings for CFLAGS are being ignored.
If you run make -d sdl_class.o you'll see which file make is looking for and why it decides to not use your pattern rule.
If you rewrite your rules like this it will work better:
%.o: %.cpp
$(CC) -c -o $# $< $(CFLAGS)
sdl_class.o tests.o: $(DEPS)
because make will now complain that the relevant files can't be found or created.
There are other issues, of course. You shouldn't be passing $(LIBS) to your compile command; that belongs only in your link line. And, you should probably stick to the standard variables CXX for the C++ compiler, CPPFLAGS for preprocessor flags like -I and -D, and CXXFLAGS for C++ compiler flags. Also, linker library flags like -L../lib go in LDFLAGS and linker libraries like -lSDL2 go in LDLIBS.
CC/CCFLAGS are for C compilation. You should use CXX and CXXFLAGS for C++. They are used in built-in rules and in the LINK.cc macro, making the Makefile much simpler, and thus less error prone.
CXXFLAGS = -Wall ...
prog : foo.o bar.o
$(LINK.cc) -o $# $^
see Default linker setting in Makefile for linking C++ object files

How to link multiple .so files in a C++ Makefile

My Makefile looks as follows:
CXX = g++
CXXFLAGS = -g
INCLUDES = -Iinclude/
OBJS = a1.o \
b1.o
LIBPATH= /usr/lib/<arch>
test-app:$(OBJS)
$(CXX) -o $# $(OBJS)
%.o : %.cpp
$(CXX) $(INCLUDES) -c $(CXXFLAGS) $< -o $#
I want to link two files lib1.so and lib2.so present in LIBPATH? Can anyone please help me with the syntax?
The syntax is
test-app:$(OBJS)
$(CXX) -o $# $(OBJS) -Lpath_to_your_lib -lyour_libname
Also you should use pkg-config to find those variables value.
Try this one:
LIBRARIES= -llib1 -llib2
...
test-app:$(OBJS)
$(CXX) -o $# -L$(LIBPATH) $(LIBRARIES) $(OBJS)
Consider that the arguments order are most of times important since the gcc compiler/linker process the files just one time in the given order and if the order was wrong errors like "Symbol not find" and "undefined reference" will be produced.
Though, I strongly recommend CMake since it's syntax is so easier, more dynamic and It supports many build platforms (IDEs, Compilers, Makefiles, etc.)
Update:
This configuration is likely more effective than the above:
SHARED_LIBRARIES= -L/path/to/shared_libs -llib1 -llib2
STATIC_LIBRARIES= -L/path/to/static_libs -llib1 -llib2 -L/another/path/to/static_libs -llib3
...
test-app:$(OBJS)
$(CXX) -o $# $(STATIC_LIBRARIES) $(SHARED_LIBRARIES) $(OBJS)

Writing a makefile to use -D_GLIBCXX_DEBUG in debug build

I have a makefile that can be reduced to this:
OBJS = obj1.o obj2.o
FLAGS = -Wall -Wextra -Werror -pedantic-errors -fno-rtti -std=c++0x
DEBUG_FLAGS = -ggdb -O0 -fstack-protector-all -D_GLIBCXX_DEBUG
RELEASE_FLAGS = -O3
release: $(OBJS)
g++ $(FLAGS) $(RELEASE_FLAGS) $(OBJS)
debug: $(OBJS)
g++ $(FLAGS) $(DEBUG_FLAGS) $(OBJS)
obj1.o: obj1.cpp
g++ -c $(FLAGS) obj1.cpp
obj2.o: obj2.cpp
g++ -c $(FLAGS) obj2.cpp
The problem is that all or none of the files must be built with the -D_GLIBCXX_DEBUG flag. I don't know how to do this without writing two entries for every compilation unit, like
obj1_release.o: obj1.cpp
g++ -c $(FLAGS) $(RELEASE_FLAGS) obj1.cpp
obj1_debug.o: obj1.cpp
g++ -c $(FLAGS) $(DEBUG_FLAGS) obj1.cpp
How can I make the -D_GLIBCXX_DEBUG flag (and the other debug flags) take effect for all compilation units only when the user types make debug without writing two entries for every CU? (And vice versa; the release flags need to take effect on all CUs when the user types make release.)
I apologise if this is the basics of writing Makefiles, I don't know much about them.
You are looking for pattern rules: something like this should do what you want. Note that this cannot be made to work correctly unless the debug and release versions of the program are given different names.
OBJS := obj1 obj2 obj3
R_OBJS := $(OBJS:=_r.o)
D_OBJS := $(OBJS:=_d.o)
all: prog_r prog_d
release: prog_r
debug: prog_d
prog_r: $(R_OBJS)
$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) $(LDFLAGS) $^ $(LIBS) -o $#
prog_d: $(D_OBJS)
$(CXX) $(CXXFLAGS) $(DEBUG_FLAGS) $(LDFLAGS) $^ $(LIBS) -o $#
%_r.o: %.cc
$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) -c $< -o $#
%_d.o: %.cc
$(CXX) $(CXXFLAGS) $(DEBUG_FLAGS) -c $< -o $#
# header files
obj1_d.o obj1_r.o: foo.h bar.h
obj2_d.o obj2_r.o: quux.h
# ... etc ...
There is a pretty straightforward way to select compilation flags based on the type of the build in Makefiles.
In addition to that you may like to ensure that debug build only links debug object files and same for release (i.e. no mixing debug and release object files). To achieve that compile object into different directories depending on the build type.
This might help : http://sunsite.ualberta.ca/Documentation/Gnu/make-3.79/html_chapter/make_7.html
You could check the first argument (debug/release) and set the CFLAGS accordingly.
HTH.

Creating two separate executables from a makefile (g++)

Currently, I have my makefile set up to compile and make a fairly large project. I have written a second cpp file with main function for running tests. I want these to run separately, but build together and they use the same files. How is this accomplished?
edit: As reference, here is my current makefile. I'm not sure how to adjust it.
CC=g++
CFLAGS=-c -Wall -DDEBUG -g
LDFLAGS=
SOURCES=main.cpp Foo.cpp Bar.cpp Test.cpp A.cpp B.cpp C.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=myprogram
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
Normally you would just have multiple targets and do something like this:
.PHONY: all target tests
all: target tests
target: ...
...
tests: ...
...
Then you can just make (defaults to make all), or just make target or make tests as needed.
So for your makefile example above you might want to have something like this:
CC = g++
CFLAGS = -c -Wall -DDEBUG -g
LDFLAGS =
COMMON_SOURCES = Foo.cpp Bar.cpp A.cpp B.cpp C.cpp
TARGET_SOURCES = main.cpp
TEST_SOURCES = test_main.cpp
COMMON_OBJECTS = $(COMMON_SOURCES:.cpp=.o)
TARGET_OBJECTS = $(TARGET_SOURCES:.cpp=.o)
TEST_OBJECTS = $(TEST_SOURCES:.cpp=.o)
EXECUTABLE = myprogram
TEST_EXECUTABLE = mytestprogram
.PHONY: all target tests
all: target tests
target: $(EXECUTABLE)
tests: $(TEST_EXECUTABLE)
$(EXECUTABLE): $(COMMON_OBJECTS) $(TARGET_OBJECTS)
$(CC) $(LDFLAGS) $^ -o $#
$(TEST_EXECUTABLE): $(COMMON_OBJECTS) $(TEST_OBJECTS)
$(CC) $(LDFLAGS) $^ -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
Here's one way to do it:
CXXFLAGS += -std=c++11 -Wall -O3
all: myprog mytest
myprog.cpp: main.cpp
cp -vf $< $#
myprog: myprog.o Foo.o Bar.o Test.o A.o B.o C.o
mytest.cpp: main.cpp
cp -vf $< $#
mytest.o: CPPFLAGS += -DDEBUG
mytest.o: CXXFLAGS += -O0 -g
mytest: mytest.o Foo.o Bar.o Test.o A.o B.o C.o
This works because built-in rules exist for compiling objects from c++ source (%.o: %.cpp) and linking main programs (%: %.o).
Also note the use of target-specific values for the variables CPPFLAGS and CXXFLAGS.