[CMake] Creating relocatable export files

Tamás Kenéz tamas.kenez at gmail.com
Sat Nov 14 16:20:38 EST 2015


You need to manually write your config module which takes care of the
dependencies. Of course you will still use the generated exports, too.

For now let's say `ome-common` has one dependency: `omedep` and its
config-module, `omedep-config.cmake` creates the imported lib target
`omedep::omedep`. The in `ome-common`'s CMakeLists.txt:

    target_link_libraries(ome-common PUBLIC omedep::omedep)
    install(TARGETS ome-common
        EXPORT ome-common-targets ....)
    install(EXPORT ome-common-targets
        DESTINATION cmake/ome-common)
    install(FILES ome-common-config.cmake DESTINATION cmake/ome-common)

 The `ome-common-config.cmake` should look like this:

    include(CMakeFindDependencyMacro)
    find_dependency(omedep)
    include(${CMAKE_CURRENT_LIST_DIR}/ome-common-targets.cmake)

Note: for CMake versions < 3.0 you need to use `find_package` instead of
`find_dependency`.

Okay, so that's the solution if `ome-common`'s dependency creates an
imported lib target.

If `omedep` has an oldschool config-module which provides only variables
like OMEDEP_LIBRARIES containing absolute paths, then these paths will be
hardcoded in `ome-common-targets.cmake`. In this case the recommended
method is to convert these paths to relative paths in a postprocess step
after installation.
See this: https://gist.github.com/tamaskenez/7ca4cba352525985ea70 as an
example for such a script.

Of course this can only be used if `omedep` is a dependency which is
installed into the same install tree as `ome-common`.
If you have a dependency in a separate install-tree which does not create
imported lib targets then you need to do it yourself both in `ome-common`'s
CMakeLists.txt and config-modules. This is not a trivial operation but
always can be done with more or less additional logic. For a simple case
where `omedep` consists of a single library file:

`ome-common`'s CMakeLists.txt:

    find_package(omedep REQUIRED)
    add_library(ome-common::omedep STATIC IMPORTED) # STATIC or SHARED or
UNKNOWN
    set_target_properties(ome-common::omedep PROPERTIES
        INTERFACE_INCLUDE_DIRECTORIES ${OMEDEP_INCLUDE_DIRS}
        IMPORTED_LINK_INTERFACE_LANGUAGES "C"
        IMPORTED_LOCATION ${OMEDEP_LIBRARIES} # a single library
    )
    target_link_libraries(ome-common PUBLIC ome-common::omedep)
    ...

which should be repeated in `ome-common-config.cmake`:

    include(CMakeFindDependencyMacro)
    find_dependency(omedep)
    set_target_properties(ome-common::omedep PROPERTIES
        INTERFACE_INCLUDE_DIRECTORIES ${OMEDEP_INCLUDE_DIRS}
        IMPORTED_LINK_INTERFACE_LANGUAGES "C"
        IMPORTED_LOCATION ${OMEDEP_LIBRARIES} # a single library
    )
    include(${CMAKE_CURRENT_LIST_DIR}/ome-targets.cmake)

Things get more complicated when OMEDEP_LIBRARIES has per-config variants
or further dependencies. You can check the generated
`ome-common-targets.cmake` and `ome-common-targets-Debug/Relase.cmake`
files for an example on how to set up such an imported lib target.



On Sat, Nov 14, 2015 at 7:19 PM, Nicholas Braden <nicholas11braden at gmail.com
> wrote:

> Instead of using FOO_INCLUDE_DIR, I believe you should use
> target_include_directories() with the INTERFACE or PUBLIC options -
> this will export the include directories properly and they will be
> used when someone target_link_library()s your exported target.
>
> https://cmake.org/cmake/help/latest/command/target_include_directories.html?highlight=INTERFACE
>
> There seems to be a section in the documentation on making sure your
> packages are relocatable:
>
> https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#creating-relocatable-packages
>
> See also:
> https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html
>
> As for recursively finding packages, I honestly don't know on this
> front. I would imagine that everything might work if everything was
> using exported/imported targets, but I'm not sure. The problem is that
> you have to consider what happens if you relocate your relocatable
> package to a system that doesn't have the dependencies installed. I
> don't think exported/imported targets or relocatable packages can
> solve that problem easily, but I am not very knowledgeable in this
> area myself.
>
> On Sat, Nov 14, 2015 at 5:53 AM, Roger Leigh <rleigh at codelibre.net> wrote:
> > Hi,
> >
> > I'm wanting to create -config scripts for my libraries so that dependent
> > projects can find them with find_package and use them transparently.  I
> have
> > a number of header-only and shared/static libs, and I'd like to retain
> their
> > relationships, plus any additional libraries they are linked with.
> >
> > I was previously using hand-crafted templates, e.g. with this type of
> > generated structure:
> >
> >
> ---------------------------------------------------------------------------
> > set(OME_COMMON_FOUND TRUE)
> >
> > set(OME_COMMON_VERSION "5.2.0-pre0-7-gfc53ca3")
> > set(OME_COMMON_VERSION_MAJOR "5")
> > set(OME_COMMON_VERSION_MINOR "2")
> > set(OME_COMMON_VERSION_PATCH "0")
> > set(OME_COMMON_VERSION_EXTRA "-pre0-7-gfc53ca3")
> >
> > find_path(OME_COMMON_INCLUDE_DIR ome/common/module.h HINTS
> > "/tmp/split/include")
> > find_library(OME_COMMON_LIBRARY NAMES ome-common libome-common HINTS
> > "/tmp/split/lib")
> >
> ---------------------------------------------------------------------------
> >
> > They unfortuately did not handle interface targets or public library
> > dependencies required by use in the headers.  I've switched to using
> > install(EXPORT):
> >
> >
> https://github.com/rleigh-dundee/ome-common-cpp/blob/develop/lib/ome/common/CMakeLists.txt#L123
> >
> ---------------------------------------------------------------------------
> > target_link_libraries(ome-common ome-compat
> >                       ${Boost_LOG_SETUP_LIBRARY_RELEASE}
> >                       ${Boost_LOG_LIBRARY_RELEASE}
> >                       ${Boost_FILESYSTEM_LIBRARY_RELEASE}
> >                       ${Boost_SYSTEM_LIBRARY_RELEASE}
> >                       ${LibDl_LIBRARIES}
> >                       ${XercesC_LIBRARIES})
> >
> > set_target_properties(ome-common PROPERTIES LINKER_LANGUAGE CXX)
> > set_target_properties(ome-common PROPERTIES VERSION ${OME_VERSION_SHORT})
> >
> > install(TARGETS ome-common
> >         EXPORT ome-common-config
> >         RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}
> >         LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}
> >         ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR})
> > install(EXPORT ome-common-config
> >         DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/ome-common)
> >
> ---------------------------------------------------------------------------
> >
> > This does a much better job of the dependencies.  It's preserving the
> > dependencies for the internal targets, plus the external libraries.
> However,
> > it's lacking:
> >
> > - any setting of the include path via FOO_INCLUDE_DIR, unless it's just
> not
> > done in an obvious manner
> > - it's hardcoded the absolute paths of the various boost and xerces libs;
> > I'd like it to be relocatable so it can work in a superbuild and
> continue to
> > work after moving elsewhere
> > - it doesn't appear to recursively find needed import targets, e.g. I
> need
> > to find_package(ome-compat) before find_package(ome-common); it would be
> > nice if this was transparent so the user doesn't need to do this
> >
> > I'd be interested to know if anyone else has run into these issues, and
> if
> > so what your solutions were?  I'm quite new to this part of cmake, so it
> may
> > well just be I'm not doing things exactly as expected.
> >
> > Would it be easier to construct the template myself and then call
> > find_package for the external libs to avoid hardcoding the paths?  Is it
> > safe to recursively call find_package inside find_package?
> >
> >
> > Thanks all,
> > Roger
> > --
> >
> > Powered by www.kitware.com
> >
> > Please keep messages on-topic and check the CMake FAQ at:
> > http://www.cmake.org/Wiki/CMake_FAQ
> >
> > Kitware offers various services to support the CMake community. For more
> > information on each offering, please visit:
> >
> > CMake Support: http://cmake.org/cmake/help/support.html
> > CMake Consulting: http://cmake.org/cmake/help/consulting.html
> > CMake Training Courses: http://cmake.org/cmake/help/training.html
> >
> > Visit other Kitware open-source projects at
> > http://www.kitware.com/opensource/opensource.html
> >
> > Follow this link to subscribe/unsubscribe:
> > http://public.kitware.com/mailman/listinfo/cmake
> --
>
> Powered by www.kitware.com
>
> Please keep messages on-topic and check the CMake FAQ at:
> http://www.cmake.org/Wiki/CMake_FAQ
>
> Kitware offers various services to support the CMake community. For more
> information on each offering, please visit:
>
> CMake Support: http://cmake.org/cmake/help/support.html
> CMake Consulting: http://cmake.org/cmake/help/consulting.html
> CMake Training Courses: http://cmake.org/cmake/help/training.html
>
> Visit other Kitware open-source projects at
> http://www.kitware.com/opensource/opensource.html
>
> Follow this link to subscribe/unsubscribe:
> http://public.kitware.com/mailman/listinfo/cmake
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/cmake/attachments/20151114/cf5c9e48/attachment-0001.html>


More information about the CMake mailing list