cmakeshared-libraries

How to Prevent CMake from Generating Library Symlinks when Using VERSION and SOVERSION


I have a build system which uses CMake to generate a primary daemon and a handfull of shared libraries which are dynamically loaded based on configuration at runtime (via dlopen). Now, however, I need to support another build environment based on Windows+exfat which doesn't support symlinks (CMake Error: failed to create symbolic link 'libfoo.so.1': Operation not permitted). I cannot change this build requirement as it is coming from another part of the company. Adding a post-install cleanup step to remove the aberrant symlinks won't work as the build fails the moment the symlink is generated.

In my research, I have found this SO post which describes exactly what I want using NAMELINK_SKIP. Unfortunately, it seems to indicate that setting either of VERSION or SOVERSION breaks this functionality. This project does use both of these variables as we use shared library revisioning to keep track of changes to the libraries independently (each library basically provides vendor-generated configuration blob necessary to initialize a specific hardware topology). Library revisioning is an important property for us to preserve.

So, in short, How can I get CMake to not generate symlinks for my shared library in the first place yet still retain fully versioned libraries?


Solution

  • If the library is used only with dlopen mechanism, then the proper type for it is MODULE, not a SHARED:

    add_library(foo MODULE <sources>)
    

    For such libraries, CMake do not append SOVERSION to the filename and do not create symlinks. (The whole purpose of SONAME mechanism is to link with version-independent filename and to use version-dependent file at runtime. Since MODULE libraries are not linked with (at build time), they don't benefit from that mechanism).


    If you want the name of the library file to contain a version string, then you could set OUTPUT_NAME of the library:

    add_library(foo MODULE <sources>)
    # This will make the output file to be named as "libfoo.1.2.so",
    # exactly that name should be used in 'dlopen' calls.
    set_target_properties(foo PROPERTIES OUTPUT_NAME foo.1.2)