linking with particular version of a library - cmake

I am linking boost libraries with my .cpp files. The build machine has boost 1.55 in /usr/lib64 and I have boost 1.57 in my local directory. The cmake generates the following link command.
/home/ramki/mpich-install/bin/mpicxx -fopenmp -fexceptions -fno-use-linker-plugin CMakeFiles/factor.dir/factor.cpp.o CMakeFiles/factor.dir/factor_jobs.cpp.o -o factor -rdynamic -lboost_serialization -lboost_iostreams -lboost_program_options -lboost_mpi -llapack -llapacke -lblas -lpthread -lm -lz factorization/libfactorization.a
The above link command does not specify the version of the boost libraries. Because of this I get the following error.
/usr/bin/ld: warning: libboost_serialization.so.1.57.0, needed by /home/ramki/libraries/boost_1_57_0//lib/libboost_mpi.so, may conflict with libboost_serialization.so.1.55.0
Because of this nature of linking, when I use ldd to dump the linked libraries of the executable, I see it linked with couple of libboost 1.55 libraries. If the machine in which I run this executable does not have boost 1.55, it does not start at all.
In the CMakeLists.txt and CMakeCache.txt, I see that the find_package is discovering the 1.57 libraries.
find_package(Boost 1.57.0 COMPONENTS serialization iostreams program_options mpi REQUIRED).
However during linking it is not introducing the version of the library. How do I instruct the cmake to do the following.
linking libraries to use a particular version. For eg., -l:libboost_mpi.so.1.57.0
specify the library path for this version -L library path explicitly. It should NOT link with the library under /usr/lib64.
Ramki

Not sure if this will work for other libraries. Atleast for boost before find_package on boost, set (Boost_REALPATH ON). This will set Boost_LIBRARIES with full path as
/export5/home/ramki/libraries/boost_1_57_0/lib/libboost_serialization.so.1.57.0;/export5/home/ramki/libraries/boost_1_57_0/lib/libboost_iostreams.so.1.57.0;/export5/home/ramki/libraries/boost_1_57_0/lib/libboost_program_options.so.1.57.0;/export5/home/ramki/libraries/boost_1_57_0/lib/libboost_mpi.so.1.57.0.
Use this Boost_LIBRARIES with target_link_libraries(theTarget ${Boost_LIBRARIES}). Thus instead of linking with libboost_mpi.so that could be link to other versions, we are linking with the library of the correct version.

Related

How can I properly configure the g++ include path with mingw64?

I have installed msys2/mingw64 because I need the g++ compiler. Now, I want to compile some c++ oce which requires openblas. I have installed the package using pacman -S mingw-w64-x86_64-openblas. However, compiling the code fails with
fatal error: cblas.h: No such file or directory
Clearly, the include path does not contain the headers from openblas which are located at C:\msys64\mings64\include\openblas. This is easy to fix by passing -I<include path> as an additional argument to g++.
Now, I was wondering whether there is an automated way to include include files/headers of installed packages in the g++ include path. The same problem also holds for libraries.
For example, pacman might be able to atomatically append these paths onto some environment variable which g++ checks.
The standard way to get compilation and linking options for a library on MSYS2 and other Unix-like systems is to run this command:
pkg-config --cflags --libs openblas
If you're just compiling, use --cflags by itself.
If you're just linking, use --libs by itself.
Here's an example Bash command you could use to compile a single-file program:
g++ foo.cpp $(pkg-config --cflags --libs openblas) -o foo

Link libc statically

I am trying to make a static executable with CMake 3.15. I am building on Alpine Linux (hence with musl), and currently, my executable's ldd output is:
# ldd my_executable
/lib/ld-musl-x86_64.so.1 (0x7fc6f7977000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x7fc6f65b3000)
libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7fc6f7977000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7fc6f659f000)
I can set target_link_options(my_executable PRIVATE -static-libgcc -static-libstdc++), and they got linked statically:
# ldd my_executable
/lib/ld-musl-x86_64.so.1 (0x7fc6f7977000)
libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7fc6f7977000)
But I can't manage to get musl to link statically. I tried (with clean builds, to make sure that the configure step starts from zero):
Adding -static to target_link_options above.
set(CMAKE_EXE_LINKER_FLAGS "-static") before the call to add_executable(my_executable ...)
Adding -static to target_link_libraries(my_executable lib1 lib2 -static)
When I run CMake in VERBOSE=1 mode, it always ends the linking command with:
... -Wl,-Bdynamic -ldl -lrt -lm -lpthread
I believe that this is my issue: I want to get rid of that -Bdynamic. What am I missing? Is this -Bdynamic coming from one of my dependencies? I build them all from sources as static (.a) libraries, so how could they be linking libc dynamically? Or would I need to patch them all to add -static when I build them?
As hinted by KamilCuk's comment, the answer here seems to have the solution. Still, I'm not doing exactly the same, therefore I'll keep this answer, too.
For the target executable that I want statically linked:
add_executable(my_executable main.cpp)
I had to set the following properties/options:
set_target_properties(my_executable PROPERTIES LINK_SEARCH_START_STATIC ON)
set_target_properties(my_executable PROPERTIES LINK_SEARCH_END_STATIC ON)
target_link_options(my_executable PRIVATE -static-libgcc -static-libstdc++ -static)
Some notes:
LINK_SEARCH_*_STATIC were useful to remove -Bdynamic from the linking command.
I never managed to remove -ldl from the linking command, but it seems like dl did not get link eventually (presumably because it is not used).
ldd was not enough to verify that my_executable is statically linked. readelf -l my_executable showed that it does not have an INTERP header, and there is currently no such thing as a dynamic binary without it (using musl).
It turns out that checking whether a binary is statically linked or not is not so straightforward :-).

How to add linker option to CMake bootstrap?

I'm building CMake 3.12.4 from the release tarball on AIX. CMake is failing to link on the machine:
ld: 0711-781 ERROR: TOC overflow. TOC size: 65632 Maximum size: 65536
The error is detailed in the IBM technotes at ld: 0711-781 ERROR: TOC overflow. I want to add -bbigtoc linker option for the cmake recipe.
CMake's bootstrap does not appear to accept linker options for LDFLAGS as shown below.
How do I add a linker flag to the bootstrap process?
Here are the options CMake bootstrap accepts:
$ ./bootstrap --help
Usage: ./bootstrap [<options>...] [-- <cmake-options>...]
Options: [defaults in brackets after descriptions]
Configuration:
--help print this message
--version only print version information
--verbose display more information
--parallel=n bootstrap cmake in parallel, where n is
number of nodes [1]
--enable-ccache Enable ccache when building cmake
--init=FILE load FILE as script to populate cache
--system-libs use all system-installed third-party libraries
(for use only by package maintainers)
--no-system-libs use all cmake-provided third-party libraries
(default)
--system-curl use system-installed curl library
--no-system-curl use cmake-provided curl library (default)
--system-expat use system-installed expat library
--no-system-expat use cmake-provided expat library (default)
--system-jsoncpp use system-installed jsoncpp library
--no-system-jsoncpp use cmake-provided jsoncpp library (default)
--system-zlib use system-installed zlib library
--no-system-zlib use cmake-provided zlib library (default)
--system-bzip2 use system-installed bzip2 library
--no-system-bzip2 use cmake-provided bzip2 library (default)
--system-liblzma use system-installed liblzma library
--no-system-liblzma use cmake-provided liblzma library (default)
--system-libarchive use system-installed libarchive library
--no-system-libarchive use cmake-provided libarchive library (default)
--system-librhash use system-installed librhash library
--no-system-librhash use cmake-provided librhash library (default)
--system-libuv use system-installed libuv library
--no-system-libuv use cmake-provided libuv library (default)
--qt-gui build the Qt-based GUI (requires Qt >= 4.2)
--no-qt-gui do not build the Qt-based GUI (default)
--qt-qmake=<qmake> use <qmake> as the qmake executable to find Qt
--sphinx-info build Info manual with Sphinx
--sphinx-man build man pages with Sphinx
--sphinx-html build html help with Sphinx
--sphinx-qthelp build qch help with Sphinx
--sphinx-build=<sb> use <sb> as the sphinx-build executable
--sphinx-flags=<flags> pass <flags> to sphinx-build executable
Directory and file names:
--prefix=PREFIX install files in tree rooted at PREFIX
[/usr/local]
--bindir=DIR install binaries in PREFIX/DIR
[bin]
--datadir=DIR install data files in PREFIX/DIR
[share/cmake-3.12]
--docdir=DIR install documentation files in PREFIX/DIR
[doc/cmake-3.12]
--mandir=DIR install man pages files in PREFIX/DIR/manN
[man]
--xdgdatadir=DIR install XDG specific files in PREFIX/DIR
[share]
Here is the CMake link error:
cmake_build$ make VERBOSE=1
...
[ 91%] Linking CXX executable ../bin/cmake
cd /home/noloader/cmake_build/Source && /home/noloader/cmake_build/Boots
trap.cmk/cmake -E cmake_link_script CMakeFiles/cmake.dir/link.txt --verbose=1
/usr/bin/g++ -pthread -Wl,-bnoipath -Wl,-brtl -Wl,-bexpall CMakeFiles/cmake.dir
/cmakemain.cxx.o CMakeFiles/cmake.dir/cmcmd.cxx.o -o ../bin/cmake -Wl,-blibpath
:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.8.1/pthread:/opt/freeware/lib/pt
hread:/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.8.1:/opt/freeware/lib:/usr/
lib:/lib libCMakeLib.a libCMakeServerLib.a libCMakeLib.a kwsys/libcmsys.a ../Uti
lities/cmexpat/libcmexpat.a ../Utilities/cmlibarchive/libarchive/libcmlibarchive
.a ../Utilities/cmliblzma/libcmliblzma.a ../Utilities/cmbzip2/libcmbzip2.a ../Ut
ilities/cmcompress/libcmcompress.a ../Utilities/cmcurl/lib/libcmcurl.a ../Utilit
ies/cmzlib/libcmzlib.a -lld ../Utilities/cmjsoncpp/libcmjsoncpp.a ../Utilities/c
mlibuv/libcmlibuv.a -lperfstat ../Utilities/cmlibrhash/libcmlibrhash.a
ld: 0711-781 ERROR: TOC overflow. TOC size: 65632 Maximum size: 65536
collect2: error: ld returned 12 exit status
make: 1254-004 The error code from the last command is 1.
Something like this:
export CFLAGS=...
export CXXFLAGS=...
export LDFLAGS='... -Wl,-bbigtoc'
./bootstrap ... --verbose
make VERBOSE=1 all
Also you might want to read this: http://lzsiga.users.sourceforge.net/aix-linking.html#Q0025

Emitting a single IR bitcode File with LLVM LLD using CMake

I'm using Ubuntu 16.04 x86_64 and LLVM 5.0 and would like to compile a project to a single LLVM IR bitcode file using CMake. I know there is a way to do this using the GOLD Linker with the LLVM Plugin and add the CMake linker flags "-fuse-ld=gold -Wl,-plugin-opt=emit-llvm" and the CXX flag "-flto".
But when I try to compile the project with the LLVM LLD linker and the "-fuse-ld=lld -Wl,-plugin-opt=emit-llvm" respectively "-flto" Flag, the linker is generating a native executable and no LLVM IR file. I was searching for other LLD options to emit a LLVM IR file but found nothing.
Is there a way (or option) to generate a single LLVM IR file using LLD?
You can use the -save-temps option.
clang -flto -fuse-ld=lld -Wl,-save-temps a.o b.o -o myprogram
This will generate myprogramXYZ.precodegen.bc among other files. You can then use llvm-dis to get it in readable IR format.

Error when linking GSL with -static

I have written a programm in c++. Linking and runiing is working, as long as I don't use the "-static" option for g++. But I have to run it from an Antergos USB-Live Stick with default settings and there is no GSL included. In the manual of GSL they recommend
$ g++ -c main.cpp
$ g++ -static main.o -lgsl -lgslcblas -lm -lnlopt
But for this code I receive an error message:
/usr/bin/ld: cannot find -lgsl
/usr/bin/ld: cannot find -lgslcblas
collect2: Fehler: ld gab 1 als End-Status zurück
I tried it as this question, but it didn't work for me. When I run
$ g++ -O2 -o test main.cpp -lgsl -lgslcblas -lnlopt -lm
$ lld test
it prints
linux-vdso.so.1 (0x00007fffa5b95000)
libgsl.so.19 => /usr/lib/libgsl.so.19 (0x00007f8748c9a000)
libgslcblas.so.0 => /usr/lib/libgslcblas.so.0 (0x00007f8748a5d000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f87486d5000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007f87483d1000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f87481ba000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f8747e1c000)
/lib64/ld-linux-x86-64.so.2 (0x00007f87490fe000)
So I tried to create a symlink, but I do have also "libgsl.so"
$ ls /usr/lib/libgsl
libgslcblas.so libgslcblas.so.0.0.0 libgsl.so.19
libgslcblas.so.0 libgsl.so libgsl.so.19.3.0
Am I doing something stupid? Thank your for your help.
When you pass -lgsl, by default you request the linker to
find and link either the shared library libgsl.so or the static
library libgsl.a and to prefer the shared library, if both are found
in the same search directory. The linker will search, first, in any
directories you have specified with the -L/path/to/search options,
in the order you specified, and then in its default search directories
(/usr/lib, etc.). Likewise for -lgslcblas.
But when you pass the linkage option -static to gcc/g++, it prevents
linking with any shared libraries. Shared libraries, libgsl.so, libgslcblas.so
will be ignored. Static libraries libgsl.a, libgslblas.a, must be
found, in some or other of the search directories, for the linkage to
succeed.
The linker is saying:
/usr/bin/ld: cannot find -lgsl
/usr/bin/ld: cannot find -lgslcblas
because it can't find those static libraries - presumably because you
haven't installed them.
You do not say what linux distro you are working on, but if the package
that provides libgsl and libgslcblas is called, say, libgsl[suffix]
then there will be a corresponding package called libgsl-dev, libgsl-devel,
or similar. This will be the development version of the package,
for the use of people who want to develop software that links with libgsl
or libgslcblas. The development package will require the libgsl package as a dependency
- so it will install the same stuff - and will in addition contain the
library's header files and the static version of the library.
So you need to install the libgsl development package for your distro.
For Ubuntu, for example, that is libgsl-dev:
Later
I gather that your distro, Arch Linux, does not do separate dev packages. You
need to build the static libraries from source. To do that you will need
at least to have installed:
GNU Make
GNU autotools (autoconf, automake, libtool)
GCC (C compiler)
texinfo
Then to make a default build:
Get the gsl source package from https://savannah.gnu.org/git/?group=gsl
either by cloning the git repo or downloading a current tar.gz tarball
and extracting it.
cd into the package directory.
run ./autogen.sh. This will succeed provided the GNU autotools prerequisites
are fulfilled.
run ./configure --enable-maintainer-mode (as ./autogen.sh will have prompted you).
This will succeed provided that the package dependencies are satisfied
and environment sanity checks pass.
run make
If make completes without errors - which will take a matter of minutes -
then, as root, run make install.
If all is well, this will install your missing static libraries:
/usr/local/lib/libgsl.a
/usr/local/lib/libgslcblas.a
You should not need to modify your linkage command for the linker to find
them: /usr/local/lib is a default linker search path.