From 05758966a41fb07c3254f06a7cd917779ca0b1b7 Mon Sep 17 00:00:00 2001 From: jiuker Date: Mon, 17 Aug 2026 10:25:43 +0800 Subject: [PATCH 1/2] build: support building on Alpine Linux (musl) without vcpkg vcpkg's default setup downloads glibc-linked tools such as CMake, which do not run on musl, and Alpine ships no packages for curlpp or the C++ INIReader (fixes #213). Dependency resolution moves to cmake/miniocpp-deps.cmake, shared with the installed miniocpp-config.cmake. Each dependency resolves as: vcpkg CONFIG package, then pkg-config, then upstream source cloned at configure time with plain git (CMake 3.10-compatible, no FetchContent) -- curlpp pinned to a master commit that needs no patches, inih pinned to its r58 commit. The source-built deps are installed into an export set, and the consumer config re-applies the link interface, reusing the installed miniocpp::miniocpp_inih instead of re-fetching. CMP0091 is guarded so the CMake 3.10 floor holds. Also adds an Alpine CI job (image and MinIO binary pinned by digest / checksum, readiness polling) and README build instructions. Library code is untouched; vcpkg builds resolve the same libraries as before. --- .github/workflows/ci.yml | 44 +++++++++++++ CMakeLists.txt | 43 +++++++------ README.md | 17 +++++ cmake/miniocpp-deps.cmake | 132 ++++++++++++++++++++++++++++++++++++++ miniocpp-config.cmake.in | 14 ++-- 5 files changed, 225 insertions(+), 25 deletions(-) create mode 100644 cmake/miniocpp-deps.cmake diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5a7fb656..511a147a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -197,3 +197,47 @@ jobs: run: | cd minio-cpp/build ctest -C ${{ matrix.config.build_type }} + + # Alpine/musl: vcpkg's default setup downloads glibc-linked tools, and + # Alpine lacks curlpp / INIReader packages -- exercises the pkg-config + + # FetchContent fallback path. + build-alpine: + name: Alpine_Latest_GCC + runs-on: ubuntu-latest + container: alpine:3.24@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b + steps: + - name: Install dependencies + run: | + apk add --no-cache build-base cmake git ninja pkgconf \ + curl-dev inih-dev nlohmann-json openssl-dev pugixml-dev zlib-dev + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false + - name: Configure and Build + run: | + cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DMINIO_CPP_TEST=ON + cmake --build build + - name: Start MinIO server + run: | + MINIO_RELEASE=RELEASE.2025-09-07T16-13-09Z + wget --quiet https://dl.min.io/server/minio/release/linux-amd64/archive/minio.${MINIO_RELEASE} + wget --quiet https://dl.min.io/server/minio/release/linux-amd64/archive/minio.${MINIO_RELEASE}.sha256sum + sha256sum -c minio.${MINIO_RELEASE}.sha256sum + mv minio.${MINIO_RELEASE} minio + chmod +x minio + mkdir -p /data + MINIO_CI_CD=true ./minio server /data --address 127.0.0.1:9000 & + MINIO_PID=$! + for i in $(seq 1 30); do + if wget -q -O /dev/null http://127.0.0.1:9000/minio/health/live; then + exit 0 + fi + kill -0 $MINIO_PID 2>/dev/null || { echo "MinIO server exited"; exit 1; } + sleep 1 + done + echo "MinIO server did not become ready" + exit 1 + - name: Run tests + run: | + SERVER_ENDPOINT=127.0.0.1:9000 ACCESS_KEY=minioadmin SECRET_KEY=minioadmin \ + ./build/tests diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d57ab22..44326507 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,9 @@ # SPDX-License-Identifier: Apache-2.0 cmake_minimum_required(VERSION 3.10) -cmake_policy(SET CMP0091 NEW) +if (POLICY CMP0091) + cmake_policy(SET CMP0091 NEW) +endif() # Minio C++ Project # ----------------- @@ -89,22 +91,13 @@ endif() # Dependencies # ------------ +# +# Resolution (vcpkg -> pkg-config -> FetchContent) lives in +# cmake/miniocpp-deps.cmake, shared with the installed miniocpp-config.cmake. -find_package(OpenSSL REQUIRED) -find_package(unofficial-curlpp CONFIG REQUIRED) -find_package(unofficial-inih CONFIG REQUIRED) -find_package(nlohmann_json CONFIG REQUIRED) -find_package(pugixml CONFIG REQUIRED) -find_package(ZLIB REQUIRED) - -list(APPEND MINIO_CPP_LIBS - unofficial::curlpp::curlpp - unofficial::inih::inireader - nlohmann_json::nlohmann_json - pugixml - OpenSSL::SSL OpenSSL::Crypto - ZLIB::ZLIB -) +include(${CMAKE_CURRENT_LIST_DIR}/cmake/miniocpp-deps.cmake) + +list(APPEND MINIO_CPP_LIBS ${MINIO_CPP_DEPS_LINK_LIBS}) if (WIN32) list(APPEND MINIO_CPP_LIBS wsock32) @@ -321,14 +314,28 @@ install(TARGETS miniocpp LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") +# Source-built deps must be in an export set for install(EXPORT) to resolve +# them (curlpp exports itself; miniocpp_inih does not). +if (MINIO_CPP_DEPS_EXPORT_TARGETS) + install(TARGETS ${MINIO_CPP_DEPS_EXPORT_TARGETS} + EXPORT miniocpp-targets + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}") +endif() + +# The link interface is not exported; miniocpp-config.cmake re-applies it. install(EXPORT miniocpp-targets NAMESPACE miniocpp:: - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/miniocpp" - EXPORT_LINK_INTERFACE_LIBRARIES) + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/miniocpp") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/miniocpp-config.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/miniocpp") +# The consumer config includes the dependency resolver. +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/miniocpp-deps.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/miniocpp") + install(FILES ${MINIO_CPP_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/miniocpp") diff --git a/README.md b/README.md index 71b859b1..ae10d1b9 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,23 @@ $ cd minio-cpp $ ./configure.sh -DMINIO_CPP_TEST=ON ``` +### Building on Alpine Linux (musl) + +`vcpkg` can run on Alpine, but its default setup downloads glibc-linked tools +such as CMake, which do not run on musl (setting `VCPKG_FORCE_SYSTEM_BINARIES` +forces use of the apk-installed tools instead). Alpine also has no packages +for `curlpp` or the C++ `INIReader`. The dependency resolver +(`cmake/miniocpp-deps.cmake`) therefore falls back to `pkg-config` and then +to fetching those two libraries from source, so a plain system-package build +works: + +```bash +$ apk add build-base cmake git ninja pkgconf \ + curl-dev inih-dev nlohmann-json openssl-dev pugixml-dev zlib-dev +$ cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DMINIO_CPP_TEST=ON +$ cmake --build build +``` + ## Example:: file-uploader.cc ```c++ diff --git a/cmake/miniocpp-deps.cmake b/cmake/miniocpp-deps.cmake new file mode 100644 index 00000000..01683380 --- /dev/null +++ b/cmake/miniocpp-deps.cmake @@ -0,0 +1,132 @@ +# miniocpp-deps.cmake -- resolve the third-party dependencies of minio-cpp. +# Shared with the installed miniocpp-config.cmake. +# +# Resolution order per dependency: vcpkg CONFIG package -> pkg-config -> +# upstream source. The source branch is for distros where vcpkg is +# impractical (its default setup downloads glibc-linked tools that do not run +# on musl) and no curlpp / C++ INIReader packages exist. It clones at +# configure time with plain git, so it works on the CMake 3.10 floor (no +# FetchContent); vcpkg builds never reach it. +# +# Defines for the caller: +# 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 + +set(MINIO_CPP_DEPS_EXPORT_TARGETS) + +find_package(PkgConfig QUIET) +find_package(OpenSSL REQUIRED) +find_package(ZLIB REQUIRED) +find_package(nlohmann_json CONFIG REQUIRED) + +# curlpp -- pinned master commit, no patches needed: CURLOPT_CLOSEPOLICY is +# gone upstream (dropped in curl 8.10) and the build is target-based and +# self-exporting. Static target keeps BUILD_SHARED_LIBS=OFF builds working. +find_package(unofficial-curlpp CONFIG QUIET) +if (unofficial-curlpp_FOUND) + set(MINIO_CPP_CURLPP_TARGET unofficial::curlpp::curlpp) +else() + if (PkgConfig_FOUND) + pkg_check_modules(MINIO_CPP_CURLPP QUIET IMPORTED_TARGET curlpp) + endif() + if (MINIO_CPP_CURLPP_FOUND) + set(MINIO_CPP_CURLPP_TARGET PkgConfig::MINIO_CPP_CURLPP) + else() + message(STATUS "curlpp: no package found, building from source") + set(MINIO_CPP_CURLPP_SRC "${CMAKE_CURRENT_BINARY_DIR}/_deps/curlpp-src") + if (NOT EXISTS "${MINIO_CPP_CURLPP_SRC}/CMakeLists.txt") + execute_process(COMMAND git clone --quiet + https://github.com/jpbarrette/curlpp.git + "${MINIO_CPP_CURLPP_SRC}" + RESULT_VARIABLE _curlpp_clone) + if (NOT _curlpp_clone STREQUAL "0") + message(FATAL_ERROR "curlpp: git clone failed") + endif() + execute_process(COMMAND git checkout --quiet + ec1b66e699557cd9d608d322c013a1ebda16bd08 + WORKING_DIRECTORY "${MINIO_CPP_CURLPP_SRC}" + RESULT_VARIABLE _curlpp_checkout) + if (NOT _curlpp_checkout STREQUAL "0") + message(FATAL_ERROR "curlpp: git checkout of pinned commit failed") + endif() + endif() + set(CURLPP_BUILD_SHARED_LIBS OFF CACHE BOOL "Build curlpp shared library" FORCE) + add_subdirectory("${MINIO_CPP_CURLPP_SRC}" + "${CMAKE_CURRENT_BINARY_DIR}/_deps/curlpp-build") + set(MINIO_CPP_CURLPP_TARGET curlpp_static) + set_target_properties(curlpp_static PROPERTIES POSITION_INDEPENDENT_CODE ON) + endif() +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) +else() + find_package(unofficial-inih CONFIG QUIET) + if (unofficial-inih_FOUND) + set(MINIO_CPP_INIH_TARGET unofficial::inih::inireader) + 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) + else() + message(STATUS "inih INIReader: no package found, building from source") + set(MINIO_CPP_INIH_SRC "${CMAKE_CURRENT_BINARY_DIR}/_deps/inih-src") + if (NOT EXISTS "${MINIO_CPP_INIH_SRC}/ini.h") + execute_process(COMMAND git clone --quiet + https://github.com/benhoyt/inih.git + "${MINIO_CPP_INIH_SRC}" + RESULT_VARIABLE _inih_clone) + if (NOT _inih_clone STREQUAL "0") + message(FATAL_ERROR "inih: git clone failed") + endif() + execute_process(COMMAND git checkout --quiet + 5cc5e2c24642513aaa5b19126aad42d0e4e0923e # r58 + WORKING_DIRECTORY "${MINIO_CPP_INIH_SRC}" + RESULT_VARIABLE _inih_checkout) + if (NOT _inih_checkout STREQUAL "0") + message(FATAL_ERROR "inih: git checkout of pinned commit failed") + endif() + endif() + add_library(miniocpp_inih STATIC + "${MINIO_CPP_INIH_SRC}/ini.c" + "${MINIO_CPP_INIH_SRC}/cpp/INIReader.cpp" + ) + # BUILD_INTERFACE only: the cloned tree lives in the build dir. + target_include_directories(miniocpp_inih PUBLIC + $) + 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) + endif() + endif() +endif() + +find_package(pugixml CONFIG QUIET) +if (pugixml_FOUND) + set(MINIO_CPP_PUGIXML_TARGET pugixml) +else() + if (PkgConfig_FOUND) + pkg_check_modules(MINIO_CPP_PUGIXML QUIET IMPORTED_TARGET pugixml) + endif() + if (NOT MINIO_CPP_PUGIXML_FOUND) + message(FATAL_ERROR + "pugixml: neither a CMake package (pugixml) nor pkg-config (pugixml.pc) was found") + endif() + set(MINIO_CPP_PUGIXML_TARGET PkgConfig::MINIO_CPP_PUGIXML) +endif() + +set(MINIO_CPP_DEPS_LINK_LIBS + ${MINIO_CPP_CURLPP_TARGET} + ${MINIO_CPP_INIH_TARGET} + nlohmann_json::nlohmann_json + ${MINIO_CPP_PUGIXML_TARGET} + OpenSSL::SSL + OpenSSL::Crypto + ZLIB::ZLIB +) diff --git a/miniocpp-config.cmake.in b/miniocpp-config.cmake.in index 16e99eb0..9ef0db42 100644 --- a/miniocpp-config.cmake.in +++ b/miniocpp-config.cmake.in @@ -1,10 +1,10 @@ @PACKAGE_INIT@ -find_package(OpenSSL REQUIRED) -find_package(unofficial-curlpp CONFIG REQUIRED) -find_package(unofficial-inih CONFIG REQUIRED) -find_package(nlohmann_json CONFIG REQUIRED) -find_package(pugixml CONFIG REQUIRED) -find_package(ZLIB REQUIRED) - +# The exported miniocpp::miniocpp_inih target must be visible to the +# dependency resolver, so it can be reused instead of re-fetched. include("${CMAKE_CURRENT_LIST_DIR}/miniocpp-targets.cmake") + +include("${CMAKE_CURRENT_LIST_DIR}/miniocpp-deps.cmake") + +# The link interface is not exported; re-apply it. +target_link_libraries(miniocpp::miniocpp INTERFACE ${MINIO_CPP_DEPS_LINK_LIBS}) From e24625ea6146ae62b4c0d1f9054f61f7519d2623 Mon Sep 17 00:00:00 2001 From: jiuker Date: Mon, 17 Aug 2026 16:35:04 +0800 Subject: [PATCH 2/2] apply suggestion --- .github/workflows/ci.yml | 2 +- CLAUDE.md | 2 +- CMakeLists.txt | 4 ++-- README.md | 4 ++-- cmake/miniocpp-deps.cmake | 34 +++++++++++++++++++--------------- docs/README.md | 2 +- miniocpp-config.cmake.in | 7 +++++-- 7 files changed, 31 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 511a147a..265d824e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -200,7 +200,7 @@ jobs: # Alpine/musl: vcpkg's default setup downloads glibc-linked tools, and # Alpine lacks curlpp / INIReader packages -- exercises the pkg-config + - # FetchContent fallback path. + # upstream source fallback path. build-alpine: name: Alpine_Latest_GCC runs-on: ubuntu-latest diff --git a/CLAUDE.md b/CLAUDE.md index d3e1d34f..e8d123b2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,7 +10,7 @@ MinIO C++ SDK is an S3-compatible object storage client library. This fork exten ### Prerequisites -- CMake 3.10+ +- CMake 3.13.4+ - C++17 compiler - vcpkg package manager (set `VCPKG_ROOT` environment variable) - `libs3rdma` vendored under `vendor/s3rdma/` (for RDMA support). Build and diff --git a/CMakeLists.txt b/CMakeLists.txt index 44326507..9aed78b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ # # SPDX-License-Identifier: Apache-2.0 -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.13.4) if (POLICY CMP0091) cmake_policy(SET CMP0091 NEW) endif() @@ -92,7 +92,7 @@ endif() # Dependencies # ------------ # -# Resolution (vcpkg -> pkg-config -> FetchContent) lives in +# Resolution (vcpkg -> pkg-config -> upstream source) lives in # cmake/miniocpp-deps.cmake, shared with the installed miniocpp-config.cmake. include(${CMAKE_CURRENT_LIST_DIR}/cmake/miniocpp-deps.cmake) diff --git a/README.md b/README.md index ae10d1b9..d53e16c3 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ For a complete list of APIs and examples, please take a look at the [MinIO C++ C ## Build Requirements -* [cmake](https://cmake.org/) 3.10 or higher. +* [cmake](https://cmake.org/) 3.13.4 or higher. * [vcpkg](https://vcpkg.io/en/index.html) package manager. * A working C++ compiler that supports at least C++17. @@ -69,7 +69,7 @@ from every pushed `v*` tag (and can also be built on demand from the MinIO C++ cliend SDK can be consumed as a dependency in CMakeLists.txt, the following can be used as an example: ```cmake -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.13.4) project(miniocpp_example LANGUAGES C CXX) diff --git a/cmake/miniocpp-deps.cmake b/cmake/miniocpp-deps.cmake index 01683380..a0a336e2 100644 --- a/cmake/miniocpp-deps.cmake +++ b/cmake/miniocpp-deps.cmake @@ -5,7 +5,7 @@ # upstream source. The source branch is for distros where vcpkg is # impractical (its default setup downloads glibc-linked tools that do not run # on musl) and no curlpp / C++ INIReader packages exist. It clones at -# configure time with plain git, so it works on the CMake 3.10 floor (no +# configure time with plain git, so it works on the CMake 3.13.4 floor (no # FetchContent); vcpkg builds never reach it. # # Defines for the caller: @@ -43,13 +43,15 @@ else() if (NOT _curlpp_clone STREQUAL "0") message(FATAL_ERROR "curlpp: git clone failed") endif() - execute_process(COMMAND git checkout --quiet - ec1b66e699557cd9d608d322c013a1ebda16bd08 - WORKING_DIRECTORY "${MINIO_CPP_CURLPP_SRC}" - RESULT_VARIABLE _curlpp_checkout) - if (NOT _curlpp_checkout STREQUAL "0") - message(FATAL_ERROR "curlpp: git checkout of pinned commit failed") - endif() + endif() + # Also reset a cached checkout to the pinned commit, not just a fresh + # clone. + execute_process(COMMAND git checkout --quiet + ec1b66e699557cd9d608d322c013a1ebda16bd08 + WORKING_DIRECTORY "${MINIO_CPP_CURLPP_SRC}" + RESULT_VARIABLE _curlpp_checkout) + if (NOT _curlpp_checkout STREQUAL "0") + message(FATAL_ERROR "curlpp: git checkout of pinned commit failed") endif() set(CURLPP_BUILD_SHARED_LIBS OFF CACHE BOOL "Build curlpp shared library" FORCE) add_subdirectory("${MINIO_CPP_CURLPP_SRC}" @@ -85,13 +87,15 @@ else() if (NOT _inih_clone STREQUAL "0") message(FATAL_ERROR "inih: git clone failed") endif() - execute_process(COMMAND git checkout --quiet - 5cc5e2c24642513aaa5b19126aad42d0e4e0923e # r58 - WORKING_DIRECTORY "${MINIO_CPP_INIH_SRC}" - RESULT_VARIABLE _inih_checkout) - if (NOT _inih_checkout STREQUAL "0") - message(FATAL_ERROR "inih: git checkout of pinned commit failed") - endif() + endif() + # Also reset a cached checkout to the pinned commit, not just a fresh + # clone. + execute_process(COMMAND git checkout --quiet + 5cc5e2c24642513aaa5b19126aad42d0e4e0923e # r58 + WORKING_DIRECTORY "${MINIO_CPP_INIH_SRC}" + RESULT_VARIABLE _inih_checkout) + if (NOT _inih_checkout STREQUAL "0") + message(FATAL_ERROR "inih: git checkout of pinned commit failed") endif() add_library(miniocpp_inih STATIC "${MINIO_CPP_INIH_SRC}/ini.c" diff --git a/docs/README.md b/docs/README.md index 915168b1..ea85be12 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,7 +6,7 @@ For a complete list of APIs and examples, please take a look at the [MinIO C++ C ## Build requirements * A working C++ development environment supporting C++17 standards. -* CMake 3.10 or higher. +* CMake 3.13.4 or higher. * [vcpkg](https://vcpkg.io/en/index.html). ## Install from vcpkg diff --git a/miniocpp-config.cmake.in b/miniocpp-config.cmake.in index 9ef0db42..d11cd518 100644 --- a/miniocpp-config.cmake.in +++ b/miniocpp-config.cmake.in @@ -6,5 +6,8 @@ include("${CMAKE_CURRENT_LIST_DIR}/miniocpp-targets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/miniocpp-deps.cmake") -# The link interface is not exported; re-apply it. -target_link_libraries(miniocpp::miniocpp INTERFACE ${MINIO_CPP_DEPS_LINK_LIBS}) +# The link interface is not exported; re-apply it. set_property is used +# instead of target_link_libraries so the imported target stays compatible +# with the CMake 3.13.4 minimum. +set_property(TARGET miniocpp::miniocpp APPEND PROPERTY + INTERFACE_LINK_LIBRARIES ${MINIO_CPP_DEPS_LINK_LIBS})