Conditional statements in makefile - makefile

I've a directive defined in C++ code _2G_MYSQL_ which includes other mysql files when defined.
And I want to use specific libraries only when this token is defined in the code. Is there a way to so this in Makefile.
something like,
ifdef _2G_MYSQL_
LIBS = -lstdc++ -lmysqlclient -lz -lcrypt -lnsl -lssl -lcrypto -ldl -lm -lMst_main -lAMR_Reject_DSP -lFalseReject -lMStream_setting
else
LIBS = -lm -lMst_main -lAMR_Reject_DSP -lFalseReject -lMStream_setting
endif
This obviously doesnt work because the token is in the header file and not in the makefile. Any suggestions ? Thank you !

If you use gcc (and the usual text tools), you could do it in the following way:
SYMBOL=_2G_MYSQL_
MAINFILE=myfile.c
CHECK=$(shell gcc -E -dD $(MAINFILE) | grep $(SYMBOL))
ifeq ($(findstring define $(SYMBOL), $(CHECK)),define $(SYMBOL))
LIBS=-lstdc++ -lmysqlclient ....
else
LIBS=-lm -lMst_main ...
endif

Related

How to translate this command into a makefile file?

gcc testr.c -L/usr/local/hdf/hdf5/lib /usr/local/hdf/hdf5/lib/libhdf5_hl.a /usr/local/hdf/hdf5/lib/libhdf5.a -ldl -lstdc++ -lm -Wl,-rpath -Wl,/usr/local/hdf/hdf5/lib -I /usr/local/hdf/hdf5/include
there is a source file named testr.c, above is the command, and the below is my unfinished example.
LIB=-L/usr/local/hdf/hdf5/lib
INC=-I/usr/local/hdf/hdf5/include
testr: testr.c
gcc -o testr testr.c -I.
Let's start with the simplest conversion possible:
something:
gcc testr.c -L/usr/local/hdf/hdf5/lib /usr/local/hdf/hdf5/lib/libhdf5_hl.a /usr/local/hdf/hdf5/lib/libhdf5.a -ldl -lstdc++ -lm -Wl,-rpath -Wl,/usr/local/hdf/hdf5/lib -I /usr/local/hdf/hdf5/include
We notice that usr/local/hdf/hdf5 comes up a lot, so we put that in a variable:
HDF5 := /usr/local/hdf/hdf5
something:
gcc testr.c -L$(HDF5)/lib $(HDF5)/lib/libhdf5_hl.a $(HDF5)/lib/libhdf5.a -ldl -lstdc++ -lm -Wl,-rpath -Wl,$(HDF5)/lib -I $(HDF5)/include
Now it's clear that you can invoke the static libraries in a more concise way:
something:
gcc testr.c -L$(HDF5)/lib -lhdf5_hl -lhdf5 -ldl -lstdc++ -lm -Wl,-rpath -Wl,$(HDF5)/lib -I $(HDF5)/include
And clearly the intended target is testr, and the source ought to be a prerequisite:
testr: testr.c
gcc testr.c -L$(HDF5)/lib -lhdf5_hl -lhdf5 -ldl -lstdc++ -lm -Wl,-rpath -Wl,$(HDF5)/lib -I $(HDF5)/include
Add a couple of automatic variables:
testr: testr.c
gcc $< -o $# -L$(HDF5)/lib -lhdf5_hl -lhdf5 -ldl -lstdc++ -lm -Wl,-rpath -Wl,$(HDF5)/lib -I $(HDF5)/include
That's a pretty good rule. We could go a little further, depending on what other targets you'd like Make to build, but that should be enough for now. Don't forget to test each step of the above, before you adopt the final version.
Alternatively, you could use predefined implicit rules and just define appropriate variables and the target:
DIR = /usr/local/hdf/hdf5/
INC = $(DIR)include
LIB = $(DIR)lib
CPPFLAGS = -I$(INC)
LDFLAGS = -L$(LIB) -Wl,-rpath,$(LIB)
LOADLIBES = $(LIB)/libhdf5_hl.a $(LIB)/libhdf5.a
LDLIBS = -ldl -lstdc++ -lm
testr:
Note that this way as well as with Beta's solution, the output file is named testr instead of a.out with your original command.

How do I link static library and dynamic library at the same time?

I have written a makefile like the following:
COMPILER = g++
COMPILER_FLAGS = -c -g -O0 -Wall -w
EXEC=mhu9_mp3
LD = g++
LINKER = g++
mhu9_mp3 : mhu9_mp3.o teapot.o EasyBMP.o
$(LD) teapot.o mhu9_mp3.o EasyBMP.o -L./SOIL/lib -lSOIL -o mhu9_mp3 -L./usr/lib -lGL -lGLU -lglut -lGLEW
teapot.o : teapot.cpp teapot.h
$(COMPILER) $(COMPILER_FLAGS) teapot.cpp
mhu9_mp3.o : mhu9_mp3.cpp teapot.h
$(COMPILER) $(COMPILER_FLAGS) mhu9_mp3.cpp
EasyBMP.o : EasyBMP_1.06/EasyBMP.cpp
$(COMPILER) $(COMPILER_FLAGS) EasyBMP_1.06/EasyBMP.cpp
clean:
-rm -f *.o mhu9_mp3
where libSOIL.a is a static library (I linked it by using "-L./SOIL/lib -lSOIL") and -lGL -lGLU -lglut -lGLEW are dynamic libraries. I have linked them together at the same line. In my cpp file I have a function call that calls a function defined in SOIL.h . However, when I compiled I got this error:
undefined reference to `SOIL_load_image'
I'm pretty sure I have included the header file SOIL.h, and also I have linked in the static library libSOIL.a. So what is the reason for this error? I try adding a -static flag before the -lSOIL but the linker wrongly assumes other dynamics libraries are static. Is there any better ways of linking static and dynamic libraries at the same time?
Put the list of dynamic libraries before the list of static libraries.
Example:
$(LD) -L<path> -l<dynamiclib1> -l<dynamiclib2> -static -l<staticlib1> -l<staticlib2>
Counterpart of -static is -Bdynamic. So if you really have to, it could be something like
ld -o foo foo.o -static -lstaticlib -Bdynamic -ldynamiclib0 -ldynamiclib1
However, this makes sense only when both dynamic and static libraries are present. If only one exists, linker will chose one itself.
In your case, problem may be caused by wrong link order or by the fact that SOIL_load_image is indeed missing (verify it with nm or objdump).

Clang error while creating shared library

I want to compile a shared library on MBP and based on the advise given here, I have switched to clang (from gcc) to create the shared library. My makefile is:
CC = clang
CFLAGS = -c -fPIC -Wall -O3 -lpthread -g
BaseDir = /Users/admin/Prog/
Include = -I$(BaseDir)UMFPACK/Include -I$(BaseDir)AMD/Include -I$(BaseDir)SuiteSparse_config
Lib = -L$(BaseDir)UMFPACK/Lib -L$(BaseDir)AMD/Lib -L$(BaseDir)GotoBLAS2 -L$(BaseDir)SuiteSparse_config
AddFiles = -lumfpack -lamd -lgoto2 -lsuitesparseconfig
StaticLibs = $(BaseDir)GotoBLAS2/libgoto2.a $(BaseDir)UMFPACK/Lib/libumfpack.a $(BaseDir)AMD/Lib/libamd.a $(BaseDir)SuiteSparse_config/libsuitesparseconfig.a
all: TDS.o TDSJac.o ExtraRoutines.o CalcVFC.o TDS.h
$(CC) $(Include) $(Lib) $(AddFiles) -dynamiclib -lpthread -o libTDS.so $^ -lm -g $(StaticLibs)
TDS.o: TDS.c TDS.h
$(CC) $(Include) $(CFLAGS) $^
TDSJac.o: TDSJac.c TDS.h
$(CC) $(CFLAGS) $^
ExtraRoutines.o: ExtraRoutines.c TDS.h
$(CC) $(CFLAGS) $^
CalcVFC.o: CalcVFC.c TDS.h
$(CC) $(CFLAGS) $^
MexFile: TDSGateway.c
mex -g -largeArrayDims -ldl TDSGateway.c
Move:
mv libTDS.so ../../
mv TDSGateway.mexmaci64 ../../
What I do here is:
1) Only compile TDS.c, TDSJac.c, ExtraRoutines.c, and CalcVFC.c to create four corresponding object files.
2) Merging object files and creating a shared library using following command:
clang -I(Some folders) -L(Some folders) -l(Some libraries) -shared -lpthread -o libTDS.so TDS.o TDSJac.o ExtraRoutines.o CalcVFC.o TDS.h -lm -g
clang: error: cannot specify -o when generating multiple output files
As I am absolutely new to clang, I do not know what is wrong with Makefile. (If I replace CC=clang with CC=gcc, everything works good.)
I searched the internet with no success. Manual page of clang says nothing about shared library. I could not even get anything out of clang homepage. It is appreciated if help me to work around this problem.
Thanks for your help in advance.
I had yesterday almost the same problem.
But i never used cmake. I'm using an own makefile system of my company, so I just can tell you, what fixed the problem for me so far.
Clang has still some trouble with giving you the right hints on errorcase.
The linking error was:
/usr/bin/ld: /usr/lib/crt1.o: relocation R_X86_64_32 against `_DYNAMIC' can not be used when making a shared object; recompile with -fPIC
I solved the problem as I figgered out, that the -shared Parameter has to be behind the -o X.o parameters. As I see this is not made in your case, too. You should try that first.
In our case I also had to parse the LFlags with -WL, or -L, (afaik it doesn't matter which one you take but I read about a clang bug in relation to -Wl,).
But idk in how far you have to parse LFlags or not, when using cmake.
You've listed headers (TDS.h) as dependencies, which is fine, but you've then used $^ as inputs, which includes all dependencies. You should not list a header as an input. It should not be on the command-line at all, and in clang this is actually an error.
The error message is obscure but easy to resolve. You have 2 choices:
Be explicit instead of using $^. You could use a variable for inputs and another for dependencies, e.g.; or
Use intermediate .o files instead of .c files as inputs to a .so. The *.o files can depend on any .h they include.

compile with gsl with an existing makefile

i have a makefile for some code library i'm using and now i've added to that code some code that uses gsl. i'm not so sure how and what to add to the makefile (which i wat to keep since it's invoking boost as well) that would invoke gsl.
This is my makefile:
CXX = g++
ARCH = -mtune=generic
# ARCH = -march=core2
# ARCH = -march=native
COFLAGS = $(ARCH) -O3 -pipe
CXXFLAGS = -Wall $(COFLAGS)
PROGRAMS = getData analyzeData
BOOSTFLAGS = -I .
OPENMP = -fopenmp -DSUPPORT_OPENMP
all: $(PROGRAMS)
getData: getData.cpp common.o parse.o common.h
$(CXX) $(CXXFLAGS) getData.cpp common.o parse.o -o getData
analyzeData: analyzeData.cpp common.o parse.o parameters.o
$(CXX) $(CXXFLAGS) $(BOOSTFLAGS) $(OPENMP) estimateCrossReplicatesExpression.cpp common.o parse.o parameters.o -o analyzeData
parameters.o: parameters.cpp parameters.h
parse.o: parse.cpp parse.h
common.o: common.cpp common.h
clean:
rm *.o $(PROGRAMS)
In case GSL is installed on the default path (/usr/local/include/gsl) on your system, the compilation command for a source file "example.c" would be
gcc -Wall -I/usr/local/include -c example.c
The library is installed as a single file, libgsl.a. A shared version of the library libgsl.so is also installed on systems that support shared libraries. The default location of these files is /usr/local/lib. If this directory is not on the standard search path of your linker you will also need to provide its location as a command line flag.
To link against the library you need to specify both the main library and a supporting cblas library, which provides standard basic linear algebra subroutines. A suitable cblas implementation is provided in the library libgslcblas.a if your system does not provide one. The following example shows how to link an application with the library,
$ gcc -L/usr/local/lib example.o -lgsl -lgslcblas -lm
The option -lm links with the system math library. On some systems it is not needed.
Thus, you need to specify the gsl specific flags in your compile command. Update the Makefile accordingly.

compiling using libnids

I have been trying to install libnids (Ubuntu LTS and Mac OS X) all the day and now I know how to compile programs with it.
I write this here because there is not much documentation but there are samples in the libnids downloaded folder with a makefile. The important things of this makefile are these:
CC = gcc
PCAPLIB = -lpcap
LNETLIB = -lnet
LIBS = -L../src -lnids $(PCAPLIB) $(LNETLIB) -lgthread-2.0 -lnsl
example:
$(CC) example.c -o example $(LIBS)
And if you're compiling it in Mac OS X ignore this: -lgthread-2.0 -lnsl -L../src
But I don't know if something stop to works because of these omitted things.
I found it. The best way is to compile the library and then use local reference to the ".a" file.
Makefile example
CC = gcc -g -Wall
GLIB = `pkg-config --cflags --libs glib-2.0`
PCAPLIB = -lpcap
LNETLIB = -lnet
LIBS_SRC = libnids-1.24/src/libnids.a
LIBS = $(PCAPLIB) $(LNETLIB) -lgthread-2.0
program: program.c
$(CC) -c $(CFLAGS) program.c -o program.o $(GLIB) $(LIBS)
$(CC) program.o -o program $(LIBS_SRC) $(GLIB) $(LIBS)
But if you want to compile the library and install it into your system you got to use -lnids instead of the above way. But the first solution always works.
I got errors when compiling samples under libnids:
gcc -o overflows overflows.o -L../src -lnids -lpcap -lnet -lgthread-2.0 -lnsl ../src/libnids.a
/usr/bin/ld: ../src/libnids.a(libnids.o): undefined reference to symbol 'g_async_queue_pop'
/lib/x86_64-linux-gnu/libglib-2.0.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make: * [overflows] Error 1
You recommendation
GLIB = `pkg-config --cflags --libs glib-2.0`
solves my problem.
PS: my system Ubuntu 13.10. 64bit.

Resources