CMake: How to Create Binary Files "As Static As Possible"

I would like to have control over the type of libraries that are detected / linked to my binaries in CMake. The ultimate goal is to create “as static as possible” binaries in order to link statically with every library that has a static version. This is important because it allows you to transfer binary files on different systems during testing.

This ATM seems to be quite difficult to achieve, since the FindXXX.cmake packages, or rather, the find_library command always selects dynamic libraries when both static and dynamic are available.

Tips on how to implement this functionality - preferably in an elegant way - are very welcome!

+44
linker cmake shared-libraries static-linking dynamic-library
Sep 21 '10 at 15:51
source share
2 answers

I did some research, and although I could not find a satisfactory solution to the problem, I found half the solution.

The problem of static builds boils down to 3 things:

  • Creating and linking internal project libraries.

    Pretty simple, you just have to turn the BUILD_SHARED_LIBS OFF switch.

  • Search for static versions of external libraries.

    The only way, apparently, is to set CMAKE_FIND_LIBRARY_SUFFIXES to contain the desired file suffix (its list of priorities).

    This solution is rather dirty and very similar to CMake's cross-platform ambition. IMHO this should be handled behind the scenes of CMake, but as I understand it, because of the ".lib" confusion in Windows, it seems that CMake developers prefer the current implementation.

  • Linking statically with system libraries.

CMake provides the LINK_SEARCH_END_STATIC option, which is based on the documentation: "Complete the link line to use static system libraries." It would seem, that’s all, the problem is solved. However, it seems that the current implementation is not up to the task. If this option is enabled, CMake generates an implicit linker call with an argument list that ends with parameters passed to the linker, including -Wl,-Bstatic . However, this is not enough. Only linking the linker statically results in an error, in my case: /usr/bin/ld: cannot find -lgcc_s . What is missing tells gcc that we need a static binding via the -static argument, which is not generated by invoking the linker using CMake. I think this is a mistake, but so far I have not been able to get confirmation from the developers.

Finally, I think that all this could and should be done by CMake backstage, because it is not so difficult, except that it is impossible in Windows - if it is considered difficult ...

+24
Nov 09 '10 at 12:29
source share

A well-made FindXXX.cmake file will contain something for this. If you look in FindBoost.cmake, you can set the Boost_USE_STATIC_LIBS variable to control if it detects static or shared libraries. Unfortunately, most packages do not implement this.

If the module uses the find_library command (most often), you can change the behavior of CMake using the CMAKE_FIND_LIBRARY_SUFFIXES variable. Here is the corresponding CMake code from FindBoost.cmake to use this:

 IF(WIN32) SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) ELSE(WIN32) SET(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) ENDIF(WIN32) 

You can either put this before the call to find_package, or, better, modify the .cmake files yourself and contribute to the community.

For the .cmake files that I use in my project, I save them all in my folder in the source control. I did this because I found that having the correct .cmake file for some libraries was inconsistent and saving my own copy allowed me to make changes and ensure that everyone who checked the code would have the same system build files.

+14
Nov 08 '10 at 17:52
source share



All Articles