Force CMake to use static libraries - gcc

[Shamelessly cross-posted from the CMake help list]
I'm trying to create binaries as statically as possible. The fortran code I've got has got X11 and quadmath as dependencies, and I've come across a number of issues (maybe each of these issues should be in a different question?):
My variables are currently
set(CMAKE_LIBRARY_PATH /usr/X11/lib /usr/X11/include/X11 ${CMAKE_LIBRARY_PATH})
find_package(X11 REQUIRED)
find_library(X11 NAMES X11.a PATHS /usr/X11/include/X11/ /usr/X11/lib)
find_library(X11_Xaw_LIB NAMES Xaw Xaw /usr/X11/include/X11/ /usr/X11/lib ${X11_LIB_SEARCH_PATH})
find_library(Xaw Xaw7 PATHS ${X11_LIB_SEARCH_PATH})
set(CMAKE_LIBRARY_PATH /usr/lib/gcc/x86_64-linux-gnu/4.7 /usr/lib/gcc/x86_64-linux-gnu/4.7/x32 /usr/lib/gcc/x86_64-linux-gnu/4.7/32 ${CMAKE_LIBRARY_PATH})
find_library(quadmath NAMES quadmath.a)
set(BUILD_SHARED_LIBS ON)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(LINK_SEARCH_START_STATIC TRUE)
set(LINK_SEARCH_END_STATIC TRUE)
set(SHARED_LIBS OFF)
set(STATIC_LIBS ON)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
Using these, CMake attempts to build every program statically (as expected) - however, it fails because I don't have Xaw.a - I can't find out whether this actually should exist. I have installed the latest libxaw7-dev which I was expecting to fix it. One option would be to compile the X11 libraries myself, but I don't really want to do that...
if I comment out only set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static"), then CMake compiles everything, but uses shared libraries for every program, even though I specify the location of .a X11 libraries in my find_library() calls. I was expecting CMake to use the .a files where it could and then only use shared libraries - is there a way to force this behaviour?
does anyone know yet of a fix for the bug described here: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46539; whereby gfortran seemingly can't statically link libquadmath? I tried the fix using gcc but I can't get CMake to recognise the libgfortran flag:
cmake -DCMAKE_Fortran_COMPILER=gcc -DCMAKE_Fortran_FLAGS=-gfortran
results in
-- The Fortran compiler identification is unknown
-- Check for working Fortran compiler: /usr/bin/gcc
-- Check for working Fortran compiler: /usr/bin/gcc -- broken
CMake Error at /usr/share/cmake-2.8/Modules/CMakeTestFortranCompiler.cmake:54 (message):
The Fortran compiler "/usr/bin/gcc" is not able to compile a simple test program.
However, as you might have noticed, I set the location of the libquadmath.a; when I build a program which doesn't use X11 but does use quadmath when I use
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
then the program does compile successfully (running ldd reports 'not a dynamic executable') - does this mean that the bug has been fixed, or does it only work because I set the location in CMake?

I was having a similar problem. Turns out that cmake was implicitly linking against libgfortran and libquadmath. To fix this I put the following in my top level CMakeLists.txt:
unset(CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES)
I could then explicitly link again the libraries using:
SET_TARGET_PROPERTIES(main_f PROPERTIES LINKER_LANGUAGE "C"
LINK_FLAGS
"/usr/local/Cellar/gcc/7.1.0/lib/gcc/7/libgfortran.a
/usr/local/Cellar/gcc/7.1.0/lib/gcc/7/libquadmath.a -lm -lgcc"
)
The static version of libgfortran is necessary because the shared library also depends on libquadmath. The added "-lm" and "-lgcc" bring in the system dynamic versions of these libraries. On a mac system, you would want to use the full path to your libm.a as well.

I guess your questions are not that much related, I don't know the answer for all of them.
For your static linking problems, since you're using GCC, you can pass multiple -static and -dynamic flags to it:
set(CMAKE_EXE_LINKER_FLAGS "-static ${STATIC_LIBS} -dynamic ${EVERYTHING ELSE} -static ${MORE_STATIC_LIBS}")
I don't know why Xaw.a isn't available on your system, probably because the package maintainer of your Linux distribution didn't really make them available.
Also, compiling everything static might make things not compatible between all distros out there and you cripple the ability for others to use improved, up-to-date libraries with your program, it might not be what you want.
If you intend to make a self-contained package of your program, it might be better just to include the shared libraries you used together, like Dropbox and many other proprietary applications do (Humble Bundle games are other example).

Related

Identify Compiler Versions with arm-none-eabi cross compiling

I'm trying to figure out the compiler versions that are used in my project (to sync them across the team).
I'm using ChibiOS on an STM32 and it uses a makefile to compile. In the Makefile it uses
TRGT = arm-none-eabi-
CC = $(TRGT)gcc
Which makes it clear that arm-none-eabi-gcc is being used. However unclear to me is, if the version of my gcc compiler (gcc --version) is at all relevant to the compilation. As far a I understand gcc just is being set to a specific target here? Whats the relationship between my gcc/cc executable and the arm-none-eabi-gcc executable?
There is no relationship. It is a separate compiler which usually comes with its own include files, libraries, startup file and linker scripts. Usually, it is called a toolchain as often it comes with other tools as well (linker, specific versions of gdb and other tools).

Building cmake with non-default GCC uses system libstdc++

I'm trying to compile CMake using a non-default GCC installed in /usr/local/gcc530, on Solaris 2.11.
I have LD_LIBRARY_PATH=/usr/local/gcc530/lib/sparcv9
Bootstrap proceeds fine, bootstrapped cmake successfully compiles various object files, but when it tries to link the real cmake (and other executables), I get pages of "undefined reference" errors to various standard library functions, because, as running the link command manually with -Wl,-verbose shows, the linker links with /usr/lib/64/libstdc++.so of the system default, much older GCC.
This is because apparently CMake tries to find curses/ncurses libraries (even if I tell it BUILD_CursesDialog:BOOL=OFF), finds them in /usr/lib/64, and adds -L/usr/lib/64 to build/Source/CMakeFiles/cmake.dir/link.txt, which causes the linker to use libstdc++.so from there, and not my actual GCC's own.
I found a workaround: I can get the path to proper libraries from $CC -m64 -print-file-name=libstdc++.so then put it with -L into LDFLAGS when running ./configure, and all works well then.
Is there a less hacky way? It's really weird that I can't tell GCC to prioritize its own libraries.
Also, is there some way to have CMake explain where different parts of a resulting command line came from?

Let cmake with clang use c++11 (c++14)

My cmake project shall compile c++14 code. It also uses the CMakeLists.txts included from its external libraries (which are git submodules in my project). The build fails on macOS Sierra (cmake 3.6.2) because the default STL of clang is old and doesn't handle c++11. As far as I understand, there are two STLs shipped with clang: libstdc++ (from gcc) (default) or libc++. So if I add the -stdlib=libc++ option to cmake, the source compiles:
add_compile_options( "$<$<COMPILE_LANGUAGE:CXX>:-std=c++14>" )
add_compile_options( "$<$<COMPILE_LANGUAGE:CXX>:-stdlib=libc++>" )
But then it fails at link time because it tries to use libstdc++ for linking. How do I specify in cmake that the new STL libc++ shall be used for the whole build process?
PS: What is the rationale behind clang using the gcc STL by default if it is too old? Could I permanently specify which STL it shall use? Or am I doing something completely wrong (could some of my subprojects silently force gcc?)?
You should rely on CMake to handle compile options. Just specify the wanted standard version:
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
target_compile_features can also be used to require particular features of the standard (and implicitly ask CMake to set the adequate configuration). More information here.
EDIT
You figured out the solution, you also had to remove the following line in the CMakeLists of Ogred3D:
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7)
Removing it prevented CMake to add the flag mmacosx-version-min=10.7 causing the error.
I suppose, you also need to pass that flang to the linker in the clang case:
link_libraries("-stdlib=libc++")

Can't get GCC's -static-libgcc working with DYLIB libraries on Mac OS X

I've installed GCC 4.6.3 into a non-system path on a Mac system and it works fine. However, GCC wants to use code from libgcc for all the binaries I compile, and running otool -L shows that these compiled programs look for libgcc_s.1.dylib in GCC's install path. I can override this by passing -static-libgcc, which just compiles the stuff needed into the binary and that's fine. The problem is this only seems to work with executables, not shared libraries. If I use GCC to compile some third-party lib I want to use in one of my programs as a .dylib, these libraries still look for libgcc_s.1.dylib in the local GCC install path even if I specify -static-libgcc! Needless to say, this is a problem as there's no guarantee that those libraries will find libgcc when run on some other system.
I tried this with ffmpeg. If I look at config.log, the -static-libgcc is most certainly being used. GCC is just not linking libgcc statically with the resulting dylibs. I even tried the -nostdlib, -nostartfiles and -nodefaultlibs options but they were ignored. Again, I checked config.log and they're definitely there!
I believe this is to do with throwing exceptions across the shared library boundary. This page says:
There are several situations in which an application should use the
shared libgcc instead of the static version. The most common of these
is when the application wishes to throw and catch exceptions across
different shared libraries. In that case, each of the libraries as
well as the application itself should use the shared libgcc.
Therefore, the G++ and GCJ drivers automatically add -shared-libgcc
whenever you build a shared library or a main executable, because C++
and Java programs typically use exceptions, so this is the right thing
to do.
The rest of that sections gives a possible workaround (it appears) and that is to use the GCC driver to link your shared library, however if the statically-linked library throws exceptions you'll probably get a Segmentation Violation.

How to statically compile an SDL game on Windows

I have been trying to produce a statically linked "single binary" version of my game for windows. I want to link with sdl, sdl_image and sdl_mixer which in turn pull in a few support libraries. Unfortunately I haven't found a way to get them all to compile and link using cygwin/mingw/gcc. As far as I can tell all existing public versions are only shared libraries / dlls.
Please note that I'm not talking about licencing here. The source will be open thus the GPL/LGPLness of sdl is not relevant.
When compiling your project, you need to make just a couple changes to your makefile.
Instead of sdl-config --libs, use sdl-config --static-libs
Surround the use of the above-mentioned sdl-config --static-libs with -Wl,-Bstatic and -Wl,-Bdynamic. This tells GCC to force static linking, but only for the libraries specified between them.
If your makefile currently looks like:
SDLLIBS=`sdl-config --libs`
Change it to:
SDLLIBS=-Wl,-Bstatic `sdl-config --static-libs` -Wl,-Bdynamic
These are actually the same things you should do on Unix-like systems, but it usually doesn't cause as many errors on Unix-likes if you use the simpler -static flag to GCC, like it does on Windows.
Via this SDL mailing list post it seems that the sdl development tools ship with a sdl-config script that you can use with the --static-libs flag to determine what linker flags you need to use.
Environment: VMWare Virtual Machine with Windows 7 x64 and Equipment we Dev c + + build 7.4.2.569, complilador g+ + (tdm-1) 4.6.1
Once, SDL2-2.0.3 API installed as configuration Dev c ++ is not very clear what I've done as tradition requires command line.
The first problem is that Windows 7 appears to have changed the methodology and they go to his ball. Inventory. Ref. https://stackoverflow.com/users/464581/cheers-and-hth-alf
After the first hurdle, SDL_platform.h is that bad, it's down another, I do not remember where I downloaded, but the next does not work in the indicated version.
We must put SDL2.h ls in the directory of the executable.
D:\prg_desa\zsdl2>g++ bar.cpp main.cpp -o pepe1 -ID:\SDL2-2.0.3\i686-w64-mingw32\include\SDL2 -LD:\SDL2-2.0.3\i686-w64-mingw32\lib -lmingw32 -lSDL2main -lSDL2 -mwindow
I've finally compiled and works SDL2 testing.
That's because the SDL libs are under the LGPL-license.
If you want to static link the libs (you can do that if your recompile them. It needs some hacking into the makefiles though) you have to place your game under some compatible open source license as well.
The SDL-libs come as shared libraries because most programs that use them are closed source. The binary distribution comes in a form that most people need.
On my system (Ubuntu) I have to use the following flags:
-Wl,Bstatic -lSDL_image `sdl-config --libs` -lpng12 -lz -ltiff -ljpeg -lasound -laudio -lesd -Wl,-Bdynamic `directfb-config --libs` -lpulse-simple -lcaca -laa -ldl
That links SDL, SDL_image, and many of their dependencies as static. libdl you never want static, so making a fully-static binary that uses SDL_image is a poor idea. pulse,caca,aa, and directfb can probably be made static. I haven't got far enough to figure them out yet.

Resources