diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a7c131f..66b2c935 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,6 +99,12 @@ include(${CMAKE_CURRENT_LIST_DIR}/cmake/miniocpp-deps.cmake) list(APPEND MINIO_CPP_LIBS ${MINIO_CPP_DEPS_LINK_LIBS}) +if (MINIO_CPP_ENABLE_RDMA) + # Installed beside libminio, so -L${libdir} on the Libs line already finds + # it; a static consumer still has to name it. + list(APPEND MINIO_CPP_PC_LIBS_PRIVATE -ls3rdma) +endif() + if (WIN32) list(APPEND MINIO_CPP_LIBS wsock32) list(APPEND MINIO_CPP_LIBS ws2_32) @@ -459,5 +465,13 @@ install(FILES install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/tl" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") +string(REPLACE ";" " " MINIO_CPP_PC_REQUIRES_PRIVATE_STR "${MINIO_CPP_PC_REQUIRES_PRIVATE}") +string(REPLACE ";" " " MINIO_CPP_PC_LIBS_PRIVATE_STR "${MINIO_CPP_PC_LIBS_PRIVATE}") +if (MINIO_CPP_PC_REQUIRES_PRIVATE_STR) + set(MINIO_CPP_PC_REQUIRES_PRIVATE_LINE "Requires.private: ${MINIO_CPP_PC_REQUIRES_PRIVATE_STR}\n") +endif() +if (MINIO_CPP_PC_LIBS_PRIVATE_STR) + set(MINIO_CPP_PC_LIBS_PRIVATE_LINE "Libs.private: ${MINIO_CPP_PC_LIBS_PRIVATE_STR}\n") +endif() configure_file(miniocpp.pc.in ${CMAKE_CURRENT_BINARY_DIR}/miniocpp.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/miniocpp.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) diff --git a/cmake/miniocpp-deps.cmake b/cmake/miniocpp-deps.cmake index 385d6d1b..44d9a3d8 100644 --- a/cmake/miniocpp-deps.cmake +++ b/cmake/miniocpp-deps.cmake @@ -12,9 +12,42 @@ # MINIO_CPP_DEPS_LINK_LIBS -- link targets, in link order # MINIO_CPP_DEPS_EXPORT_TARGETS -- source-built targets the caller must # install into an export set +# MINIO_CPP_PC_REQUIRES_PRIVATE -- pkg-config modules a static consumer needs +# MINIO_CPP_PC_LIBS_PRIVATE -- link flags for private deps with no .pc set(MINIO_CPP_DEPS_EXPORT_TARGETS) +# miniocpp.pc cannot see target_link_libraries(), so the dependencies that +# reach a consumer only through libminio.a have to be recorded here, where the +# resolution branch that picked them is known. Each branch below appends to +# one of these; a hardcoded list in miniocpp.pc.in goes stale as soon as the +# dependency set moves, which is what left INIReader and brotli out of it. +set(MINIO_CPP_PC_REQUIRES_PRIVATE) +set(MINIO_CPP_PC_LIBS_PRIVATE) + +# Requires.private is preferred over a bare -l: these archives live in the +# dependency's own prefix (a vcpkg tree, say), not in miniocpp's libdir, so +# only the module's own .pc supplies the -L that finds them. The fallback is +# for a dependency installed into miniocpp's libdir, which -L${libdir} on the +# Libs line already covers. +macro(miniocpp_pc_private_dep module fallback) + set(_miniocpp_pc_ok FALSE) + if (PkgConfig_FOUND) + # A per-module result prefix: pkg_check_modules caches under it, and a + # stale hit would name a module that is not installed, which fails every + # later pkg-config query outright rather than merely under-linking. + pkg_check_modules(_miniocpp_pc_probe_${module} QUIET ${module}) + if (_miniocpp_pc_probe_${module}_FOUND) + set(_miniocpp_pc_ok TRUE) + endif() + endif() + if (_miniocpp_pc_ok) + list(APPEND MINIO_CPP_PC_REQUIRES_PRIVATE ${module}) + elseif (NOT "${fallback}" STREQUAL "") + list(APPEND MINIO_CPP_PC_LIBS_PRIVATE ${fallback}) + endif() +endmacro() + find_package(PkgConfig QUIET) find_package(OpenSSL REQUIRED) find_package(ZLIB REQUIRED) @@ -79,21 +112,53 @@ else() endif() endif() +# Brotli is not a dependency minio-cpp declares: it reaches libminio.a through +# cpp-httplib, which links it whenever it was built with CPPHTTPLIB_BROTLI_SUPPORT +# (the vcpkg port is). A consumer linking statically therefore needs it, so +# work out whether the httplib that was actually resolved uses it. Its config +# package exports HTTPLIB_IS_USING_BROTLI; the source build sets that only in +# its own directory scope, so fall back to the compile definition the target +# carries, whose BOOL genex is already expanded at this point. Do not match +# CPPHTTPLIB_BROTLI_SUPPORT as a plain substring: httplib lists the features it +# was built without in exactly the same way, wrapped in a false genex. +set(MINIO_CPP_HTTPLIB_USES_BROTLI FALSE) +if (DEFINED HTTPLIB_IS_USING_BROTLI) + set(MINIO_CPP_HTTPLIB_USES_BROTLI ${HTTPLIB_IS_USING_BROTLI}) +elseif (TARGET ${MINIO_CPP_HTTPLIB_TARGET}) + get_target_property(_miniocpp_httplib_defs + ${MINIO_CPP_HTTPLIB_TARGET} INTERFACE_COMPILE_DEFINITIONS) + if (_miniocpp_httplib_defs MATCHES "\\$<\\$]*)>:CPPHTTPLIB_BROTLI_SUPPORT>") + if (CMAKE_MATCH_1) + set(MINIO_CPP_HTTPLIB_USES_BROTLI TRUE) + endif() + elseif (_miniocpp_httplib_defs MATCHES "(^|;)CPPHTTPLIB_BROTLI_SUPPORT(;|$)") + set(MINIO_CPP_HTTPLIB_USES_BROTLI TRUE) + endif() +endif() +if (MINIO_CPP_HTTPLIB_USES_BROTLI) + miniocpp_pc_private_dep(libbrotlienc "-lbrotlienc") + miniocpp_pc_private_dep(libbrotlidec "-lbrotlidec") + miniocpp_pc_private_dep(libbrotlicommon "-lbrotlicommon") +endif() + # inih -- Alpine ships only the C library; build the C++ INIReader from source # (inih is meson-only, hence the manual target). An installed # miniocpp::miniocpp_inih (shipped with the miniocpp install) is reused as-is. if (TARGET miniocpp::miniocpp_inih) set(MINIO_CPP_INIH_TARGET miniocpp::miniocpp_inih) + list(APPEND MINIO_CPP_PC_LIBS_PRIVATE -lminiocpp_inih) else() find_package(unofficial-inih CONFIG QUIET) if (unofficial-inih_FOUND) set(MINIO_CPP_INIH_TARGET unofficial::inih::inireader) + miniocpp_pc_private_dep(INIReader "-lINIReader -linih") else() if (PkgConfig_FOUND) pkg_check_modules(MINIO_CPP_INIREADER QUIET IMPORTED_TARGET inireader) endif() if (MINIO_CPP_INIREADER_FOUND) set(MINIO_CPP_INIH_TARGET PkgConfig::MINIO_CPP_INIREADER) + list(APPEND MINIO_CPP_PC_REQUIRES_PRIVATE inireader) else() message(STATUS "inih INIReader: no package found, building from source") set(MINIO_CPP_INIH_SRC "${CMAKE_CURRENT_BINARY_DIR}/_deps/inih-src") @@ -125,6 +190,7 @@ else() set_target_properties(miniocpp_inih PROPERTIES POSITION_INDEPENDENT_CODE ON) set(MINIO_CPP_INIH_TARGET miniocpp_inih) list(APPEND MINIO_CPP_DEPS_EXPORT_TARGETS miniocpp_inih) + list(APPEND MINIO_CPP_PC_LIBS_PRIVATE -lminiocpp_inih) endif() endif() endif() diff --git a/miniocpp.pc.in b/miniocpp.pc.in index 8d361657..95750bc4 100644 --- a/miniocpp.pc.in +++ b/miniocpp.pc.in @@ -8,5 +8,5 @@ Description: @PROJECT_DESCRIPTION@ Version: @PROJECT_VERSION@ Requires: libcrypto libssl pugixml zlib -Libs: -L${libdir} -lminio@MINIO_CPP_PC_EXTRA_LIBS@ -Cflags: -I${includedir} \ No newline at end of file +@MINIO_CPP_PC_REQUIRES_PRIVATE_LINE@Libs: -L${libdir} -lminio@MINIO_CPP_PC_EXTRA_LIBS@ +@MINIO_CPP_PC_LIBS_PRIVATE_LINE@Cflags: -I${includedir}