From 2f91a1d6207302dc7397a9981b9bc3bc39d8a3df Mon Sep 17 00:00:00 2001 From: Scott K Logan Date: Thu, 2 Oct 2025 20:38:08 -0500 Subject: [PATCH] Introduce CMake find modules for dependencies While this approach maintains pkg-config as the preferred mechanism for discovering dependencies, it allows us to support the older config mechanism shipped with many of these dependencies on older distributions like CentOS 7. An additional part of this change is the switch to CMake targets for dependencies, which significantly reduces boilerplate in the main CMakeLists.txt. --- CMakeLists.txt | 60 +++++++++++------------------- cmake/Findassuan.cmake | 48 ++++++++++++++++++++++++ cmake/Findcreaterepo_c.cmake | 18 +++++++++ cmake/Findglib-2.0.cmake | 18 +++++++++ cmake/Findgpg-error.cmake | 48 ++++++++++++++++++++++++ cmake/Findgpgme.cmake | 48 ++++++++++++++++++++++++ cmake/use_config_util.cmake | 71 ++++++++++++++++++++++++++++++++++++ test/CMakeLists.txt | 8 ++-- 8 files changed, 276 insertions(+), 43 deletions(-) create mode 100644 cmake/Findassuan.cmake create mode 100644 cmake/Findcreaterepo_c.cmake create mode 100644 cmake/Findglib-2.0.cmake create mode 100644 cmake/Findgpg-error.cmake create mode 100644 cmake/Findgpgme.cmake create mode 100644 cmake/use_config_util.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 05ef314..466a3f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,30 +14,24 @@ endif() add_compile_options(-Wall -Wextra -Wconversion -Wpedantic) -include(FindPkgConfig) -pkg_check_modules(CREATEREPO_C REQUIRED createrepo_c) -pkg_check_modules(GLIB2 REQUIRED glib-2.0) -pkg_check_modules(GPG_ERROR REQUIRED gpg-error) -pkg_check_modules(GPGME REQUIRED gpgme) -pkg_check_modules(LIBASSUAN REQUIRED libassuan) +list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +find_package(createrepo_c 0.13.0 MODULE REQUIRED) +find_package(glib-2.0 MODULE REQUIRED) +find_package(gpg-error 1.13 MODULE REQUIRED) +find_package(gpgme 1.7.0 MODULE REQUIRED) +find_package(assuan 2.2.0 MODULE REQUIRED) # Repository operations add_library(createrepo-cache STATIC src/createrepo-cache/coordinator.c src/createrepo-cache/repo_cache.c) target_include_directories(createrepo-cache PUBLIC - $ - $) -target_include_directories(createrepo-cache SYSTEM PUBLIC - ${CREATEREPO_C_INCLUDE_DIRS} - ${GLIB2_INCLUDE_DIRS} - ${GPG_ERROR_INCLUDE_DIRS} - ${GPGME_INCLUDE_DIRS}) -target_link_libraries(createrepo-cache PRIVATE - ${CREATEREPO_C_LIBRARIES} - ${GLIB2_LIBRARIES} - ${GPG_ERROR_LIBRARIES} - ${GPGME_LIBRARIES}) + $) +target_link_libraries(createrepo-cache PUBLIC + createrepo_c + glib-2.0 + gpg-error + gpgme) target_compile_definitions(createrepo-cache PRIVATE -DG_LOG_DOMAIN="CREATEREPO_CACHE") set_target_properties(createrepo-cache PROPERTIES @@ -57,38 +51,26 @@ add_library(createrepo-agent-lib OBJECT target_include_directories(createrepo-agent-lib PUBLIC $ $) -target_include_directories(createrepo-agent-lib SYSTEM PRIVATE - ${CREATEREPO_C_INCLUDE_DIRS}) -target_include_directories(createrepo-agent-lib SYSTEM PUBLIC - ${GLIB2_INCLUDE_DIRS} - ${GPG_ERROR_INCLUDE_DIRS} - ${LIBASSUAN_INCLUDE_DIRS}) target_link_libraries(createrepo-agent-lib PRIVATE createrepo-cache - ${CREATEREPO_C_LIBRARIES}) + createrepo_c) target_link_libraries(createrepo-agent-lib PUBLIC - ${GLIB2_LIBRARIES} - ${GPG_ERROR_LIBRARIES} - ${LIBASSUAN_LIBRARIES}) + assuan + gpg-error + glib-2.0) target_compile_definitions(createrepo-agent-lib PRIVATE -DG_LOG_DOMAIN="CREATEREPO_AGENT") # Executable add_executable(${PROJECT_NAME} src/${PROJECT_NAME}/agent.c) -target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE - ${CREATEREPO_C_INCLUDE_DIRS} - ${GLIB2_INCLUDE_DIRS} - ${GPG_ERROR_INCLUDE_DIRS} - ${GPGME_INCLUDE_DIRS} - ${LIBASSUAN_INCLUDE_DIRS}) target_link_libraries(${PROJECT_NAME} PRIVATE + assuan createrepo-agent-lib - ${CREATEREPO_C_LIBRARIES} - ${GLIB2_LIBRARIES} - ${GPG_ERROR_LIBRARIES} - ${GPGME_LIBRARIES} - ${LIBASSUAN_LIBRARIES}) + createrepo_c + glib-2.0 + gpg-error + gpgme) install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin COMPONENT bin) diff --git a/cmake/Findassuan.cmake b/cmake/Findassuan.cmake new file mode 100644 index 0000000..7ab2b48 --- /dev/null +++ b/cmake/Findassuan.cmake @@ -0,0 +1,48 @@ +cmake_minimum_required(VERSION 3.15) + +include(FindPackageHandleStandardArgs) + +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_check_modules(assuan QUIET IMPORTED_TARGET libassuan) + list(GET assuan_LINK_LIBRARIES 0 assuan_LIBRARY) +endif() + +if(NOT assuan_FOUND) + find_program(LIBASSUAN_CONFIG NAMES libassuan-config) + if(LIBASSUAN_CONFIG) + include(use_config_util) + + extract_libs(assuan_LINK_LIBRARIES + ${LIBASSUAN_CONFIG} --libs) + list(GET assuan_LINK_LIBRARIES 0 assuan_LIBRARY) + + extract_includes(assuan_INCLUDE_DIRS + ${LIBASSUAN_CONFIG} --cflags) + + execute_process( + COMMAND ${LIBASSUAN_CONFIG} --version + OUTPUT_VARIABLE assuan_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() +endif() + +find_package_handle_standard_args(assuan + REQUIRED_VARS + assuan_LIBRARY + assuan_VERSION + VERSION_VAR assuan_VERSION) + +if(TARGET PkgConfig::assuan) + add_library(assuan ALIAS PkgConfig::assuan) +else() + add_library(assuan UNKNOWN IMPORTED) + set_target_properties(assuan PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${assuan_INCLUDE_DIRS}") + set(assuan_OTHER_LIBRARIES ${assuan_LINK_LIBRARIES}) + list(POP_FRONT assuan_OTHER_LIBRARIES) + set_target_properties(assuan PROPERTIES INTERFACE_LINK_LIBRARIES "${assuan_OTHER_LIBRARIES}") + unset(assuan_OTHER_LIBRARIES) + set_property(TARGET assuan APPEND PROPERTY IMPORTED_LOCATION "${assuan_LIBRARY}") +endif() + +mark_as_advanced(assuan_LIBRARY) diff --git a/cmake/Findcreaterepo_c.cmake b/cmake/Findcreaterepo_c.cmake new file mode 100644 index 0000000..f180b48 --- /dev/null +++ b/cmake/Findcreaterepo_c.cmake @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.15) + +include(FindPackageHandleStandardArgs) + +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_check_modules(createrepo_c QUIET REQUIRED IMPORTED_TARGET createrepo_c) + list(GET createrepo_c_LINK_LIBRARIES 0 createrepo_c_LIBRARY) + mark_as_advanced(createrepo_c_LIBRARY) +endif() + +find_package_handle_standard_args(createrepo_c + REQUIRED_VARS + createrepo_c_LIBRARY + createrepo_c_VERSION + VERSION_VAR createrepo_c_VERSION) + +add_library(createrepo_c ALIAS PkgConfig::createrepo_c) diff --git a/cmake/Findglib-2.0.cmake b/cmake/Findglib-2.0.cmake new file mode 100644 index 0000000..1348e32 --- /dev/null +++ b/cmake/Findglib-2.0.cmake @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.15) + +include(FindPackageHandleStandardArgs) + +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_check_modules(glib-2.0 QUIET REQUIRED IMPORTED_TARGET glib-2.0) + list(GET glib-2.0_LINK_LIBRARIES 0 glib-2.0_LIBRARY) + mark_as_advanced(glib-2.0_LIBRARY) +endif() + +find_package_handle_standard_args(glib-2.0 + REQUIRED_VARS + glib-2.0_LIBRARY + glib-2.0_VERSION + VERSION_VAR glib-2.0_VERSION) + +add_library(glib-2.0 ALIAS PkgConfig::glib-2.0) diff --git a/cmake/Findgpg-error.cmake b/cmake/Findgpg-error.cmake new file mode 100644 index 0000000..1301a31 --- /dev/null +++ b/cmake/Findgpg-error.cmake @@ -0,0 +1,48 @@ +cmake_minimum_required(VERSION 3.15) + +include(FindPackageHandleStandardArgs) + +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_check_modules(gpg-error QUIET IMPORTED_TARGET gpg-error) + list(GET gpg-error_LINK_LIBRARIES 0 gpg-error_LIBRARY) +endif() + +if(NOT gpg-error_FOUND) + find_program(GPG_ERROR_CONFIG NAMES gpg-error-config) + if(GPG_ERROR_CONFIG) + include(use_config_util) + + extract_libs(gpg-error_LINK_LIBRARIES + ${GPG_ERROR_CONFIG} --libs) + list(GET gpg-error_LINK_LIBRARIES 0 gpg-error_LIBRARY) + + extract_includes(gpg-error_INCLUDE_DIRS + ${GPG_ERROR_CONFIG} --cflags) + + execute_process( + COMMAND ${GPG_ERROR_CONFIG} --version + OUTPUT_VARIABLE gpg-error_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() +endif() + +find_package_handle_standard_args(gpg-error + REQUIRED_VARS + gpg-error_LIBRARY + gpg-error_VERSION + VERSION_VAR gpg-error_VERSION) + +if(TARGET PkgConfig::gpg-error) + add_library(gpg-error ALIAS PkgConfig::gpg-error) +else() + add_library(gpg-error UNKNOWN IMPORTED) + set_target_properties(gpg-error PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${gpg-error_INCLUDE_DIRS}") + set(gpg-error_OTHER_LIBRARIES ${gpg-error_LINK_LIBRARIES}) + list(POP_FRONT gpg-error_OTHER_LIBRARIES) + set_target_properties(gpg-error PROPERTIES INTERFACE_LINK_LIBRARIES "${gpg-error_OTHER_LIBRARIES}") + unset(gpg-error_OTHER_LIBRARIES) + set_property(TARGET gpg-error APPEND PROPERTY IMPORTED_LOCATION "${gpg-error_LIBRARY}") +endif() + +mark_as_advanced(gpg-error_LIBRARY) diff --git a/cmake/Findgpgme.cmake b/cmake/Findgpgme.cmake new file mode 100644 index 0000000..d1de765 --- /dev/null +++ b/cmake/Findgpgme.cmake @@ -0,0 +1,48 @@ +cmake_minimum_required(VERSION 3.15) + +include(FindPackageHandleStandardArgs) + +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_check_modules(gpgme QUIET IMPORTED_TARGET gpgme) + list(GET gpgme_LINK_LIBRARIES 0 gpgme_LIBRARY) +endif() + +if(NOT gpgme_FOUND) + find_program(GPGME_CONFIG NAMES gpgme-config) + if(GPGME_CONFIG) + include(use_config_util) + + extract_libs(gpgme_LINK_LIBRARIES + ${GPGME_CONFIG} --libs) + list(GET gpgme_LINK_LIBRARIES 0 gpgme_LIBRARY) + + extract_includes(gpgme_INCLUDE_DIRS + ${GPGME_CONFIG} --cflags) + + execute_process( + COMMAND ${GPGME_CONFIG} --version + OUTPUT_VARIABLE gpgme_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() +endif() + +find_package_handle_standard_args(gpgme + REQUIRED_VARS + gpgme_LIBRARY + gpgme_VERSION + VERSION_VAR gpgme_VERSION) + +if(TARGET PkgConfig::gpgme) + add_library(gpgme ALIAS PkgConfig::gpgme) +else() + add_library(gpgme UNKNOWN IMPORTED) + set_target_properties(gpgme PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${gpgme_INCLUDE_DIRS}") + set(gpgme_OTHER_LIBRARIES ${gpgme_LINK_LIBRARIES}) + list(POP_FRONT gpgme_OTHER_LIBRARIES) + set_target_properties(gpgme PROPERTIES INTERFACE_LINK_LIBRARIES "${gpgme_OTHER_LIBRARIES}") + unset(gpgme_OTHER_LIBRARIES) + set_property(TARGET gpgme APPEND PROPERTY IMPORTED_LOCATION "${gpgme_LIBRARY}") +endif() + +mark_as_advanced(gpgme_LIBRARY) diff --git a/cmake/use_config_util.cmake b/cmake/use_config_util.cmake new file mode 100644 index 0000000..e1ec00c --- /dev/null +++ b/cmake/use_config_util.cmake @@ -0,0 +1,71 @@ +function(extract_includes OUT_VAR) + list(SUBLIST ARGV 1 -1 CMDARGS) + execute_process( + COMMAND ${CMDARGS} + OUTPUT_VARIABLE STANDARD_OUTPUT + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE COMMAND_RESULT) + if(NOT "${COMMAND_RESULT}" STREQUAL "0") + return() + endif() + + separate_arguments(STANDARD_OUTPUT) + + set(INCDIRS) + foreach(arg ${STANDARD_OUTPUT}) + if("${arg}" MATCHES "^-I(.+)") + list(APPEND INCDIRS "${CMAKE_MATCH_1}") + endif() + endforeach() + + set(FULL_INCDIRS) + foreach(incdir ${INCDIRS}) + file(TO_CMAKE_PATH "${incdir}" incdir) + list(APPEND FULL_INCDIRS "${incdir}") + endforeach() + + set(${OUT_VAR} ${FULL_INCDIRS} PARENT_SCOPE) +endfunction() + +function(extract_libs OUT_VAR) + list(SUBLIST ARGV 1 -1 CMDARGS) + execute_process( + COMMAND ${CMDARGS} + OUTPUT_VARIABLE STANDARD_OUTPUT + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE COMMAND_RESULT) + if(NOT "${COMMAND_RESULT}" STREQUAL "0") + return() + endif() + + separate_arguments(STANDARD_OUTPUT) + + set(LIBDIRS) + set(LIBS) + foreach(arg ${STANDARD_OUTPUT}) + if("${arg}" MATCHES "^-L(.+)") + list(APPEND LIBDIRS "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^-l(.+)") + list(APPEND LIBS "${CMAKE_MATCH_1}") + endif() + endforeach() + + set(HINTS) + foreach(libdir ${LIBDIRS}) + file(TO_CMAKE_PATH "${libdir}" libdir) + list(APPEND HINTS "${libdir}") + endforeach() + + set(FULL_LIBS) + foreach(lib ${LIBS}) + find_library(${lib}_path + NAMES ${lib} + HINTS ${HINTS}) + if(NOT ${${lib}_path_FOUND}) + return() + endif() + list(APPEND FULL_LIBS ${${lib}_path}) + endforeach() + + set(${OUT_VAR} ${FULL_LIBS} PARENT_SCOPE) +endfunction() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c868f1e..43fcfb7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -10,16 +10,16 @@ find_package(GTest REQUIRED) macro(add_cache_test NAME) add_executable(test_${NAME} "main.cpp" "test_${NAME}.cpp") target_link_libraries(test_${NAME} - ${GTEST_LIBRARIES} - createrepo-cache) + createrepo-cache + GTest::gtest) add_test(NAME ${NAME} COMMAND test_${NAME}) endmacro() macro(add_integration_test NAME) add_executable(test_${NAME} "integration_main.cpp" "test_${NAME}.cpp") target_link_libraries(test_${NAME} - ${GTEST_LIBRARIES} - createrepo-agent-lib) + createrepo-agent-lib + GTest::gtest) add_test(NAME ${NAME} COMMAND test_${NAME}) endmacro()