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

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)

Related

SFML library doesn't link with makefile compilation

I have been trying to link the SFML dlls to my windows C++ project, but I can't get it to work. I always end up with:
fatal error: SFML/System.hpp: No such file or directory
I've tried a bunch of things but nothing changes the issue.
Here is my makefile:
PROGRAM = zero_flip
OBJS = src/main.o src/Math.o src/card.o src/game_board.o src/indicator.o src/ui.o
CXX = g++
CXX_FLAGS = -O0 -g -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable
LIB_DIRS = -L./Resources/libs/
LIBS = -lsfml-system -lsfml-graphics -lsfml-window -lsfml-audio
LNK_FLAGS = $(LIB_DIRS) $(LIBS)
DEPS=$(OBJS:.o=.d)
.PHONY: all clean
all: $(PROGRAM)
-include $(DEPS)
%.o: %.cpp
$(CXX) $(CXX_FLAGS) $(LNK_FLAGS) $< -o $#
$(PROGRAM): $(OBJS)
$(CXX) $(CXX_FLAGS) $(LNK_FLAGS) $^ -o $#
clean:
rm -f $(OBJS) $(DEPS) $(PROGRAM) && clear
The "./Resources/libs/" directory contains:
openal32.dll
sfml-audio-2.dll
sfml-audio-d-2.dll
sfml-graphics-2.dll
sfml-graphics-d-2.dll
sfml-system-2.dll
sfml-system-d-2.dll
sfml-window-2.dll
sfml-window-d-2.dll
Can anyone get me unstuck please this is driving me mad.
This is wrong:
%.o: %.cpp
$(CXX) $(CXX_FLAGS) $(LNK_FLAGS) $< -o $#
This rule says it will compile a source file into an object file, but the recipe actually builds a complete executable: it will compile the source file like xxx.cpp then link it into a program named xxx.o. You need to invoke just the compiler here, not the linker, so you should not have $(LNK_FLAGS) and you need to add the -c option to tell the compiler to stop after compiling and not link.
Then you need to add an -I option to the compile line telling the compiler where to find the header files needed during compilation... in this case SFML/System.hpp.

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

object files need to be placed in different directory

I would appreciate if anyone could help me with the Makefile error. I would like to compile a C++ application into a shared library and place the compiled object *.o files in ./sobjs directory like below. I followed several examples to do this, however I still have the problem to get this correct compilation and linker.
Makefile:
OBJS = a1.o a2.o a3.o a4.o a5.o
objects = sobj/$(OBJS)
all: $(objects)
$(CXX) $(CXX_FLAGS) $(objects) -shared -o libname.so
$(objects) : | sobjs
sobjs:
#mkdir -p $#
sobjs/%.o: %.cpp
#echo $<
$(CXX) -fPIC -c -o $# $< $(CXX_FLAGS) $(MY_FLAGS) $(INCLUDE_DIRS)
I made a mistake. Replace this
objects = sobj/$(OBJS)
with this
objects = $(patsubst %.o, sobjs/%.o,$(OBJS))
and it will now compile files correctly.

c++ makefile with multiple program, autodetection of source files

I recently lost 5 hours to figure out how I could write the makefile I need. I'm not an informaticien or programmer so I'd like some comments on what I managed to do. I already looked a lot on different sites but still...
I need a makefile that creates different executables: prog1, prog2...
To create the .o files, as I have many files with many dependencies, I don't want to specify them all. So I want/need to use automatic variables with a pattern rule. To speed up the compilation I also take care to only recompile the modified files. I achieved this by using the -MD flag that creates a .d file saved in the $(BUILD) directory.
What I still can't do is to detect automatically which .o files prog1 needs. So for now I have to specify them automatically... If you know how to do that automatically...
I also would like to save the .o files in the $(BUILD) directory, but I can't make it work.
Any advice are welcome !
Thx
CXX = g++
ERRORS = -Wall -Wextra -pedantic
LAPACK = -llapack -lblas
OPTION = -O3 -fopenmp
CXXFLAGS = $(LAPACK) $(ERRORS) $(OPTION)
LDFLAGS = $(LAPACK) $(ERRORS) $(OPTION)
BUILD=build
SRCS=(wildcard *.cpp)
all:prog1 prog2 ...
prog1:prog1.o dep_only_for_prog_1.o dep_for_all_progs.o dep_for_some_progs.o
$(CXX) -o $# $^ $(LDFLAGS) $(NOASSERT)
prog2:prog2.o dep_only_for_prog_2.o dep_for_all_progs.o dep_for_some_progs.o
$(CXX) -o $# $^ $(LDFLAGS) $(NOASSERT)
...
%.o:%.cpp
$(CXX) -MD -c $(CXXFLAGS) $(NOASSERT) $< -o $#
mv $(<:.cpp=.d) $(BUILD)
-include $(addprefix $(BUILD)/$(SRCS:.cpp=.d))
clean:
rm -f *.o $(BUILD)/*
You just can't get make to infer somehow which files belong to which programs, but you CAN make your makefile simpler to read and update. Also you have a few bad things here, such as adding $(LAPACK) (which contains linker flags) to $(CXXFLAGS) (which are passed to the compiler).
Try:
PROGRAMS = prog1 prog2
prog1_SOURCES = prog1.cpp dep_only_for_prog_1.cpp \
dep_for_all_progs.cpp dep_for_some_progs.cpp
prog2_SOURCES = prog2.cpp dep_only_for_prog_2.cpp \
dep_for_all_progs.cpp dep_for_some_progs.cpp
#----- Don't need to change below here
CXX = g++
ERRORS = -Wall -Wextra -pedantic
LAPACK = -llapack -lblas
OPTION = -O3 -fopenmp
CXXFLAGS = $(ERRORS) $(OPTION)
LDFLAGS = $(LAPACK) $(ERRORS) $(OPTION)
BUILD=build
SRCS := $(wildcard *.cpp)
all: $(PROGRAMS)
.SECONDEXPANSION:
$(PROGRAMS): $$($$#_SOURCES:%.cpp=%.o)
$(CXX) -o $# $^ $(LDFLAGS) $(NOASSERT)
%.o : %.cpp
$(CXX) -MD -c $(CXXFLAGS) $(NOASSERT) $< -o $#
mv $(<:.cpp=.d) $(BUILD)
-include $(addprefix $(BUILD)/$(SRCS:.cpp=.d))
clean:
rm -f *.o $(BUILD)/*
Or you can use eval if you want.