From 6ce82425aebda435ef7f2265404331acc037f631 Mon Sep 17 00:00:00 2001 From: Tete17 Date: Mon, 20 Apr 2026 19:19:52 +0200 Subject: [PATCH] build: ship libosrm as a CMake Config Package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this change, downstream CMake consumers of libosrm had to copy example/cmake/FindLibOSRM.cmake into their project and prepend it to CMAKE_MODULE_PATH. That find-module was a hand-rolled pkg-config wrapper that returned flag-string variables — no imported targets, no transitive usage requirements, no auto-discovery. Ship a proper CMake Config Package instead, matching the pattern used by every modern C++ library we depend on via vcpkg (flatbuffers, fmt, nlohmann_json, protozero, TBB). Consumers now only need: find_package(LibOSRM REQUIRED) target_link_libraries(myapp PRIVATE osrm::osrm) No CMAKE_MODULE_PATH tweak, no pkg-config, no manual dependency find_package() calls — LibOSRMConfig.cmake re-declares Boost, TBB, Threads, and ZLIB via find_dependency() on behalf of the consumer. Changes: - New cmake/LibOSRMConfig.cmake.in template consumed by configure_package_config_file(); paired with write_basic_package_version_file(VERSION OSRM_VERSION COMPATIBILITY SameMinorVersion) for version-range checks. - install(TARGETS osrm ... EXPORT LibOSRMTargets ...) + install(EXPORT LibOSRMTargets NAMESPACE osrm::) writes lib/cmake/LibOSRM/LibOSRMTargets.cmake with the imported target definition, IMPORTED_LOCATION, INTERFACE_INCLUDE_DIRECTORIES, and INTERFACE_LINK_LIBRARIES baked in. - target_include_directories(osrm INTERFACE ...) exposes the public include dir via BUILD_INTERFACE (subproject builds) and two INSTALL_INTERFACE entries — both include and include/osrm — so consumer code using either #include or the internal "engine/api/..." non-prefixed paths resolves after install. - ZLIB_LIBRARY and CMAKE_THREAD_LIBS_INIT uses replaced with their imported-target equivalents (ZLIB::ZLIB, Threads::Threads) so ENGINE_LIBRARIES serialises cleanly into LibOSRMTargets.cmake instead of absolute file paths that would be non-portable across install prefixes. Scope: only osrm (the routing engine) is exposed as a Config Package target. The other six osrm_* libraries are build-internal support for the command-line tools and keep their existing plain install(TARGETS ... DESTINATION lib) rules; exposing them as imported targets would require modernising the OSMIUM_LIBRARIES / EXPAT / BZIP2 / LUA variables to imported targets, which is left for a follow-up. This matches the scope of the removed find-module, which only ever covered the routing library. libosrm.pc is kept as-is for Make/Meson/autotools consumers that have no CMake. example/cmake/FindLibOSRM.cmake is deleted — superseded by LibOSRMConfig.cmake. example/CMakeLists.txt is rewritten from the variable-splicing dance down to find_package + target_link_libraries. Verified end-to-end: - cmake --install to a scratch prefix produces the expected four files under lib/cmake/LibOSRM/ (Config, ConfigVersion, Targets, Targets-release). - A fresh consumer project (stripped copy of example/) with only CMAKE_PREFIX_PATH pointed at the scratch prefix configures, compiles, and links osrm-example against osrm::osrm without any other hints. Co-Authored-By: Claude Opus 4.7 (1M context) --- CMakeLists.txt | 75 ++++++++++++++++++++++++++++----- cmake/LibOSRMConfig.cmake.in | 15 +++++++ example/CMakeLists.txt | 24 +++-------- example/cmake/FindLibOSRM.cmake | 44 ------------------- 4 files changed, 85 insertions(+), 73 deletions(-) create mode 100644 cmake/LibOSRMConfig.cmake.in delete mode 100644 example/cmake/FindLibOSRM.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index fbcb5f31bbb..f9a1076f784 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -209,6 +209,17 @@ add_library(osrm::customize ALIAS osrm_customize) add_library(osrm::update ALIAS osrm_update) add_library(osrm::store ALIAS osrm_store) +# Public include directories for downstream consumers of the exported osrm +# target. Public headers are installed under /include/osrm/... while +# some headers use non-prefixed paths like "engine/api/route_parameters.hpp" +# internally, so the consumer needs both /include and /include/osrm +# on the include path (mirroring the historical pkg-config behaviour). +target_include_directories(osrm INTERFACE + $ + $ + $ + $) + # Explicitly set the build type to Release if no other type is specified # on the command line. Without this, cmake defaults to an unoptimized, # non-debug build, which almost nobody wants. @@ -475,7 +486,9 @@ endif() # (e.g. nodejs) that expect the same zlib ABI. find_package(ZLIB REQUIRED) add_dependency_includes(${ZLIB_INCLUDE_DIRS}) -set(ZLIB_LIBRARY ${ZLIB_LIBRARIES}) +# Use the imported target (not the file-path variable) so it can serialize +# cleanly into the exported LibOSRMTargets.cmake for downstream consumers. +set(ZLIB_LIBRARY ZLIB::ZLIB) add_definitions(${OSRM_DEFINES}) include_directories(SYSTEM ${DEPENDENCIES_INCLUDE_DIRS}) @@ -491,7 +504,7 @@ target_link_libraries(osrm-routed osrm ${Boost_PROGRAM_OPTIONS_LIBRARY} ${OPTION set(EXTRACTOR_LIBRARIES ${BZIP2_LIBRARIES} ${BOOST_BASE_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} + Threads::Threads ${EXPAT_LIBRARIES} ${LUA_LIBRARIES} ${OSMIUM_LIBRARIES} @@ -500,47 +513,47 @@ set(EXTRACTOR_LIBRARIES ${MAYBE_COVERAGE_LIBRARIES}) set(PARTITIONER_LIBRARIES ${BOOST_ENGINE_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} + Threads::Threads ${TBB_LIBRARIES} ${MAYBE_RT_LIBRARY} ${MAYBE_COVERAGE_LIBRARIES}) set(CUSTOMIZER_LIBRARIES ${BOOST_ENGINE_LIBRARIES} ${ZLIB_LIBRARY} - ${CMAKE_THREAD_LIBS_INIT} + Threads::Threads ${TBB_LIBRARIES} ${MAYBE_RT_LIBRARY} ${MAYBE_COVERAGE_LIBRARIES}) set(UPDATER_LIBRARIES ${BOOST_BASE_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} + Threads::Threads ${TBB_LIBRARIES} ${MAYBE_RT_LIBRARY} ${MAYBE_COVERAGE_LIBRARIES} ${ZLIB_LIBRARY}) set(CONTRACTOR_LIBRARIES ${BOOST_BASE_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} + Threads::Threads ${LUA_LIBRARIES} ${TBB_LIBRARIES} ${MAYBE_RT_LIBRARY} ${MAYBE_COVERAGE_LIBRARIES}) set(ENGINE_LIBRARIES ${BOOST_ENGINE_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} + Threads::Threads ${TBB_LIBRARIES} ${MAYBE_RT_LIBRARY} ${MAYBE_COVERAGE_LIBRARIES} ${ZLIB_LIBRARY}) set(STORAGE_LIBRARIES ${BOOST_BASE_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} + Threads::Threads ${TBB_LIBRARIES} ${MAYBE_RT_LIBRARY} ${MAYBE_COVERAGE_LIBRARIES}) set(UTIL_LIBRARIES ${BOOST_BASE_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} + Threads::Threads ${TBB_LIBRARIES} ${MAYBE_COVERAGE_LIBRARIES} ${ZLIB_LIBRARY}) @@ -609,7 +622,16 @@ install(TARGETS osrm-contract DESTINATION bin) install(TARGETS osrm-datastore DESTINATION bin) install(TARGETS osrm-routed DESTINATION bin) -install(TARGETS osrm DESTINATION lib) +# Install osrm as part of an EXPORT set so consumers can find_package(LibOSRM) +# and link osrm::osrm with its usage requirements (include dirs + transitive +# deps) baked in. The other osrm_* libraries are build-internal support for +# the command-line tools; they are still installed for pkg-config / legacy +# consumers but are not part of the exported CMake package. +install(TARGETS osrm + EXPORT LibOSRMTargets + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + RUNTIME DESTINATION bin) install(TARGETS osrm_extract DESTINATION lib) install(TARGETS osrm_partition DESTINATION lib) install(TARGETS osrm_customize DESTINATION lib) @@ -617,6 +639,11 @@ install(TARGETS osrm_update DESTINATION lib) install(TARGETS osrm_contract DESTINATION lib) install(TARGETS osrm_store DESTINATION lib) +install(EXPORT LibOSRMTargets + FILE LibOSRMTargets.cmake + NAMESPACE osrm:: + DESTINATION lib/cmake/LibOSRM) + # Install profiles and support library to /usr/local/share/osrm/profiles by default set(DefaultProfilesDir profiles) install(DIRECTORY ${DefaultProfilesDir} DESTINATION share/osrm) @@ -664,7 +691,15 @@ JOIN("-I${DEPENDENCIES_INCLUDE_DIRS}" " -I" PKGCONFIG_OSRM_INCLUDE_FLAGS) foreach(engine_lib ${ENGINE_LIBRARIES}) - if(TARGET ${engine_lib}) + # Translate well-known imported targets to portable pkg-config flags. + # Threads::Threads is INTERFACE-only and has no library name to derive a + # `-l` flag from; ZLIB::ZLIB would otherwise serialize as an absolute path + # via TARGET_LINKER_FILE, which is non-portable across install prefixes. + if(engine_lib STREQUAL "Threads::Threads") + list(APPEND PKGCONFIG_DEPENDENT_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}") + elseif(engine_lib STREQUAL "ZLIB::ZLIB") + list(APPEND PKGCONFIG_DEPENDENT_LIBRARIES "-lz") + elseif(TARGET ${engine_lib}) # Some imported targets (e.g. Boost::regex in modern Boost) are # INTERFACE-only and have no TARGET_LINKER_FILE. Only embed a linker # file for targets that actually produce one. @@ -697,6 +732,24 @@ if(NOT _is_multi_config) install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION ${PKGCONFIG_LIBRARY_DIR}/pkgconfig) endif() +# CMake package config: downstream users do +# find_package(LibOSRM REQUIRED) +# target_link_libraries(myapp PRIVATE osrm::osrm) +# LibOSRMTargets.cmake is written by install(EXPORT ...) above. +include(CMakePackageConfigHelpers) +configure_package_config_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/LibOSRMConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/LibOSRMConfig.cmake + INSTALL_DESTINATION lib/cmake/LibOSRM) +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/LibOSRMConfigVersion.cmake + VERSION ${OSRM_VERSION} + COMPATIBILITY SameMinorVersion) +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/LibOSRMConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/LibOSRMConfigVersion.cmake + DESTINATION lib/cmake/LibOSRM) + # uninstall target configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" diff --git a/cmake/LibOSRMConfig.cmake.in b/cmake/LibOSRMConfig.cmake.in new file mode 100644 index 00000000000..cdd91241dfc --- /dev/null +++ b/cmake/LibOSRMConfig.cmake.in @@ -0,0 +1,15 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) + +# osrm is built as a static library and links against all of the +# below, so consumers need them re-resolved at link time. +find_dependency(Boost 1.83 CONFIG COMPONENTS date_time iostreams regex thread) +find_dependency(TBB CONFIG) +find_dependency(Threads) +find_dependency(ZLIB) +find_dependency(LibArchive) + +include("${CMAKE_CURRENT_LIST_DIR}/LibOSRMTargets.cmake") + +check_required_components(LibOSRM) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index c1a9e5667e0..318175f63d3 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -16,23 +16,11 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") - -if(CMAKE_SIZEOF_VOID_P EQUAL 8) - message(STATUS "Building on a 64 bit system") -else() - message(STATUS "Building on a 32 bit system") -endif() - -find_package(Boost REQUIRED CONFIG COMPONENTS date_time iostreams thread) - -link_directories(${LibOSRM_LIBRARY_DIRS}) -add_executable(osrm-example example.cpp) - +# find_package(LibOSRM) resolves via the CMake Config package installed +# at /lib/cmake/LibOSRM/ (LibOSRMConfig.cmake). That package +# re-declares Boost / TBB / Threads / ZLIB as find_dependency() calls, +# so consumers do not have to call find_package() for them by hand. find_package(LibOSRM REQUIRED) -set(LibOSRM_LINKABLE_LIBRARIES ${LibOSRM_LIBRARIES} ${LibOSRM_DEPENDENT_LIBRARIES}) -list(REMOVE_DUPLICATES LibOSRM_LINKABLE_LIBRARIES) -target_link_libraries(osrm-example ${LibOSRM_LINKABLE_LIBRARIES}) -include_directories(SYSTEM ${LibOSRM_INCLUDE_DIRS}) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LibOSRM_CXXFLAGS}") +add_executable(osrm-example example.cpp) +target_link_libraries(osrm-example PRIVATE osrm::osrm) diff --git a/example/cmake/FindLibOSRM.cmake b/example/cmake/FindLibOSRM.cmake deleted file mode 100644 index 622ac3ed253..00000000000 --- a/example/cmake/FindLibOSRM.cmake +++ /dev/null @@ -1,44 +0,0 @@ -# - Try to find LibOSRM -# Once done this will define -# LibOSRM_FOUND - System has LibOSRM -# LibOSRM_LIBRARIES - The libraries and ldflags needed to use LibOSRM -# LibOSRM_DEPENDENT_LIBRARIES - The libraries and ldflags need to link LibOSRM dependencies -# LibOSRM_LIBRARY_DIRS - The libraries paths needed to find LibOSRM -# LibOSRM_CXXFLAGS - Compiler switches required for using LibOSRM - -find_package(PkgConfig) -pkg_search_module(PC_LibOSRM QUIET libosrm) - -function(JOIN VALUES GLUE OUTPUT) - string (REPLACE ";" "${GLUE}" _TMP_STR "${VALUES}") - set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE) -endfunction() - -list(REMOVE_ITEM PC_LibOSRM_CFLAGS " ") -JOIN("${PC_LibOSRM_CFLAGS}" " " output) - -set(LibOSRM_CXXFLAGS ${output}) -set(LibOSRM_LIBRARY_DIRS ${PC_LibOSRM_LIBRARY_DIRS}) - -find_path(LibOSRM_INCLUDE_DIR osrm/osrm.hpp - PATH_SUFFIXES osrm include/osrm include - HINTS ${PC_LibOSRM_INCLUDEDIR} ${PC_LibOSRM_INCLUDE_DIRS} - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /opt/local - /opt) - -set(LibOSRM_DEPENDENT_LIBRARIES ${PC_LibOSRM_STATIC_LDFLAGS}) -set(LibOSRM_LIBRARIES ${PC_LibOSRM_LDFLAGS}) - -include(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set LIBOSRM_FOUND to TRUE -# if all listed variables are TRUE -find_package_handle_standard_args(LibOSRM DEFAULT_MSG - LibOSRM_LIBRARY_DIRS - LibOSRM_CXXFLAGS - LibOSRM_LIBRARIES - LibOSRM_DEPENDENT_LIBRARIES - LibOSRM_INCLUDE_DIR) \ No newline at end of file