[CMake] Creating relocatable export files

Nicholas Braden nicholas11braden at gmail.com
Sat Nov 14 13:19:11 EST 2015


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


More information about the CMake mailing list