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

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.

Related

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

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.

Error loading SDL2 shared libraries while executing program on another pc

I'm trying to compile a program i made using SDL2 to work on others computers (or testing VM in this case).
I've been compiling it with what i think are the correct flags, e.g. g++ main.cpp -o main -lSDL2, however when i try executing it on another Ubuntu installation i get this error.
error while loading shared libraries: libSDL2-2.0.so.0: cannot open shared object file: No such file or directory
From my understanding it's not a problem in my compiling but with how i expect it to work on another Linux installation; I've cross-compiled (using mingw32) and tested it (using a freshly installed VM) on Windows adding the correct dlls with the exe (seems to work fine) and I was expecting for it to work in a similar fashion.
What's the standard in this cases? Should i write a setup scripts to install the library dependencies on the target machine? Is there another way I'm not aware of? I've never released an application for Linux (nor Windows) and I'm struggling to find the resources to do things "the right way".
Thanks for everyone suggestions, I ended up settling for the easy way, compiling the "easy to install" libraries dynamically e.g.-lSDL2 and the others statically (checked the licenses and it should be fine) like so:
g++ main.cpp -o main -Wl,-Bdynamic -lSDL2 -lSDL2_image -lSDL2_ttf -Wl,-Bstatic -lSDL2_gfx -static-libgcc -static-libstdc++
I'll put in my documentation how to install the required SDL2 libraries.
I am not sure how familiar you are with pkg-config, but the output for sdl2 is this:
-D_REENTRANT -I/usr/include/SDL2 -lSDL2
This was found from running this:
pkg-config --cflags --libs sdl2
Basically, you need to point to where SDL2 is located BEFORE you actually link to it.
The tool pkg-config is designed to tell you the information you need when you want to link to a package in Linux. You were linking with the library, but you forgot to tell GCC where the library is located.
If you want to compile you code, try this:
g++ main.cpp -o runme `pkg-config --cflags --libs sdl2`
This will automatically grab all of the flags that you need to compile with SDL2 included.
Oh, and you should note, ORDER MATTERS WHEN ADDING FLAGS AND LIBRARIES!!!
There are many questions on SO where the order of compiler options caused all of the problems. Do not be like those people. I suggest you search SO for more info on that.

GCC Flag to SCONS

I`m building a library using make with the following flags:
INCL = `PKG_CONFIG_PATH=/mingw64/lib64/pkgconfig:/mingw64/lib/pkgconfig:/mingw64/share/pkgconfig:/mingw64/lib/pkgconfig:/mingw64/share/pkgconfig pkg-config --cflags ipopt` $(ADDINCFLAGS)
LIBS =
'PKG_CONFIG_PATH=/mingw64/lib64/pkgconfig:/mingw64/lib/pkgconfig:/mingw64/share/pkgconfig:/mingw64/lib/pkgconfig:/mingw64/share/pkgconfig pkg-config --libs ipopt'
How can I translate this to build with SCONS ?
My issue is to understand how the path definition PKG_CONFIG_PATH= ... is passed to SCONS.
Likely you'll want to use either ParseFlags() or MergeFlags()
See:
http://scons.org/doc/production/HTML/scons-man.html
Further there's a reasonable example in the SCons wiki here:
https://bitbucket.org/scons/scons/wiki/UsingPkgConfig

how to do static linking of libwinpthread-1.dll in mingw?

I use mingw from here: http://sourceforge.net/projects/mingwbuilds/files/host-windows/releases/4.7.2/32-bit/threads-posix/sjlj/x32-4.7.2-release-posix-sjlj-rev2.7z/download
And I've sucessfully managed to link statically libstdc++-6.dll and libgcc_s_sjlj-1.dll by using -static-libgcc -static-libstdc++ parameters, but I cannot find a command for doing the same with libwinpthread-1.dll.
If your toolchain includes the static winpthreads, adding the option
-static
Will pull in static versions of all libraries it can.
Alternatively, you can remove libwinpthread.dll.a and the DLL itself from the toolchain directories. This might mess up programs linking with libstdc++ and libgcc DLLs though, so be careful.
A third option is to use -Wl,-Bdynamic and -Wl,-Bstatic to select which version you want linked in (which is what -static internally does when ld is called). An example:
gcc -o someexec someobject.o -Wl,-Bdynamic -lsomelibIwantshared -Wl,-Bstatic -lsomelibIwantstatic
If you run your link command with -v added, you should see these options appearing in the ld/collect2 invocation when you use -static-libgcc and -static-libstdc++.
Try this:
-static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic
Notice the -lstdc++ before -lpthread. It worked for me.
Make sure to add this to the very end of your g++ command line.
You should probably check command line options documentation for GCC.
These's no '-static-something' command, only standard libraries (libgcc and libstdc++) can be set to static linking with one command. For other libraries, you first switch to static linking with "-static" and then list the libraries to include with separate commands, ie "-lpthread".
To statically link winpthread even if threading isn't used in the program, pass the -Bstatic and --whole-archive parameters to the linker:
g++ -o hello.exe hello.cpp -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive
Note the following:
The "whole archive" option should be disabled immediately afterwards.
You don't need to do this hack if your program actually uses symbols from the library (i.e. you use <thread> from C++11), in which case the library won't get dropped when you statically link it.
This hack is intended for MinGW-w64, to fix the libwinpthread-1.dll dependencies.
For anyone working in CMake, this solution is readily implemented in your CMakeLists.txt file as follows...
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static")
Apparently, CMake does some weird stuff with how the -Wl compiler flags are handled, making the -Wl,-Bstatic -lstdc++ -lwinpthread -Wl,-Bdynamic solution not work, with only two other options seemingly left: the bad compiler flag -static and the ugly compiler flag -Wl,--whole-archive.
Meanwhile, the good option that actually works in CMake, yet seems rather undocumented, is to directly use the linker flags. Hence, in CMake, this seems to be the best way to statically link to all the mingw-w64 C++ dependencies:
target_link_libraries (MyVeryAwesomeApp -static gcc stdc++ winpthread -dynamic)
It should be noted that even if there isn't a library explicitly following -dynamic, it should still be applied in order to ensure that the standard, implicitly linked libraries get linked correctly.
I circumvented this problem by using win32 variant of the mingw toolchain instead of the posix variant. With the win32 variant, -static-libgcc -static-libstdc++ is sufficient for an independent build.
If you are using toolchains from MSys2 (tested with gcc version 12) ,the only way to use winpthread statically is standard -static (forces all library to be static) or simply delete/rename the libwinpthread.dll.a && libpthread.dll.a imp libs.
Other methods like "Bstatic", "-l:libwinpthread.a" will no longer work (due to dependency hell, especially in CMake). The one with whole archive still works but it overrides the program properties.
You may also want static link libgcc and libstdc++ if the dependency comes from them.
Just link with -l:libwinpthread.a
Just add -static to your CFLAGS.
For example: ./configure CFLAGS="-static".
This will link all static libraries to your executable file.

Backslash on Include directories with pkg-config on Mac OS Lion

Good evening everybody,
I have virtually no experience with pkg-config but it seems that I will have to use it in working with openssl. Im on a Mac, which might be of some importance.
The problem is:
i compile my testing program with
cc test.cc `pkg-config --libs --cflags openssl` -o test
i have compiled openssl and installed it in ~/openssl afterwards adding ~/openssl/lib/pkgconfig to the PKG_CONFIG_PATH
since I want to use the newest version instead of the preinstalled one, I specify the options with every compilation
the result of running pkg-config --libs or pkg-config --cflags openssl is -L\~/openssl/lib -lssl -lcrypto
This begs the question for me why there is a backsash and whether my compiled version is used or the preinstalled one and if the first one is the case how i could possibly fix this...
Any kind of help is appreciated
The expansion of ~ to your home directory only occurs in certain circumstances. Basically, it's the shell that's doing it. If a program or a file API sees the tilde, it is interpreted as a literal; it's not expanded.
Use $HOME when setting PKG_CONFIG_PATH instead, as in $HOME/openssl.