Re: [CMake] Creating relocatable export files
On Saturday, November 14, 2015 12:19:11 Nicholas Braden 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-re > locatable-packages > > See also: > https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html this is from before the fancy target-include-directories-propagation functionality was added, it shouldn't be necessary anymore. Alex -- 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
Re: [CMake] Creating relocatable export files
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 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 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
Re: [CMake] Creating relocatable export files
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 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/train
[CMake] Creating relocatable export files
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