How to "override pkg-config" by setting MYLIB_LIBS and MYLIB_CFLAGS? - build

I'm trying to build some program which uses GNU autotools on a Unix-like OS. It needs some library which my OS distribution doesn't have, say mylib, so I download, build and install that library under /opt/mylib.
Now, I want to tell the configure script to use mylib under /opt/mylib, but it doesn't have a command-line option such as --mylib-location=. However, configure --help tells me:
Some influential environment variables:
... snip ...
MYLIB_CFLAGS C compiler flags for mylib, overriding pkg-config
MYLIB_LIBS linker flags for mylib, overriding pkg-config
... snip ...
I'm guessing these are shell variables I need to set. But - what exactly do I need to set them to?

These variables are expanded in the command-line for compilation and for linking respectively. So, typically, the _CFLAGS would need to indicate an include file search path and _LIBS would need to tell the linker to use the library, plus indicate a search path for it.
In your specific case, and assuming typical layout of /opt/mylibs, you need to set:
MYLIB_CFLAGS=-I/opt/mylib/include
MYLIB_LIBS="-L/opt/mylib/lib -lmylib"
and that should do it. The text about "overriding pkg-config" is due to how pkg-config is used as the default for obtaining these flags. Example (for the PNG library and on my system):
# pkg-config --cflags libpng
-I/usr/include/libpng16
# pkg-config --libs libpng
-lpng16 -lz
pkg-config has search paths configured for include and library directories, plus a repository of .pc files etc., with which it determines the system location of various libraries/packages.

Related

C++ using functions from shared library

I have the following problem:
I have two separate c++ projects, and want to use certain functions from one of them in the other. I am compiling using g++, on Linux.
I decided to do this by creating a shared library out of the project from which to use the functions. I added -fPIC to the compiler flags in the Makefile and then created a shared library like this:
g++ -shared -Wl,-soname,libmyproject.so.1 -o libmyproject.so a.o b.o c.o -lc
Then I simply copied the .so file and the header files into the (parent) directory of the new project and added the following to its Makefile:
To LIBS:
-L/../external_proj/libmyproject.so
To CXXFLAGS:
-I/../external_proj
Then I #include the appropriate header file in the destination project code and try to call certain functions from the original project. However, when I compile the destination project I get an error "undefined reference" for the imported function.
My question is then: is there something I'm missing in this setup? Is there perhaps something that needs to be added to the headers in the original project in order to export the functions I want to use?
I should note this is the first time I have attempted to use a shared library in this way. Thanks.
The -L option only specifies the directory where the linker will search for libraries to link with. Then you will need to use the -l option to specify the base name of the shared library (without the "lib" prefix and the ".so" suffix).
But even that will unlikely to be enough. The runtime loader needs to find the shared library, when you attempt to try to execute it. -L and -l will be sufficient to successfully link, but the runtime loader only searches /usr/lib(64)?, and a few other places by default. It does NOT search the current directory, and the ELF binary only records the names of the shared libraries that must be loaded, and not their full pathnames. You have to explicitly record any extra directories to search for any shared libraries, which is the -rpath option.
To finish the job you will also need to pass -rpath to the linker, but g++ does not support this option directory, you will have to use -W to do that.
The full set of options you will likely need are:
-L/../external_proj -lmyproject -Wl,-rpath -Wl,`cd ../external_proj && pwd`
See gcc documentation for more information on the -W option.
Absolute pathnames should be used with -rpath, hence the need to obtain the full pathname to the directory where the shared library is.
The -L flag is to add a path to search libraries in. The -l (lower-case L) is for linking with a library in the search path.
Or you can skip the flags and link with the library directly, almost like you do now (but without the -L option).
If you use the -l option, then remember that for a file libname.so you use only name as the library name. As in -lname. The linker will search for the correct files with the added prefix and suffix.
And lastly an important note about the paths used when linking: If you use -L and -l to link with a shared library, it's only the linker which will find the library. The OS runtime-loader will not be able to see the path used and will not find the library, if it's in a non-standard location. For that you must also set the runtime-path using the special linker option -rpath.
Unfortunately the GCC frontend program g++ doesn't recognize that option, you have to use -Wl to tell g++ to pass on an option to the actual linker. As in -Wl,-rpath,/path/to/libraries.
To summarize, here are the different variants you can use:
Link directly with the library: g++ your_source.cpp ../external_proj/libmyproject.so
Use the -L and -l options: g++ your_source.cpp -L../external_proj -lmyproject
To set the runtime linker path: g++ your_source.cpp -L../external_proj -lmyproject -Wl,-rpath,../external_proj

C++ where are the flags for linking libraries documented?

With every new library I want to use I have noticed there is a specific flag, or set of flags, I have to add to the compile in order for it to actually link the library.
For example with GL GLEW and GLUT I use "-lglut -lGLU -lGL".
The problem is the only way to find these flags that I need is to search endlessly on google for them. Is there a 'standard' place to find these flags for any library? Are they appended to the tops of the headers or something? I hope it's just something obvious I'm missing.
Typically, you develop an intuition for discovering these things on the platforms you develop for. It does suck.
For example, on my Debian development system, I would start by checking pkg-config for the library I want.
pkg-config --list-all | less -i
It looks like there's a package named gl. So, you can get the linker flags using pkg-config:
pkg-config --libs gl
pkg-config --cflags gl
Then you can put that into your Makefile:
gl_cflags := $(shell pkg-config --cflags gl)
gl_libs := $(shell pkg-config --libs gl)
override CFLAGS += $(gl_cflags)
override LIBS += $(gl_libs)
my_app: my_app.o
$(CC) $(LDFLAGS) -o $# $^ (LIBS)
This doesn't work for all libraries, only those with .pc files installed. For example, it won't work for LibJPEG. In these cases, you would either remember the flags (-ljpeg) or you would use an Autoconf / CMake / etc. configuration script to discover the flags at configuration time.
And, none of this will work at all if you don't have the development versions of your libraries installed.
sudo apt-get install libgl1-mesa-dev
P.S. GLU is a bit obsolete.
I'll assume you are asking about GCC/G++ compiler.
The flag is -l<libName>, where <libName> is the name of the library you want to link against. For example, -lGL links against the GL library.
The reason some libraries require multiple flags in certain order is simply the way they depend on each other (the libraries your library depends on might also depend on some other ones, and so on). The library's documentation should solve the problem in most cases.

LEDA library(C++ library) setup linux

I want to set up LEDA library in my system.
I have downloaded LEDA library from the following link
http://www.algorithmic-solutions.info/free/d5.php
Instruction given in read me file
2. Preparations
---------------
Unpacking the LEDA distribution file
LEDA---.tar.gz will create the LEDA root
directory "LEDA---". You might want to rename
it or move it to some different place. Let denote the final
complete path name of the LEDA root directory.
To install and use the Unix object code of LEDA you have to modify
your environment as follows:
a) LEDAROOT:
Set the environment variable LEDAROOT to the LEDA root directory:
csh/tcsh: setenv LEDAROOT
sh/bash: LEDAROOT=
export LEDAROOT
b) Command Search Path:
Include $LEDAROOT/Manual/cmd into your command search path
(environment variable path (csh) or PATH (sh)) and call rehash (if
required by your system).
c) Shared Library: (for solaris, linux, irix, osf1)
If you planning to use shared libraries include $LEDAROOT into the
LD_LIBRARY_PATH search path. Then go to $LEDAROOT and type
make shared. This will construct the shared libraries from the static
libraries.
Please note: Building the shared library is not supported on each
platform.
d) xlman and demos: Go to $LEDAROOT and type make xlman to compile
and link LEDA's interactive manual reader xlman. Now you can start
xlman for reading and printing manual pages, starting demo programs
and browsing more release notes.
3. Compiling and linking application programs
---------------------------------------------
a) Use the -I compiler flag to tell the compiler where to find the
LEDA header files.
CC (g++) -I$LEDAROOT/incl -c file.c
b) Use the -L compiler flag to tell the compiler where to find the
library (libleda.a/so)
CC (g++) -L$LEDAROOT file.o -lleda -lX11 -lm
If using windows on solaris systems you might have to link
with the system socket library and the network services library as
well:
CC (g++) ... -lleda -lX11 -lsocket -lnsl -lm
c) Compile and link simultaneously with
CC (g++) -I$LEDAROOT/incl -L$LEDAROOT file.c -lleda -lX11 -lm
You may want to ask your system adminstrator to install the header
files and library in the system's default directories.
Then you no longer have to specify header and library search paths on
the compiler command line.
I followed these instruction but I got error in command
> make xlman
error
coredump#coredump-VPCCB15FG:~/Documents/LEDA$ make xlman
make -C demo/xlman
make: *** demo/xlman: No such file or directory. Stop.
make: *** [xlman] Error 2
someone please help me to setup library.
NOTE: For the free version of the Leda library, you don't have to build the package to use the library. It simply doesn't work.
To use the library simply include it in your compile line and linker.
If you are compiling from the shell (assuming you are using Linux), do the following:
1. Set the env variable to the library folder e.g export LEDAROOT= /path/to/Leda
2. Set the LD_LIBRARY_PATH env variable e.g export LD_LIBRARY_PATH=$LEDAROOT
Verify that this variables are set then you can compile and link and run. You can simply do
CC (g++) -I$LEDAROOT/incl -L$LEDAROOT file.c -lleda -lX11 -lm
With this you should be good to go.
If you are using an IDE, simply add the include path (i.e /path/to/leda) to you project settings.
This is all you have to do. Building the library does not work. Simply include it

Static and Dynamic/Shared Linking with MinGW

I want to start with a simple linking usage to explain my problem. Lets assume that there is a library z which could be compiled to shared library libz.dll(D:/libs/z/shared/libz.dll) or to static library libz.a (D:/libs/z/static/libz.a).
Let I want to link against it, then I do this:
gcc -o main.exe main.o -LD:/libs/z/static -lz
According to this documentation, gcc would search for libz.a, which is
archive files whose members are object files
I also can do the following:
gcc -o main.exe main.o -LD:/libs/z/shared -lz
It is not mentioned in the documentation above that -l flag will search for lib<name>.so.
What will happen if I libz.a and libz.dll will be in the same directory? How the library will be linked with a program? Why I need the flags -Wl,-Bstatic and -Wl,-Bdynamic if -l searches both for shared and static libraries?
Why some developers provide .a files with .dll files for the same modules, if I compile a shared library distribution?
For example, Qt provides .dll files in bin directory with .a files in lib directory. Is it the same library, but built like shared and static, respectively? Or .a files are some kind of dummy libraries which provide linking with shared libraries, where there are real library implementations?
Another example is OpenGL library on Windows. Why every compiler must provide the static OpenGL lib like libopengl32.a in MingW?
What are files with .dll.a and .la extensions used for?
P.S. There are a lot of questions here, but I think each one depends on the previous one and there is no need to split them into several questions.
Please, have a look at ld and WIN32 (cygwin/mingw). Especially, the direct linking to a dll section for more information on the behavior of -l flag on Windows ports of LD. Extract:
For instance, when ld is called with the argument -lxxx it will attempt to find, in the first directory of its search path,
libxxx.dll.a
xxx.dll.a
libxxx.a
cygxxx.dll (*)
libxxx.dll
xxx.dll
before moving on to the next directory in the search path.
(*) Actually, this is not cygxxx.dll but in fact is <prefix>xxx.dll, where <prefix> is set by the ld option -dll-search-prefix=<prefix>. In the case of cygwin, the standard gcc spec file includes -dll-search-prefix=cyg, so in effect we actually search for cygxxx.dll.
NOTE: If you have ever built Boost with MinGW, you probably recall that the naming of Boost libraries exactly obeys the pattern described in the link above.
In the past there were issues in MinGW with direct linking to *.dll, so it was advised to create a static library lib*.a with exported symbols from *.dll and link against it instead. The link to this MinGW wiki page is now dead, so I assume that it should be fine to link directly against *.dll now. Furthermore, I did it myself several times with the latest MinGW-w64 distribution, and had no issues, yet.
You need link flags -Wl,-Bstatic and -Wl,-Bdynamic because sometimes you want to force static linking, for example, when the dynamic library with the same name is also present in a search path:
gcc object1.o object2.o -lMyLib2 -Wl,-Bstatic -lMyLib1 -Wl,-Bdynamic -o output
The above snippet guarantees that the default linking priority of -l flag is overridden for MyLib1, i.e. even if MyLib1.dll is present in the search path, LD will choose libMyLib1.a to link against. Notice that for MyLib2 LD will again prefer the dynamic version.
NOTE: If MyLib2 depends on MyLib1, then MyLib1 is dynamically linked too, regardless of -Wl,-Bstatic (i.e. it is ignored in this case). To prevent this you would have to link MyLib2 statically too.

eclipse cdt: add include path from pkg-config

i want to add a dynamic configuration path (generated from pkg-config) to my project. (this is basically for third-party dependencies like boost, so workspace includes is not appropiate, and filesystem include neither because that would be hardcoded and every developer would have to change that manually)
i am on project properties->c++ general->paths and symbols->includes tab->add...->add directory path->variables but i can only select among existing variables, how do i create a new variable dynamically generated from a command line program? like pkg-config --cflags boost-1.43?
this is easy to do in netbeans; you just add the pkg-config commandline with the backquotes in the build additional options and it resolves the build include and even in theory it should update the indexer (although truth be said, last time the indexer was correctly updating from pkg-config was on netbeans 6.8, it has been broken on 6.9 and 6.9.1)
i read this StackOverflow post but i still not sure how it helps this specific case
i read somewhere that you can use $(shell pkg-config...) to generate environment variables but not sure where to place the command
if there is no easy out of the box solution i'll try the script in this blog post
btw, i'm using eclipse helios -cdt 7
thanks!
Pkg-config support is finally coming to CDT and will be finished on August.
http://code.google.com/p/pkg-config-support-for-eclipse-cdt/
you can use $(shell pkg-config --cflags your_libs) in:
Project properties->C/C++ Build->Settings->"Tools Settings" tab->**C Compiler**->Miscellaneous->Other Flags
and
you can use
$(shell pkg-config **--libs** your_libs)
in
Project properties->C/C++ Build->Settings->"Tools Settings" tab->**C Linker**->Miscellaneous->Other Flags
if the linker doesn't link, make sure (for example in the build console window) that the pkg-config flags appear after the objects to link.
you can do this in properties->C/C++ Build->Settings->"Tools Settings" tab->C Linker->Command line pattern moving ${FLAGS} to the end :
from this (for example) :
${COMMAND} **${FLAGS}** ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} **${INPUTS}**
to this :
${COMMAND} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} **${INPUTS} ${FLAGS}**
In eclipse 4.3.2 at least, it looks as though it's possible to simply add
`pkg-config --libs <mylibname>`
in
Project->Properties->C/C++ Build->Settings->GCC {C|C++} Linker->Miscellaneous->Linker Flags
similarly
`pkg-config --cflags <mylibname>`
in
Project->Properties->C/C++ Build->Settings->GCC {C|C++} Compiler->Miscellaneous->Other Flags
what i found so far is that you can do
project-> properties-> c++ build-> build variables
add a new variable of string type.
Call it whatever you like:
UNITTEST_CPP_CXXFLAGS
then set as its value:
$(shell pkg-config --cflags unittest-cpp)
the go to project properties-> c++ general -> path and symbols,
includes.
Select languages c++, otherwise it defaults to assembly source file.
Click add.
On the add directory path, click variables... (because we want to add the variable we have just created)
type the name of the variable (UNITTEST_CPP_CXXFLAGS), press enter and ok
when you rebuild the result of the shell command is replaced in a -I option (for the gnu gcc toolchain at least), in general pkg-config output might include one or more -I so this won't work. Lets go to c++ build->settings->tool settings->gcc c++ compiler->miscellaneous. In there, add ${UNITTEST_CPP_CXXFLAGS} to the other flags.
now the include will be added, but there is no hope of getting the indexer to browse those include!
Use this link at eclipse help/install new spftware. It installs pkg-config. https://raw.githubusercontent.com/TuononenP/pkg-config.p2/master/site.xml
I did find this link in this webpage. https://groups.google.com/forum/#!topic/pkg-config-support-for-eclipse-cdt/HNblZRTKBQQ