From 99e153c835c99a09e90de51fef0297b14bf96120 Mon Sep 17 00:00:00 2001 From: Socrates Date: Wed, 29 Apr 2026 21:16:13 +0800 Subject: [PATCH 1/9] Add configurable dependency source resolution --- README.md | 45 ++++++ cmake_modules/DefineOptions.cmake | 26 +++ cmake_modules/FindArrowAlt.cmake | 97 +++++++++++ cmake_modules/FindLZ4Alt.cmake | 63 ++++++++ cmake_modules/FindRE2Alt.cmake | 43 +++++ cmake_modules/FindSnappyAlt.cmake | 63 ++++++++ cmake_modules/FindZLIBAlt.cmake | 53 ++++++ cmake_modules/FindzstdAlt.cmake | 68 ++++++++ cmake_modules/ThirdpartyToolchain.cmake | 206 +++++++++++++++++++++++- 9 files changed, 658 insertions(+), 6 deletions(-) create mode 100644 cmake_modules/FindArrowAlt.cmake create mode 100644 cmake_modules/FindLZ4Alt.cmake create mode 100644 cmake_modules/FindRE2Alt.cmake create mode 100644 cmake_modules/FindSnappyAlt.cmake create mode 100644 cmake_modules/FindZLIBAlt.cmake create mode 100644 cmake_modules/FindzstdAlt.cmake diff --git a/README.md b/README.md index eff93320f..61cc54e55 100644 --- a/README.md +++ b/README.md @@ -140,6 +140,51 @@ $ cd build $ cmake .. $ make ``` + +### Third-party dependencies + +Paimon C++ can either build selected third-party dependencies from bundled +sources or use libraries that are already installed on the system. The default +mode is `AUTO`, which tries system packages first and falls back to bundled +sources when they are not found. + +``` +$ cmake -B build -DPAIMON_DEPENDENCY_SOURCE=AUTO +``` + +The supported dependency source values are: + +* `AUTO`: use a system package when available, otherwise build bundled sources. +* `BUNDLED`: always build bundled sources. +* `SYSTEM`: require system packages and fail if they are not found. +* `CONDA`: use `$CONDA_PREFIX` as the default package prefix. + +You can also override individual dependencies. The first supported dependency +set is Arrow/Parquet plus compression libraries. + +``` +$ cmake -B build \ + -DPAIMON_DEPENDENCY_SOURCE=AUTO \ + -DArrow_SOURCE=SYSTEM \ + -DArrow_ROOT=/opt/arrow \ + -Dzstd_SOURCE=BUNDLED +``` + +Use `PAIMON_PACKAGE_PREFIX` to provide one common prefix for dependencies whose +own `_ROOT` variable is not set. + +``` +$ cmake -B build \ + -DPAIMON_DEPENDENCY_SOURCE=SYSTEM \ + -DPAIMON_PACKAGE_PREFIX=/opt/paimon-deps +``` + +When `Arrow_SOURCE` is explicitly set to `SYSTEM`, `BUNDLED`, or `CONDA`, the +compression dependencies default to the same source unless individually +overridden. Mixing system and bundled copies of transitive dependencies can +cause ABI conflicts, so prefer keeping Arrow and its compression dependencies +from the same source unless you have a specific reason to override them. + ## Contributing Paimon-cpp is an active open-source project and we welcome people who want to contribute or share good ideas! diff --git a/cmake_modules/DefineOptions.cmake b/cmake_modules/DefineOptions.cmake index 9fa3629e2..a5e11ea9e 100644 --- a/cmake_modules/DefineOptions.cmake +++ b/cmake_modules/DefineOptions.cmake @@ -138,6 +138,32 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") option(PAIMON_BUILD_CONFIG_SUMMARY_JSON "Summarize build configuration in a JSON file" ON) + + #---------------------------------------------------------------------- + set_option_category("Dependencies") + + define_option_string(PAIMON_DEPENDENCY_SOURCE + "Default third-party dependency source" "AUTO" AUTO BUNDLED + SYSTEM CONDA) + + define_option_string(PAIMON_PACKAGE_PREFIX + "Default prefix used to find third-party packages" "") + + define_option(PAIMON_DEPENDENCY_USE_SHARED + "Prefer shared libraries for system third-party packages" OFF) + + define_option_string(Arrow_SOURCE "Dependency source for Apache Arrow" "" AUTO + BUNDLED SYSTEM CONDA) + define_option_string(zstd_SOURCE "Dependency source for zstd" "" AUTO BUNDLED + SYSTEM CONDA) + define_option_string(Snappy_SOURCE "Dependency source for Snappy" "" AUTO + BUNDLED SYSTEM CONDA) + define_option_string(LZ4_SOURCE "Dependency source for LZ4" "" AUTO BUNDLED + SYSTEM CONDA) + define_option_string(ZLIB_SOURCE "Dependency source for ZLIB" "" AUTO BUNDLED + SYSTEM CONDA) + define_option_string(RE2_SOURCE "Dependency source for RE2" "" AUTO BUNDLED + SYSTEM CONDA) endif() macro(validate_config) diff --git a/cmake_modules/FindArrowAlt.cmake b/cmake_modules/FindArrowAlt.cmake new file mode 100644 index 000000000..582bdd8d3 --- /dev/null +++ b/cmake_modules/FindArrowAlt.cmake @@ -0,0 +1,97 @@ +# Copyright 2024-present Alibaba Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); + +set(_PAIMON_ARROW_ROOTS ${Arrow_ROOT} ${ARROW_ROOT} ${PAIMON_PACKAGE_PREFIX}) +list(REMOVE_ITEM _PAIMON_ARROW_ROOTS "") +if(_PAIMON_ARROW_ROOTS) + set(_PAIMON_ARROW_FIND_ARGS HINTS ${_PAIMON_ARROW_ROOTS} NO_DEFAULT_PATH) +endif() + +find_package(Arrow CONFIG QUIET ${_PAIMON_ARROW_FIND_ARGS}) +find_package(Parquet CONFIG QUIET ${_PAIMON_ARROW_FIND_ARGS}) +find_package(ArrowDataset CONFIG QUIET ${_PAIMON_ARROW_FIND_ARGS}) +find_package(ArrowAcero CONFIG QUIET ${_PAIMON_ARROW_FIND_ARGS}) + +function(_paimon_select_first_target OUT_VAR) + foreach(_target IN LISTS ARGN) + if(TARGET ${_target}) + set(${OUT_VAR} + ${_target} + PARENT_SCOPE) + return() + endif() + endforeach() +endfunction() + +if(PAIMON_DEPENDENCY_USE_SHARED) + _paimon_select_first_target(_PAIMON_ARROW_TARGET Arrow::arrow_shared + Arrow::arrow) + _paimon_select_first_target(_PAIMON_PARQUET_TARGET Parquet::parquet_shared + Parquet::parquet) + _paimon_select_first_target(_PAIMON_ARROW_DATASET_TARGET + ArrowDataset::arrow_dataset_shared + Arrow::arrow_dataset_shared + ArrowDataset::arrow_dataset) + _paimon_select_first_target(_PAIMON_ARROW_ACERO_TARGET + ArrowAcero::arrow_acero_shared + Arrow::arrow_acero_shared ArrowAcero::arrow_acero) +else() + _paimon_select_first_target(_PAIMON_ARROW_TARGET Arrow::arrow_static + Arrow::arrow) + _paimon_select_first_target(_PAIMON_PARQUET_TARGET Parquet::parquet_static + Parquet::parquet) + _paimon_select_first_target(_PAIMON_ARROW_DATASET_TARGET + ArrowDataset::arrow_dataset_static + Arrow::arrow_dataset_static + ArrowDataset::arrow_dataset) + _paimon_select_first_target(_PAIMON_ARROW_ACERO_TARGET + ArrowAcero::arrow_acero_static + Arrow::arrow_acero_static ArrowAcero::arrow_acero) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + ArrowAlt + REQUIRED_VARS _PAIMON_ARROW_TARGET _PAIMON_PARQUET_TARGET + _PAIMON_ARROW_DATASET_TARGET _PAIMON_ARROW_ACERO_TARGET) + +if(ArrowAlt_FOUND) + get_target_property(ARROW_INCLUDE_DIR ${_PAIMON_ARROW_TARGET} + INTERFACE_INCLUDE_DIRECTORIES) + + if(NOT TARGET arrow) + add_library(arrow INTERFACE IMPORTED) + if(ARROW_INCLUDE_DIR) + set_target_properties(arrow PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${ARROW_INCLUDE_DIR}") + endif() + target_link_libraries(arrow INTERFACE ${_PAIMON_ARROW_TARGET}) + endif() + + if(NOT TARGET arrow_acero) + add_library(arrow_acero INTERFACE IMPORTED) + target_link_libraries(arrow_acero INTERFACE ${_PAIMON_ARROW_ACERO_TARGET} + arrow) + endif() + + if(NOT TARGET arrow_dataset) + add_library(arrow_dataset INTERFACE IMPORTED) + target_link_libraries(arrow_dataset + INTERFACE ${_PAIMON_ARROW_DATASET_TARGET} + arrow_acero) + endif() + + if(NOT TARGET parquet) + add_library(parquet INTERFACE IMPORTED) + target_link_libraries(parquet INTERFACE ${_PAIMON_PARQUET_TARGET} + arrow_dataset) + endif() +endif() + +unset(_PAIMON_ARROW_ACERO_TARGET) +unset(_PAIMON_ARROW_DATASET_TARGET) +unset(_PAIMON_ARROW_FIND_ARGS) +unset(_PAIMON_ARROW_ROOTS) +unset(_PAIMON_ARROW_TARGET) +unset(_PAIMON_PARQUET_TARGET) diff --git a/cmake_modules/FindLZ4Alt.cmake b/cmake_modules/FindLZ4Alt.cmake new file mode 100644 index 000000000..ebf0efc7a --- /dev/null +++ b/cmake_modules/FindLZ4Alt.cmake @@ -0,0 +1,63 @@ +# Copyright 2024-present Alibaba Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); + +set(_PAIMON_LZ4_ROOTS ${LZ4_ROOT} ${lz4_ROOT} ${PAIMON_PACKAGE_PREFIX}) +list(REMOVE_ITEM _PAIMON_LZ4_ROOTS "") +if(_PAIMON_LZ4_ROOTS) + set(_PAIMON_LZ4_FIND_ARGS HINTS ${_PAIMON_LZ4_ROOTS} NO_DEFAULT_PATH) +endif() + +find_package(lz4 CONFIG QUIET ${_PAIMON_LZ4_FIND_ARGS}) +find_package(LZ4 CONFIG QUIET ${_PAIMON_LZ4_FIND_ARGS}) + +set(_PAIMON_LZ4_TARGETS lz4::lz4 lz4::lz4_static LZ4::lz4 LZ4::LZ4) +foreach(_target IN LISTS _PAIMON_LZ4_TARGETS) + if(TARGET ${_target}) + set(_PAIMON_LZ4_TARGET ${_target}) + break() + endif() +endforeach() + +if(_PAIMON_LZ4_TARGET) + get_target_property(LZ4_INCLUDE_DIR ${_PAIMON_LZ4_TARGET} + INTERFACE_INCLUDE_DIRECTORIES) + if(NOT TARGET lz4) + add_library(lz4 INTERFACE IMPORTED) + if(LZ4_INCLUDE_DIR) + set_target_properties(lz4 PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${LZ4_INCLUDE_DIR}") + endif() + target_link_libraries(lz4 INTERFACE ${_PAIMON_LZ4_TARGET}) + endif() + set(LZ4_LIBRARIES ${_PAIMON_LZ4_TARGET}) + set(LZ4Alt_FOUND TRUE) +else() + find_package(PkgConfig QUIET) + if(PkgConfig_FOUND) + pkg_check_modules(PC_LZ4 QUIET liblz4) + endif() + + find_path(LZ4_INCLUDE_DIR NAMES lz4.h ${_PAIMON_LZ4_FIND_ARGS} + HINTS ${PC_LZ4_INCLUDE_DIRS} PATH_SUFFIXES include) + find_library(LZ4_LIBRARY NAMES lz4 liblz4 ${_PAIMON_LZ4_FIND_ARGS} + HINTS ${PC_LZ4_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(LZ4Alt REQUIRED_VARS LZ4_LIBRARY + LZ4_INCLUDE_DIR) + + if(LZ4Alt_FOUND AND NOT TARGET lz4) + add_library(lz4 UNKNOWN IMPORTED) + set_target_properties(lz4 + PROPERTIES IMPORTED_LOCATION "${LZ4_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${LZ4_INCLUDE_DIR}") + set(LZ4_LIBRARIES "${LZ4_LIBRARY}") + endif() +endif() + +unset(_PAIMON_LZ4_FIND_ARGS) +unset(_PAIMON_LZ4_ROOTS) +unset(_PAIMON_LZ4_TARGET) +unset(_PAIMON_LZ4_TARGETS) diff --git a/cmake_modules/FindRE2Alt.cmake b/cmake_modules/FindRE2Alt.cmake new file mode 100644 index 000000000..cafa397df --- /dev/null +++ b/cmake_modules/FindRE2Alt.cmake @@ -0,0 +1,43 @@ +# Copyright 2024-present Alibaba Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); + +set(_PAIMON_RE2_ROOTS ${RE2_ROOT} ${re2_ROOT} ${PAIMON_PACKAGE_PREFIX}) +list(REMOVE_ITEM _PAIMON_RE2_ROOTS "") +if(_PAIMON_RE2_ROOTS) + set(_PAIMON_RE2_FIND_ARGS HINTS ${_PAIMON_RE2_ROOTS} NO_DEFAULT_PATH) +endif() + +find_package(re2 CONFIG QUIET ${_PAIMON_RE2_FIND_ARGS}) + +if(TARGET re2::re2) + get_target_property(RE2_INCLUDE_DIR re2::re2 INTERFACE_INCLUDE_DIRECTORIES) + set(RE2_LIBRARIES re2::re2) + set(RE2Alt_FOUND TRUE) +else() + find_package(PkgConfig QUIET) + if(PkgConfig_FOUND) + pkg_check_modules(PC_RE2 QUIET re2) + endif() + + find_path(RE2_INCLUDE_DIR NAMES re2/re2.h ${_PAIMON_RE2_FIND_ARGS} + HINTS ${PC_RE2_INCLUDE_DIRS} PATH_SUFFIXES include) + find_library(RE2_LIBRARY NAMES re2 ${_PAIMON_RE2_FIND_ARGS} + HINTS ${PC_RE2_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(RE2Alt REQUIRED_VARS RE2_LIBRARY + RE2_INCLUDE_DIR) + + if(RE2Alt_FOUND) + add_library(re2::re2 UNKNOWN IMPORTED) + set_target_properties(re2::re2 + PROPERTIES IMPORTED_LOCATION "${RE2_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${RE2_INCLUDE_DIR}") + set(RE2_LIBRARIES "${RE2_LIBRARY}") + endif() +endif() + +unset(_PAIMON_RE2_FIND_ARGS) +unset(_PAIMON_RE2_ROOTS) diff --git a/cmake_modules/FindSnappyAlt.cmake b/cmake_modules/FindSnappyAlt.cmake new file mode 100644 index 000000000..8b2b461ca --- /dev/null +++ b/cmake_modules/FindSnappyAlt.cmake @@ -0,0 +1,63 @@ +# Copyright 2024-present Alibaba Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); + +set(_PAIMON_SNAPPY_ROOTS ${Snappy_ROOT} ${SNAPPY_ROOT} ${PAIMON_PACKAGE_PREFIX}) +list(REMOVE_ITEM _PAIMON_SNAPPY_ROOTS "") +if(_PAIMON_SNAPPY_ROOTS) + set(_PAIMON_SNAPPY_FIND_ARGS HINTS ${_PAIMON_SNAPPY_ROOTS} + NO_DEFAULT_PATH) +endif() + +find_package(Snappy CONFIG QUIET ${_PAIMON_SNAPPY_FIND_ARGS}) + +set(_PAIMON_SNAPPY_TARGETS Snappy::snappy snappy::snappy) +foreach(_target IN LISTS _PAIMON_SNAPPY_TARGETS) + if(TARGET ${_target}) + set(_PAIMON_SNAPPY_TARGET ${_target}) + break() + endif() +endforeach() + +if(_PAIMON_SNAPPY_TARGET) + get_target_property(SNAPPY_INCLUDE_DIR ${_PAIMON_SNAPPY_TARGET} + INTERFACE_INCLUDE_DIRECTORIES) + if(NOT TARGET snappy) + add_library(snappy INTERFACE IMPORTED) + if(SNAPPY_INCLUDE_DIR) + set_target_properties(snappy PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${SNAPPY_INCLUDE_DIR}") + endif() + target_link_libraries(snappy INTERFACE ${_PAIMON_SNAPPY_TARGET}) + endif() + set(SNAPPY_LIBRARIES ${_PAIMON_SNAPPY_TARGET}) + set(SnappyAlt_FOUND TRUE) +else() + find_package(PkgConfig QUIET) + if(PkgConfig_FOUND) + pkg_check_modules(PC_Snappy QUIET snappy) + endif() + + find_path(SNAPPY_INCLUDE_DIR NAMES snappy.h ${_PAIMON_SNAPPY_FIND_ARGS} + HINTS ${PC_Snappy_INCLUDE_DIRS} PATH_SUFFIXES include) + find_library(SNAPPY_LIBRARY NAMES snappy ${_PAIMON_SNAPPY_FIND_ARGS} + HINTS ${PC_Snappy_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(SnappyAlt REQUIRED_VARS SNAPPY_LIBRARY + SNAPPY_INCLUDE_DIR) + + if(SnappyAlt_FOUND AND NOT TARGET snappy) + add_library(snappy UNKNOWN IMPORTED) + set_target_properties(snappy + PROPERTIES IMPORTED_LOCATION "${SNAPPY_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${SNAPPY_INCLUDE_DIR}") + set(SNAPPY_LIBRARIES "${SNAPPY_LIBRARY}") + endif() +endif() + +unset(_PAIMON_SNAPPY_FIND_ARGS) +unset(_PAIMON_SNAPPY_ROOTS) +unset(_PAIMON_SNAPPY_TARGET) +unset(_PAIMON_SNAPPY_TARGETS) diff --git a/cmake_modules/FindZLIBAlt.cmake b/cmake_modules/FindZLIBAlt.cmake new file mode 100644 index 000000000..713bcf930 --- /dev/null +++ b/cmake_modules/FindZLIBAlt.cmake @@ -0,0 +1,53 @@ +# Copyright 2024-present Alibaba Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); + +set(_PAIMON_ZLIB_ROOTS ${ZLIB_ROOT} ${PAIMON_PACKAGE_PREFIX}) +list(REMOVE_ITEM _PAIMON_ZLIB_ROOTS "") +if(_PAIMON_ZLIB_ROOTS) + set(_PAIMON_ZLIB_FIND_ARGS HINTS ${_PAIMON_ZLIB_ROOTS} NO_DEFAULT_PATH) +endif() + +if(_PAIMON_ZLIB_ROOTS) + find_package(ZLIB CONFIG QUIET ${_PAIMON_ZLIB_FIND_ARGS}) +else() + find_package(ZLIB QUIET) +endif() + +if(TARGET ZLIB::ZLIB) + if(NOT TARGET zlib) + add_library(zlib INTERFACE IMPORTED) + get_target_property(ZLIB_INCLUDE_DIR ZLIB::ZLIB INTERFACE_INCLUDE_DIRECTORIES) + if(NOT ZLIB_INCLUDE_DIR) + set(ZLIB_INCLUDE_DIR ${ZLIB_INCLUDE_DIRS}) + endif() + if(ZLIB_INCLUDE_DIR) + set_target_properties(zlib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${ZLIB_INCLUDE_DIR}") + endif() + target_link_libraries(zlib INTERFACE ZLIB::ZLIB) + endif() + set(ZLIB_LIBRARIES ZLIB::ZLIB) + set(ZLIBAlt_FOUND TRUE) +else() + find_path(ZLIB_INCLUDE_DIR NAMES zlib.h ${_PAIMON_ZLIB_FIND_ARGS} + PATH_SUFFIXES include) + find_library(ZLIB_LIBRARY NAMES z zlib ${_PAIMON_ZLIB_FIND_ARGS} + PATH_SUFFIXES lib lib64) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(ZLIBAlt REQUIRED_VARS ZLIB_LIBRARY + ZLIB_INCLUDE_DIR) + + if(ZLIBAlt_FOUND AND NOT TARGET zlib) + add_library(zlib UNKNOWN IMPORTED) + set_target_properties(zlib + PROPERTIES IMPORTED_LOCATION "${ZLIB_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${ZLIB_INCLUDE_DIR}") + set(ZLIB_LIBRARIES "${ZLIB_LIBRARY}") + endif() +endif() + +unset(_PAIMON_ZLIB_FIND_ARGS) +unset(_PAIMON_ZLIB_ROOTS) diff --git a/cmake_modules/FindzstdAlt.cmake b/cmake_modules/FindzstdAlt.cmake new file mode 100644 index 000000000..f7d59e694 --- /dev/null +++ b/cmake_modules/FindzstdAlt.cmake @@ -0,0 +1,68 @@ +# Copyright 2024-present Alibaba Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); + +set(_PAIMON_ZSTD_ROOTS ${zstd_ROOT} ${ZSTD_ROOT} ${PAIMON_PACKAGE_PREFIX}) +list(REMOVE_ITEM _PAIMON_ZSTD_ROOTS "") +if(_PAIMON_ZSTD_ROOTS) + set(_PAIMON_ZSTD_FIND_ARGS HINTS ${_PAIMON_ZSTD_ROOTS} NO_DEFAULT_PATH) +endif() + +find_package(zstd CONFIG QUIET ${_PAIMON_ZSTD_FIND_ARGS}) + +set(_PAIMON_ZSTD_TARGETS) +if(PAIMON_DEPENDENCY_USE_SHARED) + list(APPEND _PAIMON_ZSTD_TARGETS zstd::libzstd_shared zstd::libzstd) +endif() +list(APPEND _PAIMON_ZSTD_TARGETS zstd::libzstd_static zstd::libzstd + zstd::zstd) + +foreach(_target IN LISTS _PAIMON_ZSTD_TARGETS) + if(TARGET ${_target}) + set(_PAIMON_ZSTD_TARGET ${_target}) + break() + endif() +endforeach() + +if(_PAIMON_ZSTD_TARGET) + get_target_property(ZSTD_INCLUDE_DIR ${_PAIMON_ZSTD_TARGET} + INTERFACE_INCLUDE_DIRECTORIES) + if(NOT TARGET zstd) + add_library(zstd INTERFACE IMPORTED) + if(ZSTD_INCLUDE_DIR) + set_target_properties(zstd PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${ZSTD_INCLUDE_DIR}") + endif() + target_link_libraries(zstd INTERFACE ${_PAIMON_ZSTD_TARGET}) + endif() + set(ZSTD_LIBRARIES ${_PAIMON_ZSTD_TARGET}) + set(zstdAlt_FOUND TRUE) +else() + find_package(PkgConfig QUIET) + if(PkgConfig_FOUND) + pkg_check_modules(PC_zstd QUIET libzstd) + endif() + + find_path(ZSTD_INCLUDE_DIR NAMES zstd.h ${_PAIMON_ZSTD_FIND_ARGS} + HINTS ${PC_zstd_INCLUDE_DIRS} PATH_SUFFIXES include) + find_library(ZSTD_LIBRARY NAMES zstd libzstd ${_PAIMON_ZSTD_FIND_ARGS} + HINTS ${PC_zstd_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(zstdAlt REQUIRED_VARS ZSTD_LIBRARY + ZSTD_INCLUDE_DIR) + + if(zstdAlt_FOUND AND NOT TARGET zstd) + add_library(zstd UNKNOWN IMPORTED) + set_target_properties(zstd + PROPERTIES IMPORTED_LOCATION "${ZSTD_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${ZSTD_INCLUDE_DIR}") + set(ZSTD_LIBRARIES "${ZSTD_LIBRARY}") + endif() +endif() + +unset(_PAIMON_ZSTD_FIND_ARGS) +unset(_PAIMON_ZSTD_ROOTS) +unset(_PAIMON_ZSTD_TARGET) +unset(_PAIMON_ZSTD_TARGETS) diff --git a/cmake_modules/ThirdpartyToolchain.cmake b/cmake_modules/ThirdpartyToolchain.cmake index 9e3c47d75..9535d0a5e 100644 --- a/cmake_modules/ThirdpartyToolchain.cmake +++ b/cmake_modules/ThirdpartyToolchain.cmake @@ -371,6 +371,198 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.30") list(APPEND EP_COMMON_CMAKE_ARGS -DCMAKE_POLICY_VERSION_MINIMUM=3.5) endif() +set(PAIMON_DEPENDENCY_SOURCE_VALUES AUTO BUNDLED SYSTEM CONDA) + +function(paimon_validate_dependency_source SOURCE_VALUE OPTION_NAME) + string(TOUPPER "${SOURCE_VALUE}" _source) + list(FIND PAIMON_DEPENDENCY_SOURCE_VALUES "${_source}" _source_index) + if(_source_index EQUAL -1) + message(FATAL_ERROR "${OPTION_NAME} got invalid value '${SOURCE_VALUE}'. " + "Allowed values: AUTO, BUNDLED, SYSTEM, CONDA.") + endif() +endfunction() + +function(paimon_get_dependency_source DEPENDENCY_NAME OUT_VAR) + set(_source "${${DEPENDENCY_NAME}_SOURCE}") + if("${_source}" STREQUAL "") + set(_source "${PAIMON_DEPENDENCY_SOURCE}") + endif() + string(TOUPPER "${_source}" _source) + paimon_validate_dependency_source("${_source}" "${DEPENDENCY_NAME}_SOURCE") + set(${OUT_VAR} + "${_source}" + PARENT_SCOPE) +endfunction() + +function(paimon_set_dependency_source_default DEPENDENCY_NAME SOURCE_VALUE REASON) + if("${${DEPENDENCY_NAME}_SOURCE}" STREQUAL "") + set(${DEPENDENCY_NAME}_SOURCE + "${SOURCE_VALUE}" + CACHE STRING "Dependency source for ${DEPENDENCY_NAME}" FORCE) + set_property(CACHE ${DEPENDENCY_NAME}_SOURCE + PROPERTY STRINGS ${PAIMON_DEPENDENCY_SOURCE_VALUES}) + message(STATUS + "Defaulting ${DEPENDENCY_NAME}_SOURCE to ${SOURCE_VALUE}: ${REASON}") + endif() +endfunction() + +function(paimon_apply_dependency_source_defaults) + paimon_get_dependency_source(Arrow _arrow_source) + if(_arrow_source STREQUAL "SYSTEM" OR _arrow_source STREQUAL "BUNDLED" + OR _arrow_source STREQUAL "CONDA") + foreach(_dependency zstd Snappy LZ4 ZLIB RE2) + paimon_set_dependency_source_default( + ${_dependency} ${_arrow_source} + "follow Arrow_SOURCE to avoid mixed transitive dependencies") + endforeach() + elseif(_arrow_source STREQUAL "AUTO") + paimon_configure_dependency_root(Arrow "${_arrow_source}" + _arrow_resolved_source) + find_package(ArrowAlt QUIET MODULE) + if(ArrowAlt_FOUND) + set(_arrow_dependency_default SYSTEM) + set(_arrow_dependency_reason + "system Arrow found during AUTO dependency precheck") + else() + set(_arrow_dependency_default BUNDLED) + set(_arrow_dependency_reason + "system Arrow not found during AUTO dependency precheck") + endif() + foreach(_dependency zstd Snappy LZ4 ZLIB RE2) + paimon_set_dependency_source_default( + ${_dependency} ${_arrow_dependency_default} + "${_arrow_dependency_reason}") + endforeach() + endif() +endfunction() + +function(paimon_configure_dependency_root DEPENDENCY_NAME SOURCE_VALUE OUT_SOURCE) + set(_root_var "${DEPENDENCY_NAME}_ROOT") + + if(SOURCE_VALUE STREQUAL "CONDA") + if("$ENV{CONDA_PREFIX}" STREQUAL "") + message(FATAL_ERROR "${DEPENDENCY_NAME}_SOURCE=CONDA requires CONDA_PREFIX") + endif() + if(NOT DEFINED ${_root_var} OR "${${_root_var}}" STREQUAL "") + set(${_root_var} + "$ENV{CONDA_PREFIX}" + CACHE PATH "Root directory for ${DEPENDENCY_NAME}" FORCE) + endif() + set(${OUT_SOURCE} + "SYSTEM" + PARENT_SCOPE) + return() + endif() + + if(NOT "${PAIMON_PACKAGE_PREFIX}" STREQUAL "" + AND (NOT DEFINED ${_root_var} OR "${${_root_var}}" STREQUAL "")) + set(${_root_var} + "${PAIMON_PACKAGE_PREFIX}" + CACHE PATH "Root directory for ${DEPENDENCY_NAME}" FORCE) + endif() + + set(${OUT_SOURCE} + "${SOURCE_VALUE}" + PARENT_SCOPE) +endfunction() + +macro(paimon_build_dependency DEPENDENCY_NAME) + if("${DEPENDENCY_NAME}" STREQUAL "Arrow") + build_arrow() + elseif("${DEPENDENCY_NAME}" STREQUAL "zstd") + build_zstd() + elseif("${DEPENDENCY_NAME}" STREQUAL "Snappy") + build_snappy() + elseif("${DEPENDENCY_NAME}" STREQUAL "LZ4") + build_lz4() + elseif("${DEPENDENCY_NAME}" STREQUAL "ZLIB") + build_zlib() + elseif("${DEPENDENCY_NAME}" STREQUAL "RE2") + build_re2() + else() + message(FATAL_ERROR "No bundled build rule for ${DEPENDENCY_NAME}") + endif() +endmacro() + +macro(resolve_dependency DEPENDENCY_NAME) + set(options) + set(one_value_args FIND_PACKAGE_NAME) + set(multi_value_args) + cmake_parse_arguments(ARG + "${options}" + "${one_value_args}" + "${multi_value_args}" + ${ARGN}) + + if(ARG_FIND_PACKAGE_NAME) + set(_paimon_find_package_name "${ARG_FIND_PACKAGE_NAME}") + else() + set(_paimon_find_package_name "${DEPENDENCY_NAME}") + endif() + set(_paimon_alt_package_name "${_paimon_find_package_name}Alt") + set(_paimon_found_var "${_paimon_alt_package_name}_FOUND") + + paimon_get_dependency_source(${DEPENDENCY_NAME} _paimon_requested_source) + paimon_configure_dependency_root(${DEPENDENCY_NAME} "${_paimon_requested_source}" + _paimon_resolved_source) + + if(_paimon_resolved_source STREQUAL "BUNDLED") + message(STATUS "Using bundled ${DEPENDENCY_NAME}") + paimon_build_dependency(${DEPENDENCY_NAME}) + set(PAIMON_${DEPENDENCY_NAME}_ACTUAL_SOURCE + "BUNDLED" + CACHE INTERNAL "Actual source for ${DEPENDENCY_NAME}") + elseif(_paimon_resolved_source STREQUAL "SYSTEM") + message(STATUS "Using system ${DEPENDENCY_NAME}") + find_package(${_paimon_alt_package_name} REQUIRED MODULE) + set(PAIMON_${DEPENDENCY_NAME}_ACTUAL_SOURCE + "${_paimon_requested_source}" + CACHE INTERNAL "Actual source for ${DEPENDENCY_NAME}") + elseif(_paimon_resolved_source STREQUAL "AUTO") + message(STATUS "Resolving ${DEPENDENCY_NAME} with AUTO source") + find_package(${_paimon_alt_package_name} QUIET MODULE) + if(${_paimon_found_var}) + message(STATUS "Using system ${DEPENDENCY_NAME}") + set(PAIMON_${DEPENDENCY_NAME}_ACTUAL_SOURCE + "SYSTEM" + CACHE INTERNAL "Actual source for ${DEPENDENCY_NAME}") + else() + message(STATUS "System ${DEPENDENCY_NAME} not found; using bundled") + paimon_build_dependency(${DEPENDENCY_NAME}) + set(PAIMON_${DEPENDENCY_NAME}_ACTUAL_SOURCE + "BUNDLED" + CACHE INTERNAL "Actual source for ${DEPENDENCY_NAME}") + endif() + else() + message(FATAL_ERROR "Unsupported source ${_paimon_resolved_source} " + "for ${DEPENDENCY_NAME}") + endif() + + unset(_paimon_find_package_name) + unset(_paimon_alt_package_name) + unset(_paimon_found_var) + unset(_paimon_requested_source) + unset(_paimon_resolved_source) +endmacro() + +function(paimon_warn_if_mixed_arrow_dependencies) + if(NOT DEFINED PAIMON_Arrow_ACTUAL_SOURCE) + return() + endif() + + foreach(_dependency zstd Snappy LZ4 ZLIB RE2) + if(DEFINED PAIMON_${_dependency}_ACTUAL_SOURCE + AND NOT "${PAIMON_${_dependency}_ACTUAL_SOURCE}" STREQUAL + "${PAIMON_Arrow_ACTUAL_SOURCE}") + message(WARNING + "Arrow resolved from ${PAIMON_Arrow_ACTUAL_SOURCE}, but " + "${_dependency} resolved from " + "${PAIMON_${_dependency}_ACTUAL_SOURCE}. Mixing SYSTEM, " + "CONDA, and BUNDLED dependencies can cause ABI conflicts.") + endif() + endforeach() +endfunction() + macro(build_lucene) message(STATUS "Building lucene from source") @@ -1440,12 +1632,14 @@ endmacro() build_fmt() build_rapidjson() -build_re2() -build_snappy() -build_zstd() -build_zlib() -build_lz4() -build_arrow() +paimon_apply_dependency_source_defaults() +resolve_dependency(RE2) +resolve_dependency(Snappy) +resolve_dependency(zstd) +resolve_dependency(ZLIB) +resolve_dependency(LZ4) +resolve_dependency(Arrow) +paimon_warn_if_mixed_arrow_dependencies() build_tbb() build_glog() From 6528ec6d9cdf32bf84ad9d129aee502d8ac3b414 Mon Sep 17 00:00:00 2001 From: Socrates Date: Thu, 30 Apr 2026 00:49:23 +0800 Subject: [PATCH 2/9] Add ORC and Protobuf dependency source resolution --- README.md | 7 +- cmake_modules/DefineOptions.cmake | 4 + cmake_modules/FindORCAlt.cmake | 69 +++++++++++ cmake_modules/FindProtobufAlt.cmake | 148 ++++++++++++++++++++++++ cmake_modules/ThirdpartyToolchain.cmake | 31 ++++- 5 files changed, 256 insertions(+), 3 deletions(-) create mode 100644 cmake_modules/FindORCAlt.cmake create mode 100644 cmake_modules/FindProtobufAlt.cmake diff --git a/README.md b/README.md index 61cc54e55..d012dd9b4 100644 --- a/README.md +++ b/README.md @@ -160,7 +160,7 @@ The supported dependency source values are: * `CONDA`: use `$CONDA_PREFIX` as the default package prefix. You can also override individual dependencies. The first supported dependency -set is Arrow/Parquet plus compression libraries. +set includes Arrow/Parquet, ORC, Protobuf, RE2, and compression libraries. ``` $ cmake -B build \ @@ -185,6 +185,11 @@ overridden. Mixing system and bundled copies of transitive dependencies can cause ABI conflicts, so prefer keeping Arrow and its compression dependencies from the same source unless you have a specific reason to override them. +When `ORC_SOURCE` is explicitly set, `Protobuf_SOURCE` defaults to the same +source unless individually overridden. In `AUTO` mode, Paimon prechecks for a +system ORC installation and defaults Protobuf to `SYSTEM` only when system ORC +is found; otherwise Protobuf stays bundled with bundled ORC. + ## Contributing Paimon-cpp is an active open-source project and we welcome people who want to contribute or share good ideas! diff --git a/cmake_modules/DefineOptions.cmake b/cmake_modules/DefineOptions.cmake index a5e11ea9e..c85d95e29 100644 --- a/cmake_modules/DefineOptions.cmake +++ b/cmake_modules/DefineOptions.cmake @@ -164,6 +164,10 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") SYSTEM CONDA) define_option_string(RE2_SOURCE "Dependency source for RE2" "" AUTO BUNDLED SYSTEM CONDA) + define_option_string(Protobuf_SOURCE "Dependency source for Protobuf" "" AUTO + BUNDLED SYSTEM CONDA) + define_option_string(ORC_SOURCE "Dependency source for Apache ORC" "" AUTO + BUNDLED SYSTEM CONDA) endif() macro(validate_config) diff --git a/cmake_modules/FindORCAlt.cmake b/cmake_modules/FindORCAlt.cmake new file mode 100644 index 000000000..85906fa0b --- /dev/null +++ b/cmake_modules/FindORCAlt.cmake @@ -0,0 +1,69 @@ +# Copyright 2024-present Alibaba Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); + +set(_PAIMON_ORC_ROOTS ${ORC_ROOT} ${orc_ROOT} ${PAIMON_PACKAGE_PREFIX}) +list(REMOVE_ITEM _PAIMON_ORC_ROOTS "") +if(_PAIMON_ORC_ROOTS) + set(_PAIMON_ORC_FIND_ARGS HINTS ${_PAIMON_ORC_ROOTS} NO_DEFAULT_PATH) +endif() + +find_package(orc CONFIG QUIET ${_PAIMON_ORC_FIND_ARGS}) +find_package(ORC CONFIG QUIET ${_PAIMON_ORC_FIND_ARGS}) + +set(_PAIMON_ORC_TARGETS orc::orc ORC::orc ORC::ORC orc) +foreach(_target IN LISTS _PAIMON_ORC_TARGETS) + if(TARGET ${_target}) + set(_PAIMON_ORC_TARGET ${_target}) + break() + endif() +endforeach() + +if(_PAIMON_ORC_TARGET) + if(NOT TARGET orc::orc) + add_library(orc::orc INTERFACE IMPORTED) + target_link_libraries(orc::orc INTERFACE ${_PAIMON_ORC_TARGET}) + endif() + + foreach(_dependency zstd snappy lz4 zlib libprotobuf) + if(TARGET ${_dependency}) + target_link_libraries(orc::orc INTERFACE ${_dependency}) + endif() + endforeach() + + get_target_property(ORC_INCLUDE_DIR orc::orc INTERFACE_INCLUDE_DIRECTORIES) + set(ORCAlt_FOUND TRUE) +else() + find_package(PkgConfig QUIET) + if(PkgConfig_FOUND) + pkg_check_modules(PC_ORC QUIET orc) + endif() + + find_path(ORC_INCLUDE_DIR NAMES orc/OrcFile.hh + ${_PAIMON_ORC_FIND_ARGS} HINTS ${PC_ORC_INCLUDE_DIRS} + PATH_SUFFIXES include) + find_library(ORC_LIBRARY NAMES orc ${_PAIMON_ORC_FIND_ARGS} + HINTS ${PC_ORC_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(ORCAlt REQUIRED_VARS ORC_LIBRARY + ORC_INCLUDE_DIR) + + if(ORCAlt_FOUND AND NOT TARGET orc::orc) + add_library(orc::orc UNKNOWN IMPORTED) + set_target_properties(orc::orc + PROPERTIES IMPORTED_LOCATION "${ORC_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${ORC_INCLUDE_DIR}") + foreach(_dependency zstd snappy lz4 zlib libprotobuf) + if(TARGET ${_dependency}) + target_link_libraries(orc::orc INTERFACE ${_dependency}) + endif() + endforeach() + endif() +endif() + +unset(_PAIMON_ORC_FIND_ARGS) +unset(_PAIMON_ORC_ROOTS) +unset(_PAIMON_ORC_TARGET) +unset(_PAIMON_ORC_TARGETS) diff --git a/cmake_modules/FindProtobufAlt.cmake b/cmake_modules/FindProtobufAlt.cmake new file mode 100644 index 000000000..55a915a03 --- /dev/null +++ b/cmake_modules/FindProtobufAlt.cmake @@ -0,0 +1,148 @@ +# Copyright 2024-present Alibaba Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); + +set(_PAIMON_PROTOBUF_ROOTS ${Protobuf_ROOT} ${PROTOBUF_ROOT} + ${PAIMON_PACKAGE_PREFIX}) +list(REMOVE_ITEM _PAIMON_PROTOBUF_ROOTS "") +if(_PAIMON_PROTOBUF_ROOTS) + set(_PAIMON_PROTOBUF_FIND_ARGS HINTS ${_PAIMON_PROTOBUF_ROOTS} + NO_DEFAULT_PATH) +endif() + +find_package(Protobuf CONFIG QUIET ${_PAIMON_PROTOBUF_FIND_ARGS}) + +set(_PAIMON_PROTOBUF_LIBRARY_TARGETS protobuf::libprotobuf + Protobuf::libprotobuf) +foreach(_target IN LISTS _PAIMON_PROTOBUF_LIBRARY_TARGETS) + if(TARGET ${_target}) + set(_PAIMON_PROTOBUF_LIBRARY_TARGET ${_target}) + break() + endif() +endforeach() + +set(_PAIMON_PROTOC_LIBRARY_TARGETS protobuf::libprotoc Protobuf::libprotoc) +foreach(_target IN LISTS _PAIMON_PROTOC_LIBRARY_TARGETS) + if(TARGET ${_target}) + set(_PAIMON_PROTOC_LIBRARY_TARGET ${_target}) + break() + endif() +endforeach() + +set(_PAIMON_PROTOC_TARGETS protobuf::protoc Protobuf::protoc) +foreach(_target IN LISTS _PAIMON_PROTOC_TARGETS) + if(TARGET ${_target}) + set(_PAIMON_PROTOC_TARGET ${_target}) + get_target_property(PROTOBUF_COMPILER ${_PAIMON_PROTOC_TARGET} + IMPORTED_LOCATION) + break() + endif() +endforeach() + +if(_PAIMON_PROTOBUF_LIBRARY_TARGET AND NOT PROTOBUF_COMPILER) + find_program(PROTOBUF_COMPILER NAMES protoc ${_PAIMON_PROTOBUF_FIND_ARGS} + PATH_SUFFIXES bin) +endif() + +if(_PAIMON_PROTOBUF_LIBRARY_TARGET) + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args( + ProtobufAlt REQUIRED_VARS _PAIMON_PROTOBUF_LIBRARY_TARGET + PROTOBUF_COMPILER) + if(ProtobufAlt_FOUND) + get_target_property(PROTOBUF_INCLUDE_DIR + ${_PAIMON_PROTOBUF_LIBRARY_TARGET} + INTERFACE_INCLUDE_DIRECTORIES) + + if(NOT TARGET libprotobuf) + add_library(libprotobuf INTERFACE IMPORTED) + if(PROTOBUF_INCLUDE_DIR) + set_target_properties( + libprotobuf PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${PROTOBUF_INCLUDE_DIR}") + endif() + target_link_libraries(libprotobuf + INTERFACE ${_PAIMON_PROTOBUF_LIBRARY_TARGET}) + endif() + + if(_PAIMON_PROTOC_LIBRARY_TARGET AND NOT TARGET libprotoc) + add_library(libprotoc INTERFACE IMPORTED) + if(PROTOBUF_INCLUDE_DIR) + set_target_properties( + libprotoc PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${PROTOBUF_INCLUDE_DIR}") + endif() + target_link_libraries(libprotoc + INTERFACE ${_PAIMON_PROTOC_LIBRARY_TARGET}) + endif() + + if(NOT TARGET protoc) + add_executable(protoc IMPORTED) + set_target_properties(protoc PROPERTIES IMPORTED_LOCATION + "${PROTOBUF_COMPILER}") + endif() + + set(PROTOBUF_LIBRARIES ${_PAIMON_PROTOBUF_LIBRARY_TARGET}) + endif() +else() + find_package(PkgConfig QUIET) + if(PkgConfig_FOUND) + pkg_check_modules(PC_Protobuf QUIET protobuf) + endif() + + find_path(PROTOBUF_INCLUDE_DIR NAMES google/protobuf/message.h + ${_PAIMON_PROTOBUF_FIND_ARGS} HINTS ${PC_Protobuf_INCLUDE_DIRS} + PATH_SUFFIXES include) + find_library(PROTOBUF_LIBRARY NAMES protobuf + ${_PAIMON_PROTOBUF_FIND_ARGS} + HINTS ${PC_Protobuf_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + find_library(PROTOC_LIBRARY NAMES protoc ${_PAIMON_PROTOBUF_FIND_ARGS} + HINTS ${PC_Protobuf_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + find_program(PROTOBUF_COMPILER NAMES protoc ${_PAIMON_PROTOBUF_FIND_ARGS} + PATH_SUFFIXES bin) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args( + ProtobufAlt REQUIRED_VARS PROTOBUF_LIBRARY PROTOBUF_INCLUDE_DIR + PROTOBUF_COMPILER) + + if(ProtobufAlt_FOUND) + if(NOT TARGET libprotobuf) + add_library(libprotobuf UNKNOWN IMPORTED) + set_target_properties( + libprotobuf + PROPERTIES IMPORTED_LOCATION "${PROTOBUF_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${PROTOBUF_INCLUDE_DIR}") + if(TARGET zlib) + target_link_libraries(libprotobuf INTERFACE zlib) + endif() + endif() + + if(PROTOC_LIBRARY AND NOT TARGET libprotoc) + add_library(libprotoc UNKNOWN IMPORTED) + set_target_properties( + libprotoc PROPERTIES IMPORTED_LOCATION "${PROTOC_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${PROTOBUF_INCLUDE_DIR}") + target_link_libraries(libprotoc INTERFACE libprotobuf) + endif() + + if(NOT TARGET protoc) + add_executable(protoc IMPORTED) + set_target_properties(protoc PROPERTIES IMPORTED_LOCATION + "${PROTOBUF_COMPILER}") + endif() + + set(PROTOBUF_LIBRARIES "${PROTOBUF_LIBRARY}") + endif() +endif() + +unset(_PAIMON_PROTOBUF_FIND_ARGS) +unset(_PAIMON_PROTOBUF_LIBRARY_TARGET) +unset(_PAIMON_PROTOBUF_LIBRARY_TARGETS) +unset(_PAIMON_PROTOBUF_ROOTS) +unset(_PAIMON_PROTOC_LIBRARY_TARGET) +unset(_PAIMON_PROTOC_LIBRARY_TARGETS) +unset(_PAIMON_PROTOC_TARGET) +unset(_PAIMON_PROTOC_TARGETS) diff --git a/cmake_modules/ThirdpartyToolchain.cmake b/cmake_modules/ThirdpartyToolchain.cmake index 9535d0a5e..92651d061 100644 --- a/cmake_modules/ThirdpartyToolchain.cmake +++ b/cmake_modules/ThirdpartyToolchain.cmake @@ -434,6 +434,29 @@ function(paimon_apply_dependency_source_defaults) "${_arrow_dependency_reason}") endforeach() endif() + + if(PAIMON_ENABLE_ORC) + paimon_get_dependency_source(ORC _orc_source) + if(_orc_source STREQUAL "SYSTEM" OR _orc_source STREQUAL "BUNDLED" + OR _orc_source STREQUAL "CONDA") + paimon_set_dependency_source_default( + Protobuf ${_orc_source} + "follow ORC_SOURCE to avoid mixed transitive dependencies") + elseif(_orc_source STREQUAL "AUTO") + paimon_configure_dependency_root(ORC "${_orc_source}" + _orc_resolved_source) + find_package(ORCAlt QUIET MODULE) + if(ORCAlt_FOUND) + paimon_set_dependency_source_default( + Protobuf SYSTEM + "system ORC found during AUTO dependency precheck") + else() + paimon_set_dependency_source_default( + Protobuf BUNDLED + "system ORC not found during AUTO dependency precheck") + endif() + endif() + endif() endfunction() function(paimon_configure_dependency_root DEPENDENCY_NAME SOURCE_VALUE OUT_SOURCE) @@ -479,6 +502,10 @@ macro(paimon_build_dependency DEPENDENCY_NAME) build_zlib() elseif("${DEPENDENCY_NAME}" STREQUAL "RE2") build_re2() + elseif("${DEPENDENCY_NAME}" STREQUAL "Protobuf") + build_protobuf() + elseif("${DEPENDENCY_NAME}" STREQUAL "ORC") + build_orc() else() message(FATAL_ERROR "No bundled build rule for ${DEPENDENCY_NAME}") endif() @@ -1647,8 +1674,8 @@ if(PAIMON_ENABLE_AVRO) build_avro() endif() if(PAIMON_ENABLE_ORC) - build_protobuf() - build_orc() + resolve_dependency(Protobuf) + resolve_dependency(ORC) endif() if(PAIMON_ENABLE_JINDO) build_jindosdk_c() From 592bc2aed69f367b6fa453caf4dca7d32a517a1c Mon Sep 17 00:00:00 2001 From: Socrates Date: Thu, 30 Apr 2026 01:01:30 +0800 Subject: [PATCH 3/9] Add phase 3 dependency source resolution --- CMakeLists.txt | 2 +- README.md | 5 +- cmake_modules/DefineOptions.cmake | 12 +++++ cmake_modules/FindAvroAlt.cmake | 39 +++++++++++++++ cmake_modules/FindGTestAlt.cmake | 65 +++++++++++++++++++++++++ cmake_modules/FindRapidJSONAlt.cmake | 48 ++++++++++++++++++ cmake_modules/FindTBBAlt.cmake | 60 +++++++++++++++++++++++ cmake_modules/FindfmtAlt.cmake | 61 +++++++++++++++++++++++ cmake_modules/FindglogAlt.cmake | 64 ++++++++++++++++++++++++ cmake_modules/ThirdpartyToolchain.cmake | 22 +++++++-- 10 files changed, 370 insertions(+), 8 deletions(-) create mode 100644 cmake_modules/FindAvroAlt.cmake create mode 100644 cmake_modules/FindGTestAlt.cmake create mode 100644 cmake_modules/FindRapidJSONAlt.cmake create mode 100644 cmake_modules/FindTBBAlt.cmake create mode 100644 cmake_modules/FindfmtAlt.cmake create mode 100644 cmake_modules/FindglogAlt.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f09d1596..9a203e9dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -365,7 +365,7 @@ if(PAIMON_BUILD_TESTS) endif() # Adding unit tests part of the "paimon" portion of the test suite add_custom_target(paimon-tests) - build_gtest() + resolve_dependency(GTest) add_custom_target(unittest ctest diff --git a/README.md b/README.md index d012dd9b4..13584f002 100644 --- a/README.md +++ b/README.md @@ -159,8 +159,9 @@ The supported dependency source values are: * `SYSTEM`: require system packages and fail if they are not found. * `CONDA`: use `$CONDA_PREFIX` as the default package prefix. -You can also override individual dependencies. The first supported dependency -set includes Arrow/Parquet, ORC, Protobuf, RE2, and compression libraries. +You can also override individual dependencies. The supported dependency set +includes Arrow/Parquet, ORC, Protobuf, Avro, RE2, fmt, RapidJSON, TBB, glog, +GoogleTest, and compression libraries. ``` $ cmake -B build \ diff --git a/cmake_modules/DefineOptions.cmake b/cmake_modules/DefineOptions.cmake index c85d95e29..685748d5e 100644 --- a/cmake_modules/DefineOptions.cmake +++ b/cmake_modules/DefineOptions.cmake @@ -168,6 +168,18 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") BUNDLED SYSTEM CONDA) define_option_string(ORC_SOURCE "Dependency source for Apache ORC" "" AUTO BUNDLED SYSTEM CONDA) + define_option_string(fmt_SOURCE "Dependency source for fmt" "" AUTO BUNDLED + SYSTEM CONDA) + define_option_string(RapidJSON_SOURCE "Dependency source for RapidJSON" "" + AUTO BUNDLED SYSTEM CONDA) + define_option_string(TBB_SOURCE "Dependency source for TBB" "" AUTO BUNDLED + SYSTEM CONDA) + define_option_string(glog_SOURCE "Dependency source for glog" "" AUTO BUNDLED + SYSTEM CONDA) + define_option_string(Avro_SOURCE "Dependency source for Avro C++" "" AUTO + BUNDLED SYSTEM CONDA) + define_option_string(GTest_SOURCE "Dependency source for GoogleTest" "" AUTO + BUNDLED SYSTEM CONDA) endif() macro(validate_config) diff --git a/cmake_modules/FindAvroAlt.cmake b/cmake_modules/FindAvroAlt.cmake new file mode 100644 index 000000000..011d3abff --- /dev/null +++ b/cmake_modules/FindAvroAlt.cmake @@ -0,0 +1,39 @@ +# Copyright 2024-present Alibaba Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); + +set(_PAIMON_AVRO_ROOTS ${Avro_ROOT} ${AVRO_ROOT} ${PAIMON_PACKAGE_PREFIX}) +list(REMOVE_ITEM _PAIMON_AVRO_ROOTS "") +if(_PAIMON_AVRO_ROOTS) + set(_PAIMON_AVRO_FIND_ARGS HINTS ${_PAIMON_AVRO_ROOTS} NO_DEFAULT_PATH) +endif() + +find_package(PkgConfig QUIET) +if(PkgConfig_FOUND) + pkg_check_modules(PC_Avro QUIET avro-cpp) +endif() + +find_path(AVRO_INCLUDE_DIR NAMES avro/Decoder.hh ${_PAIMON_AVRO_FIND_ARGS} + HINTS ${PC_Avro_INCLUDE_DIRS} PATH_SUFFIXES include) +find_library(AVRO_LIBRARY NAMES avrocpp_s avrocpp ${_PAIMON_AVRO_FIND_ARGS} + HINTS ${PC_Avro_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(AvroAlt REQUIRED_VARS AVRO_LIBRARY + AVRO_INCLUDE_DIR) + +if(AvroAlt_FOUND AND NOT TARGET avro) + add_library(avro UNKNOWN IMPORTED) + set_target_properties(avro PROPERTIES IMPORTED_LOCATION "${AVRO_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${AVRO_INCLUDE_DIR}") + foreach(_dependency zlib zstd snappy) + if(TARGET ${_dependency}) + target_link_libraries(avro INTERFACE ${_dependency}) + endif() + endforeach() + set(AVRO_LIBRARIES "${AVRO_LIBRARY}") +endif() + +unset(_PAIMON_AVRO_FIND_ARGS) +unset(_PAIMON_AVRO_ROOTS) diff --git a/cmake_modules/FindGTestAlt.cmake b/cmake_modules/FindGTestAlt.cmake new file mode 100644 index 000000000..b0ed5db10 --- /dev/null +++ b/cmake_modules/FindGTestAlt.cmake @@ -0,0 +1,65 @@ +# Copyright 2024-present Alibaba Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); + +set(_PAIMON_GTEST_ROOTS ${GTest_ROOT} ${GTEST_ROOT} ${PAIMON_PACKAGE_PREFIX}) +list(REMOVE_ITEM _PAIMON_GTEST_ROOTS "") +if(_PAIMON_GTEST_ROOTS) + set(_PAIMON_GTEST_FIND_ARGS HINTS ${_PAIMON_GTEST_ROOTS} NO_DEFAULT_PATH) +endif() + +find_package(GTest CONFIG QUIET ${_PAIMON_GTEST_FIND_ARGS}) + +if(NOT TARGET GTest::gtest OR NOT TARGET GTest::gtest_main + OR NOT TARGET GTest::gmock) + find_path(GTEST_INCLUDE_DIR NAMES gtest/gtest.h ${_PAIMON_GTEST_FIND_ARGS} + PATH_SUFFIXES include) + find_library(GTEST_LIBRARY NAMES gtest ${_PAIMON_GTEST_FIND_ARGS} + PATH_SUFFIXES lib lib64) + find_library(GTEST_MAIN_LIBRARY NAMES gtest_main ${_PAIMON_GTEST_FIND_ARGS} + PATH_SUFFIXES lib lib64) + find_library(GMOCK_LIBRARY NAMES gmock ${_PAIMON_GTEST_FIND_ARGS} + PATH_SUFFIXES lib lib64) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args( + GTestAlt REQUIRED_VARS GTEST_INCLUDE_DIR GTEST_LIBRARY + GTEST_MAIN_LIBRARY GMOCK_LIBRARY) + + if(GTestAlt_FOUND) + if(NOT TARGET GTest::gtest) + add_library(GTest::gtest UNKNOWN IMPORTED) + set_target_properties( + GTest::gtest + PROPERTIES IMPORTED_LOCATION "${GTEST_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIR}") + endif() + if(NOT TARGET GTest::gtest_main) + add_library(GTest::gtest_main UNKNOWN IMPORTED) + set_target_properties( + GTest::gtest_main + PROPERTIES IMPORTED_LOCATION "${GTEST_MAIN_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIR}") + endif() + if(NOT TARGET GTest::gmock) + add_library(GTest::gmock UNKNOWN IMPORTED) + set_target_properties( + GTest::gmock + PROPERTIES IMPORTED_LOCATION "${GMOCK_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIR}") + endif() + endif() +else() + get_target_property(GTEST_INCLUDE_DIR GTest::gtest + INTERFACE_INCLUDE_DIRECTORIES) + set(GTestAlt_FOUND TRUE) +endif() + +if(GTestAlt_FOUND) + find_package(Threads REQUIRED) + set(GTEST_LINK_TOOLCHAIN GTest::gtest_main GTest::gtest GTest::gmock + Threads::Threads) +endif() + +unset(_PAIMON_GTEST_FIND_ARGS) +unset(_PAIMON_GTEST_ROOTS) diff --git a/cmake_modules/FindRapidJSONAlt.cmake b/cmake_modules/FindRapidJSONAlt.cmake new file mode 100644 index 000000000..710d0006e --- /dev/null +++ b/cmake_modules/FindRapidJSONAlt.cmake @@ -0,0 +1,48 @@ +# Copyright 2024-present Alibaba Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); + +set(_PAIMON_RAPIDJSON_ROOTS ${RapidJSON_ROOT} ${RAPIDJSON_ROOT} + ${PAIMON_PACKAGE_PREFIX}) +list(REMOVE_ITEM _PAIMON_RAPIDJSON_ROOTS "") +if(_PAIMON_RAPIDJSON_ROOTS) + set(_PAIMON_RAPIDJSON_FIND_ARGS HINTS ${_PAIMON_RAPIDJSON_ROOTS} + NO_DEFAULT_PATH) +endif() + +find_package(RapidJSON CONFIG QUIET ${_PAIMON_RAPIDJSON_FIND_ARGS}) + +set(_PAIMON_RAPIDJSON_TARGETS RapidJSON RapidJSON::RapidJSON) +foreach(_target IN LISTS _PAIMON_RAPIDJSON_TARGETS) + if(TARGET ${_target}) + set(_PAIMON_RAPIDJSON_TARGET ${_target}) + break() + endif() +endforeach() + +if(_PAIMON_RAPIDJSON_TARGET) + if(NOT TARGET RapidJSON) + add_library(RapidJSON INTERFACE IMPORTED) + target_link_libraries(RapidJSON INTERFACE ${_PAIMON_RAPIDJSON_TARGET}) + endif() + get_target_property(RAPIDJSON_INCLUDE_DIR RapidJSON + INTERFACE_INCLUDE_DIRECTORIES) + set(RapidJSONAlt_FOUND TRUE) +else() + find_path(RAPIDJSON_INCLUDE_DIR NAMES rapidjson/rapidjson.h + ${_PAIMON_RAPIDJSON_FIND_ARGS} PATH_SUFFIXES include) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(RapidJSONAlt + REQUIRED_VARS RAPIDJSON_INCLUDE_DIR) + + if(RapidJSONAlt_FOUND AND NOT TARGET RapidJSON) + add_library(RapidJSON INTERFACE IMPORTED) + target_include_directories(RapidJSON INTERFACE "${RAPIDJSON_INCLUDE_DIR}") + endif() +endif() + +unset(_PAIMON_RAPIDJSON_FIND_ARGS) +unset(_PAIMON_RAPIDJSON_ROOTS) +unset(_PAIMON_RAPIDJSON_TARGET) +unset(_PAIMON_RAPIDJSON_TARGETS) diff --git a/cmake_modules/FindTBBAlt.cmake b/cmake_modules/FindTBBAlt.cmake new file mode 100644 index 000000000..240dc3c0b --- /dev/null +++ b/cmake_modules/FindTBBAlt.cmake @@ -0,0 +1,60 @@ +# Copyright 2024-present Alibaba Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); + +set(_PAIMON_TBB_ROOTS ${TBB_ROOT} ${tbb_ROOT} ${PAIMON_PACKAGE_PREFIX}) +list(REMOVE_ITEM _PAIMON_TBB_ROOTS "") +if(_PAIMON_TBB_ROOTS) + set(_PAIMON_TBB_FIND_ARGS HINTS ${_PAIMON_TBB_ROOTS} NO_DEFAULT_PATH) +endif() + +find_package(TBB CONFIG QUIET ${_PAIMON_TBB_FIND_ARGS}) + +set(_PAIMON_TBB_TARGETS TBB::tbb tbb) +foreach(_target IN LISTS _PAIMON_TBB_TARGETS) + if(TARGET ${_target}) + set(_PAIMON_TBB_TARGET ${_target}) + break() + endif() +endforeach() + +if(_PAIMON_TBB_TARGET) + if(NOT TARGET tbb) + add_library(tbb INTERFACE IMPORTED) + get_target_property(TBB_INCLUDE_DIR ${_PAIMON_TBB_TARGET} + INTERFACE_INCLUDE_DIRECTORIES) + if(TBB_INCLUDE_DIR) + set_target_properties(tbb PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${TBB_INCLUDE_DIR}") + endif() + target_link_libraries(tbb INTERFACE ${_PAIMON_TBB_TARGET}) + endif() + set(TBBAlt_FOUND TRUE) +else() + find_package(PkgConfig QUIET) + if(PkgConfig_FOUND) + pkg_check_modules(PC_TBB QUIET tbb) + endif() + + find_path(TBB_INCLUDE_DIR NAMES tbb/tbb.h oneapi/tbb/tbb.h + ${_PAIMON_TBB_FIND_ARGS} HINTS ${PC_TBB_INCLUDE_DIRS} + PATH_SUFFIXES include) + find_library(TBB_LIBRARY NAMES tbb ${_PAIMON_TBB_FIND_ARGS} + HINTS ${PC_TBB_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(TBBAlt REQUIRED_VARS TBB_LIBRARY + TBB_INCLUDE_DIR) + + if(TBBAlt_FOUND AND NOT TARGET tbb) + add_library(tbb UNKNOWN IMPORTED) + set_target_properties(tbb PROPERTIES IMPORTED_LOCATION "${TBB_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${TBB_INCLUDE_DIR}") + endif() +endif() + +unset(_PAIMON_TBB_FIND_ARGS) +unset(_PAIMON_TBB_ROOTS) +unset(_PAIMON_TBB_TARGET) +unset(_PAIMON_TBB_TARGETS) diff --git a/cmake_modules/FindfmtAlt.cmake b/cmake_modules/FindfmtAlt.cmake new file mode 100644 index 000000000..50319dcdf --- /dev/null +++ b/cmake_modules/FindfmtAlt.cmake @@ -0,0 +1,61 @@ +# Copyright 2024-present Alibaba Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); + +set(_PAIMON_FMT_ROOTS ${fmt_ROOT} ${FMT_ROOT} ${PAIMON_PACKAGE_PREFIX}) +list(REMOVE_ITEM _PAIMON_FMT_ROOTS "") +if(_PAIMON_FMT_ROOTS) + set(_PAIMON_FMT_FIND_ARGS HINTS ${_PAIMON_FMT_ROOTS} NO_DEFAULT_PATH) +endif() + +find_package(fmt CONFIG QUIET ${_PAIMON_FMT_FIND_ARGS}) + +set(_PAIMON_FMT_TARGETS fmt::fmt fmt::fmt-header-only) +foreach(_target IN LISTS _PAIMON_FMT_TARGETS) + if(TARGET ${_target}) + set(_PAIMON_FMT_TARGET ${_target}) + break() + endif() +endforeach() + +if(_PAIMON_FMT_TARGET) + if(NOT TARGET fmt) + add_library(fmt INTERFACE IMPORTED) + get_target_property(FMT_INCLUDE_DIR ${_PAIMON_FMT_TARGET} + INTERFACE_INCLUDE_DIRECTORIES) + if(FMT_INCLUDE_DIR) + set_target_properties(fmt PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${FMT_INCLUDE_DIR}") + endif() + target_link_libraries(fmt INTERFACE ${_PAIMON_FMT_TARGET}) + endif() + set(FMT_LIBRARIES ${_PAIMON_FMT_TARGET}) + set(fmtAlt_FOUND TRUE) +else() + find_package(PkgConfig QUIET) + if(PkgConfig_FOUND) + pkg_check_modules(PC_fmt QUIET fmt) + endif() + + find_path(FMT_INCLUDE_DIR NAMES fmt/core.h ${_PAIMON_FMT_FIND_ARGS} + HINTS ${PC_fmt_INCLUDE_DIRS} PATH_SUFFIXES include) + find_library(FMT_LIBRARY NAMES fmt ${_PAIMON_FMT_FIND_ARGS} + HINTS ${PC_fmt_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(fmtAlt REQUIRED_VARS FMT_INCLUDE_DIR + FMT_LIBRARY) + + if(fmtAlt_FOUND AND NOT TARGET fmt) + add_library(fmt UNKNOWN IMPORTED) + set_target_properties(fmt PROPERTIES IMPORTED_LOCATION "${FMT_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${FMT_INCLUDE_DIR}") + set(FMT_LIBRARIES "${FMT_LIBRARY}") + endif() +endif() + +unset(_PAIMON_FMT_FIND_ARGS) +unset(_PAIMON_FMT_ROOTS) +unset(_PAIMON_FMT_TARGET) +unset(_PAIMON_FMT_TARGETS) diff --git a/cmake_modules/FindglogAlt.cmake b/cmake_modules/FindglogAlt.cmake new file mode 100644 index 000000000..b5c4fe1d4 --- /dev/null +++ b/cmake_modules/FindglogAlt.cmake @@ -0,0 +1,64 @@ +# Copyright 2024-present Alibaba Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); + +set(_PAIMON_GLOG_ROOTS ${glog_ROOT} ${GLOG_ROOT} ${PAIMON_PACKAGE_PREFIX}) +list(REMOVE_ITEM _PAIMON_GLOG_ROOTS "") +if(_PAIMON_GLOG_ROOTS) + set(_PAIMON_GLOG_FIND_ARGS HINTS ${_PAIMON_GLOG_ROOTS} NO_DEFAULT_PATH) +endif() + +find_package(glog CONFIG QUIET ${_PAIMON_GLOG_FIND_ARGS}) + +set(_PAIMON_GLOG_TARGETS glog::glog glog) +foreach(_target IN LISTS _PAIMON_GLOG_TARGETS) + if(TARGET ${_target}) + set(_PAIMON_GLOG_TARGET ${_target}) + break() + endif() +endforeach() + +if(_PAIMON_GLOG_TARGET) + if(NOT TARGET glog) + add_library(glog INTERFACE IMPORTED) + get_target_property(GLOG_INCLUDE_DIR ${_PAIMON_GLOG_TARGET} + INTERFACE_INCLUDE_DIRECTORIES) + if(GLOG_INCLUDE_DIR) + set_target_properties(glog PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${GLOG_INCLUDE_DIR}") + endif() + target_link_libraries(glog INTERFACE ${_PAIMON_GLOG_TARGET}) + endif() + set(glogAlt_FOUND TRUE) +else() + find_package(PkgConfig QUIET) + if(PkgConfig_FOUND) + pkg_check_modules(PC_glog QUIET libglog) + endif() + + find_path(GLOG_INCLUDE_DIR NAMES glog/logging.h ${_PAIMON_GLOG_FIND_ARGS} + HINTS ${PC_glog_INCLUDE_DIRS} PATH_SUFFIXES include) + find_library(GLOG_LIBRARY NAMES glog ${_PAIMON_GLOG_FIND_ARGS} + HINTS ${PC_glog_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(glogAlt REQUIRED_VARS GLOG_LIBRARY + GLOG_INCLUDE_DIR) + + if(glogAlt_FOUND AND NOT TARGET glog) + add_library(glog UNKNOWN IMPORTED) + set_target_properties( + glog PROPERTIES IMPORTED_LOCATION "${GLOG_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${GLOG_INCLUDE_DIR}" + INTERFACE_COMPILE_DEFINITIONS "GLOG_USE_GLOG_EXPORT") + find_library(LIBUNWIND_LIBRARY NAMES unwind) + if(LIBUNWIND_LIBRARY) + target_link_libraries(glog INTERFACE ${LIBUNWIND_LIBRARY}) + endif() + endif() +endif() + +unset(_PAIMON_GLOG_FIND_ARGS) +unset(_PAIMON_GLOG_ROOTS) +unset(_PAIMON_GLOG_TARGET) +unset(_PAIMON_GLOG_TARGETS) diff --git a/cmake_modules/ThirdpartyToolchain.cmake b/cmake_modules/ThirdpartyToolchain.cmake index 92651d061..6b1302a9c 100644 --- a/cmake_modules/ThirdpartyToolchain.cmake +++ b/cmake_modules/ThirdpartyToolchain.cmake @@ -492,6 +492,10 @@ endfunction() macro(paimon_build_dependency DEPENDENCY_NAME) if("${DEPENDENCY_NAME}" STREQUAL "Arrow") build_arrow() + elseif("${DEPENDENCY_NAME}" STREQUAL "fmt") + build_fmt() + elseif("${DEPENDENCY_NAME}" STREQUAL "RapidJSON") + build_rapidjson() elseif("${DEPENDENCY_NAME}" STREQUAL "zstd") build_zstd() elseif("${DEPENDENCY_NAME}" STREQUAL "Snappy") @@ -506,6 +510,14 @@ macro(paimon_build_dependency DEPENDENCY_NAME) build_protobuf() elseif("${DEPENDENCY_NAME}" STREQUAL "ORC") build_orc() + elseif("${DEPENDENCY_NAME}" STREQUAL "TBB") + build_tbb() + elseif("${DEPENDENCY_NAME}" STREQUAL "glog") + build_glog() + elseif("${DEPENDENCY_NAME}" STREQUAL "Avro") + build_avro() + elseif("${DEPENDENCY_NAME}" STREQUAL "GTest") + build_gtest() else() message(FATAL_ERROR "No bundled build rule for ${DEPENDENCY_NAME}") endif() @@ -1657,8 +1669,8 @@ macro(build_glog) endif() endmacro() -build_fmt() -build_rapidjson() +resolve_dependency(fmt) +resolve_dependency(RapidJSON) paimon_apply_dependency_source_defaults() resolve_dependency(RE2) resolve_dependency(Snappy) @@ -1667,11 +1679,11 @@ resolve_dependency(ZLIB) resolve_dependency(LZ4) resolve_dependency(Arrow) paimon_warn_if_mixed_arrow_dependencies() -build_tbb() -build_glog() +resolve_dependency(TBB) +resolve_dependency(glog) if(PAIMON_ENABLE_AVRO) - build_avro() + resolve_dependency(Avro) endif() if(PAIMON_ENABLE_ORC) resolve_dependency(Protobuf) From 33bf610f3fdc187b8c4f810992077ef2116354b0 Mon Sep 17 00:00:00 2001 From: Socrates Date: Thu, 30 Apr 2026 01:39:22 +0800 Subject: [PATCH 4/9] cmake review --- docs/cmake_review.md | 294 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 docs/cmake_review.md diff --git a/docs/cmake_review.md b/docs/cmake_review.md new file mode 100644 index 000000000..f4479f5f7 --- /dev/null +++ b/docs/cmake_review.md @@ -0,0 +1,294 @@ +# paimon-cpp CMake 工程评审与依赖管理建议 + +> 评审范围:根 `CMakeLists.txt`、`cmake_modules/`(21 个文件)、`src/paimon/CMakeLists.txt` 及各子目录、`PaimonConfig.cmake.in`、`examples/`。 +> +> 评审标准:CMake 现代化(target-based)最佳工程实践、跨平台可移植性、依赖管理可维护性。 +> +> 关联 issue:[#103](https://github.com/alibaba/paimon-cpp/issues/103) Flexible Third-Party Dependency Management System。 + +--- + +## 总体判断 + +当前 CMake 工程**能 work,但积累了较多现代化债**,整体风格沿用了 Apache Arrow 2018 年前后的写法(directory-scope `add_definitions` / `include_directories`、`macro()` 而非 `function()`、手写 `*Config.cmake.in`)。 + +Issue #103 提出的"per-dependency `_SOURCE` + `resolve_dependency()` 框架"方向上没问题,但完全自己复刻 Arrow 的 `ThirdpartyToolchain.cmake`(Arrow 那份已 4000+ 行)是**长期高维护成本路径**。本文档同时给出工程层修复建议与依赖管理的替代方案。 + +--- + +## 一、CMake 工程层面的问题 + +### 🔴 严重:会产生功能性 bug + +#### 1. `PaimonConfig.cmake.in` 是手写伪导入目标,破坏可移植性 + +[PaimonConfig.cmake.in:15-145](../PaimonConfig.cmake.in#L15-L145) 对 ~20 个目标都用 `add_library(... IMPORTED)` + `IMPORTED_LOCATION "@CMAKE_INSTALL_PREFIX@/.../libpaimon.so"` 的硬编码方式。问题列表: + +- **写死 `.so`** —— 在 macOS 上根本找不到(应是 `.dylib`),整个 `find_package(Paimon)` 在 mac 上会"假性成功"但链接失败 +- **写死绝对路径** `@CMAKE_INSTALL_PREFIX@` —— 包不可重定位(用户把整个 install dir 移走就坏) +- **没有 `find_dependency(Arrow)` / `find_dependency(Protobuf)` / 等** —— 下游必须像 [examples/CMakeLists.txt:21-22](../examples/CMakeLists.txt#L21-L22) 那样自己手动 `find_package(Arrow)`,违反了 CMake package 自描述的契约 +- **没有命名空间** —— `paimon_shared` 这种裸名极易和下游冲突 +- [BuildUtils.cmake:135](../cmake_modules/BuildUtils.cmake#L135) 已经写了 `EXPORT ${LIB_NAME}_targets`,但**全局没有任何 `install(EXPORT ...)`** —— 这些 EXPORT 集合根本没被生成 + +**正确做法(标准 modern CMake 模式):** + +```cmake +# 在每个子目录里(或聚合到根) +install(EXPORT paimon_targets + FILE PaimonTargets.cmake + NAMESPACE Paimon:: + DESTINATION ${PAIMON_CMAKE_INSTALL_DIR}) + +# PaimonConfig.cmake.in 缩成 ~20 行 +include(CMakeFindDependencyMacro) +find_dependency(Arrow CONFIG) +find_dependency(Threads) +if(@PAIMON_ENABLE_ORC@) + find_dependency(Protobuf CONFIG) +endif() +include("${CMAKE_CURRENT_LIST_DIR}/PaimonTargets.cmake") +``` + +下游就只需 `find_package(Paimon CONFIG REQUIRED)` + `target_link_libraries(app PRIVATE Paimon::paimon)`。 + +#### 2. `option()` 与 `define_option()` 重复声明 + +[CMakeLists.txt:45-56](../CMakeLists.txt#L45-L56) 用 `option()` 定义了 `PAIMON_BUILD_STATIC` / `PAIMON_BUILD_SHARED` / `PAIMON_BUILD_TESTS` / 等;[DefineOptions.cmake:95-104](../cmake_modules/DefineOptions.cmake#L95-L104) 又用 `define_option()` 重复声明。这俩谁后赢取决于求值顺序(实际是 `include(DefineOptions)` 后赢,所以前面的 `option()` 块基本是无效代码),但容易让人改错地方。 + +#### 3. `string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE)` 自我覆盖 + +[SetupCxxFlags.cmake:44](../cmake_modules/SetupCxxFlags.cmake#L44) 直接把 `CMAKE_BUILD_TYPE` 自身改成大写。CMake 文档要求它保持原值(通常 mixed-case `Release`/`Debug`),多处 CMake 内置逻辑(如 `CMAKE_CXX_FLAGS_`)依赖标准大小写。这条改完之后还可能影响 multi-config 生成器。建议改名: + +```cmake +string(TOUPPER ${CMAKE_BUILD_TYPE} UPPERCASE_BUILD_TYPE) +``` + +#### 4. Linker flag 写死 GNU ld,破坏 macOS 构建 + +- [BuildUtils.cmake:127-132](../cmake_modules/BuildUtils.cmake#L127-L132) 用了 `-Wl,--exclude-libs,ALL`、`-Wl,-Bsymbolic`、`-Wl,-z,defs`、`-Wl,--gc-sections` +- [CMakeLists.txt:352-353](../CMakeLists.txt#L352-L353) 用了 `-Wl,--version-script=...` + +这些都是 GNU ld / LLD 专属。Apple ld 全部不识别,会直接 fail。需要 `if(NOT APPLE)` 或者用 generator expression 包起来: + +```cmake +target_link_options(${LIB_NAME}_shared PRIVATE + $<$>:-Wl,--exclude-libs,ALL> + $<$>:-Wl,-Bsymbolic> + $<$>:-Wl,-z,defs> + $<$>:-Wl,--gc-sections>) +``` + +#### 5. C/C++ flag 互相污染 + +[CMakeLists.txt:250-253](../CMakeLists.txt#L250-L253) 把 C++ flags 灌给 C 编译器再字符串删除 `-std=c++17`: + +```cmake +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CXX_COMMON_FLAGS} ${PAIMON_CXXFLAGS}") +string(REPLACE "-std=c++17" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) +``` + +CMake 自 3.3 起的官方做法是 `$` generator expression,按语言精准下发。一次 grep / replace 错了,C 文件就会用 C++ 标志编译,难定位。 + +--- + +### 🟡 中等:违反现代 CMake 最佳实践,技术债积累中 + +#### 6. 大量 directory-scope 命令(命令式 / 老式 CMake) + +通篇有: +- [CMakeLists.txt:59-91](../CMakeLists.txt#L59-L91) 的 `add_definitions(-DPAIMON_ENABLE_*)` +- [CMakeLists.txt:270-348](../CMakeLists.txt#L270-L348) 的 `include_directories(...)` +- [CMakeLists.txt:294,303](../CMakeLists.txt#L294) 的 `link_directories(...)` + +这些都是 directory-scope 副作用,导致: +- 第三方 ExternalProject 编译时也会"沾染"这些 flag +- include path 顺序难调试 +- 让 `target_*` 的 PRIVATE/PUBLIC/INTERFACE 语义失效 + +**Modern CMake 的统一替代:** + +```cmake +# 在 SetupCxxFlags 里 +add_library(paimon_compile_options INTERFACE) +target_compile_features(paimon_compile_options INTERFACE cxx_std_17) +target_compile_options(paimon_compile_options INTERFACE + $<$:${CXX_ONLY_FLAGS}> + ${CXX_COMMON_FLAGS}) +target_compile_definitions(paimon_compile_options INTERFACE + $<$:PAIMON_ENABLE_ORC> + $<$:PAIMON_ENABLE_AVRO> + _GLIBCXX_USE_CXX11_ABI=$,1,0>) +``` + +然后所有内部目标 `target_link_libraries(... PRIVATE paimon_compile_options)`。一处修改,全局生效,且不会泄漏到 ExternalProject。Apache Arrow 现在就这么用的(`arrow::flags::*` interface libs)。 + +#### 7. `EXTRA_INCLUDES ${ORC_INCLUDE_DIR}` / `${AVRO_INCLUDE_DIR}` 是冗余的 + +[orc/CMakeLists.txt:32-33](../src/paimon/format/orc/CMakeLists.txt#L32-L33)、[avro/CMakeLists.txt:32-33](../src/paimon/format/avro/CMakeLists.txt#L32-L33) 同时在 `EXTRA_INCLUDES` 里塞 `${ORC_INCLUDE_DIR}`,又把 `orc::orc` / `avro` 放进 `DEPENDENCIES`。后者已经通过 `INTERFACE_INCLUDE_DIRECTORIES` 自动传播 include 路径。前者是老 CMake 留下的"以防万一"——但当 Arrow/ORC 走 SYSTEM 路径时,`ARROW_INCLUDE_DIR` / `ORC_INCLUDE_DIR` 全局变量可能根本就不存在(因为是不同的 Find 模块设置的),会出现 silent miss。 + +#### 8. `build_*` 全是 `macro()` 而不是 `function()` + +[ThirdpartyToolchain.cmake](../cmake_modules/ThirdpartyToolchain.cmake) 里所有 `build_xxx` 都是 `macro`。macro 没有自己的作用域,所有 local 变量(`ARROW_PREFIX`、`ARROW_INCLUDE_DIR` 等)会泄漏到调用方,下游又靠这些变量名工作 —— 现在 [root CMakeLists.txt:344](../CMakeLists.txt#L344) 的 `include_directories(SYSTEM ${ARROW_INCLUDE_DIR})` 就依赖这个泄漏。一旦改 SYSTEM 模式,变量名约定就崩。 + +**修法**:改成 `function()`,所有产出走 `add_library(... IMPORTED)` + `set_target_properties(...)`,外部只通过 imported target 拿信息。 + +#### 9. 命名空间不一致 + +| 已命名空间化 | 未命名空间化 | +| --- | --- | +| `re2::re2` | `arrow` | +| `orc::orc` | `parquet` | +| `GTest::gtest` | `zstd` | +| `jindosdk::c_sdk` | `lz4` | +| `Threads::Threads` | `zlib` | +| | `snappy`, `fmt`, `glog`, `tbb`, `avro`, `libprotobuf`, `RapidJSON` | + +统一加上前缀(或保留每个上游官方命名空间,如 `Arrow::arrow_static`),可以彻底防止和下游 / 子项目重名。 + +#### 10. visibility 设置时机错误 + +[CMakeLists.txt:329](../CMakeLists.txt#L329) 的 `set(CMAKE_CXX_VISIBILITY_PRESET hidden)` 出现在 `add_subdirectory(third_party/...)` 之后。visibility 设置必须在创建 target 之前才会作用到那些 target。前面已经把 `roaring_bitmap`、`xxhash` 加进来了,对它们这条无效。 + +**修法**:挪到文件靠前位置(紧跟 `set(CMAKE_CXX_STANDARD 17)`),并补上: + +```cmake +set(CMAKE_CXX_VISIBILITY_PRESET hidden) +set(CMAKE_C_VISIBILITY_PRESET hidden) +set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) +``` + +#### 11. `cmake_minimum_required(VERSION 3.16)` 偏老 + +3.16 是 2019 年的版本。 + +| 版本 | 引入特性 | 对本项目意义 | +| --- | --- | --- | +| 3.19 | CMakePresets.json | 让 CI/dev 共享 build profile,替代 [build_and_package.sh](../build_and_package.sh) 的环境变量耦合 | +| 3.20 | `find_package(... CONFIG)` 行为更稳定 | 提升 SYSTEM 模式可靠性 | +| 3.24 | `FETCH_CONTENT_TRY_FIND_PACKAGE` | BUNDLED→SYSTEM 切换更优雅 | + +建议升到 **3.22**(Ubuntu 22.04 LTS 自带),兼顾新特性与发行版兼容性。 + +#### 12. 非可移植 shell 命令 + +- [build_jieba](../cmake_modules/ThirdpartyToolchain.cmake#L711) `INSTALL_COMMAND bash -c "cp -r ..."` +- [build_jindosdk_c](../cmake_modules/ThirdpartyToolchain.cmake#L1051) `bash -c "cp -r ..."` +- [build_boost](../cmake_modules/ThirdpartyToolchain.cmake#L831) `bash -c "mkdir -p ... && cp -r ..."` + +应该用 `${CMAKE_COMMAND} -E copy_directory ...` / `make_directory`,跨平台并能正确触发 build dependency。 + +--- + +### 🟢 轻微:值得整理但非紧急 + +13. [BuildUtils.cmake:257](../cmake_modules/BuildUtils.cmake#L257) 留了一行 `message(STATUS ${TEST_NAME})`,看起来是调试残留。 +14. `UPPERCASE_BUILD_TYPE` 在三个文件里被独立计算(root、SetupCxxFlags、ThirdpartyToolchain),DRY 一下。 +15. [CMakeLists.txt:289-290](../CMakeLists.txt#L289-L290) 有 `add_subdirectory(third_party/roaring_bitmap EXCLUDE_FROM_ALL)`,但 [CMakeLists.txt:333](../CMakeLists.txt#L333) 又 `include_directories("${CMAKE_SOURCE_DIR}/third_party/roaring_bitmap")` —— 后者冗余,因为 `roaring_bitmap` target 自身的 `INTERFACE_INCLUDE_DIRECTORIES` 已经传播了。 +16. [SetupCxxFlags.cmake:42](../cmake_modules/SetupCxxFlags.cmake#L42) 设了 `CMAKE_POSITION_INDEPENDENT_CODE ON`,但 [BuildUtils.cmake:56](../cmake_modules/BuildUtils.cmake#L56) 又对每个 objlib 单独设 `POSITION_INDEPENDENT_CODE 1`,冗余。 +17. [CMakeLists.txt:131-150](../CMakeLists.txt#L131-L150) 的 `COMMAND sed -i` 在 macOS 的 BSD sed 上语义不同(`-i` 强制要求一个空字符串参数)。 + +--- + +## 二、依赖管理建议 + +当前 issue #103 的实现思路是对的(仿 Arrow),但**仿 Arrow 是个坑**:Arrow 的 `ThirdpartyToolchain.cmake` 是十多年累积下来的工程债,行数已经 4000+,paimon-cpp 现在 1700 行只是开始。建议**重新评估**。 + +### 推荐方案 A:vcpkg / Conan 作主路径,BUNDLED 退化为兜底 + +**理由:** +- vcpkg/Conan 已经把 Arrow、ORC、protobuf、zstd、snappy、lz4、glog、fmt、TBB、GTest 全部打包好了,它们解决了你现在自己在 ExternalProject 里手写的所有 patch、flags、依赖关系 +- 用户接入只需 `cmake -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake` +- BUNDLED 模式可以保留作为 fallback(CI / 离线环境) + +**改动量小**: + +```json +// vcpkg.json +{ + "name": "paimon-cpp", + "version": "0.1.0", + "dependencies": [ + "arrow", "protobuf", "zstd", "snappy", "lz4", "zlib", + "re2", "fmt", "glog", "tbb", "rapidjson", + {"name": "gtest", "host": true} + ] +} +``` + +`PAIMON_DEPENDENCY_SOURCE=AUTO` 时直接走 `find_package(...)`,找不到再 fallback 到 BUNDLED。这条路 Apache Arrow 自己也支持。 + +### 推荐方案 B:`CPM.cmake` 替代 ExternalProject + +Arrow 的 ExternalProject 最大的问题是它在 build 阶段才执行,**编译产物不在主项目的 build graph 里**。 + +`CPM.cmake`(一个单文件 wrapper)让 `FetchContent` 拥有缓存和 version pin 的能力,所有依赖都直接成为主 build graph 的一部分 —— `compile_commands.json` 包含第三方源码,IDE 跳转/补全、增量编译都正常工作。 + +**代价**:第一次配置慢(要拉所有源码),但有 `CPM_SOURCE_CACHE` 之后就和 ExternalProject 一样了。 + +### 不论选哪条路,下面这些改动是确定该做的 + +#### C. 用 `arrow_bundled_dependencies` 而不是单独构建一遍 + +现在 [build_arrow](../cmake_modules/ThirdpartyToolchain.cmake#L1339) 里你既单独 `build_zstd` / `build_snappy` / 等,又把 ROOT 透传给 Arrow。如果 Arrow 没真正 reuse(取决于它内部 `*_SOURCE` 的解析),最后会有两份 zstd 静态符号。建议加一个 build-time check:解开 `libarrow.a`,确认 `ZSTD_compress` 来自哪儿(应该只来自一处)。 + +> ⚠ 这是 ABI 风险点之一,比 issue #103 评论里讨论的"SYSTEM Avro vs BUNDLED Arrow 的 zstd"更紧迫,因为它在**当前 BUNDLED-only 路径下就已经存在**。 + +#### D. CONDA 模式:用 `CMAKE_PREFIX_PATH=$CONDA_PREFIX` 一刀切 + +现在 [paimon_configure_dependency_root](../cmake_modules/ThirdpartyToolchain.cmake#L462) 对每个 dep 单独设 `_ROOT=$CONDA_PREFIX`。Conda 是单 prefix,直接: + +```cmake +list(PREPEND CMAKE_PREFIX_PATH $ENV{CONDA_PREFIX}) +``` + +一行解决,所有 `find_package` 自动生效。 + +#### E. SYSTEM 模式需要版本下限检查 + +现在 SYSTEM Arrow 不管什么版本都会被接受。`versions.txt` 里已经有 `PAIMON_ARROW_BUILD_VERSION=...`,把它作为 minimum: + +```cmake +find_package(Arrow CONFIG ${PAIMON_ARROW_BUILD_VERSION}) +# 找不到这个版本以上的就 fail / fallback +``` + +#### F. macOS 上 visibility 与 `--exclude-libs,ALL` 等价物 + +`--exclude-libs` 在 Apple ld 上没有等价物,唯一的 portable 方法是 **build BUNDLED deps 时编译期就 `-fvisibility=hidden -fvisibility-inlines-hidden`**。Apache Arrow 在 `EP_COMMON_TOOLCHAIN` 里就是这么干的。 + +--- + +## 三、优先级建议 + +按 ROI 排序: + +| 优先级 | 项 | 理由 | +| --- | --- | --- | +| **P0** | 修 `PaimonConfig.cmake.in`(用 `install(EXPORT)`) | 现在的设计在 macOS 上**根本不工作**;下游用户体验差 | +| **P0** | 把 `--exclude-libs,ALL` / `--version-script` 等 GNU 专属 flag 用 `if(NOT APPLE)` 包起来 | 同上 | +| **P0** | `string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE)` 改名 | 潜在 multi-config 兼容隐患 | +| **P1** | 把 `add_definitions` / `include_directories` / `link_directories` 收编到 `paimon_compile_options` interface lib | 一次性还掉大笔技术债,让以后 SYSTEM/BUNDLED 切换不再靠"全局变量泄漏" | +| **P1** | `build_*` macro → function | 迁移到 SYSTEM 时不会再悄无声息地 break | +| **P1** | 评估 vcpkg/CPM 方案,看是否能替代 issue #103 大部分手写代码 | 接下来要写的 Phase 3/4 会更轻松 | +| **P2** | 升级 cmake_minimum_required 到 3.22;引入 CMakePresets.json | 让 dev / CI 配置可复用 | +| **P2** | 命名空间统一 | 长期可维护性 | +| **P3** | 各种小清理(重复 set、debug print、shell 命令) | 代码卫生 | + +--- + +## 四、结论 + +当前 CMake 工程是"能 work,但欠了不少现代化债" —— 沿用了 Arrow 2018 年左右的写法。 + +Issue #103 的方向(SOURCE / ROOT / 软默认)本身没问题,但完全自己实现 `resolve_dependency` 框架可能不是最佳投入。建议: + +1. **先解决 P0/P1**,特别是 `PaimonConfig.cmake.in` 与 macOS 兼容性 —— 这两条直接决定了项目能不能被外部用户消费。 +2. **把 vcpkg 作为 SYSTEM 的标准入口**;issue #103 的 Phase 3/4 可以收敛到"维护一份 `vcpkg.json` + 几个 `FindXxxAlt`",而不是 1700 行的 ExternalProject 蓝图。 +3. **将 `paimon_compile_options` interface lib 落地**作为后续所有 target 的统一编译选项入口,是后续重构的"杠杆点"。 + +若需要可以分别针对: +- `PaimonConfig.cmake.in` 重写 +- `paimon_compile_options` 的具体实现 +- `vcpkg.json` 雏形 + +输出独立的改造草稿。 From a00e90105dd963ac8e605003182bf191e04a306c Mon Sep 17 00:00:00 2001 From: Socrates Date: Thu, 30 Apr 2026 01:56:39 +0800 Subject: [PATCH 5/9] Refine dependency source scope --- CMakeLists.txt | 2 + README.md | 15 ++-- cmake_modules/BuildUtils.cmake | 2 + cmake_modules/DefineOptions.cmake | 30 +++---- cmake_modules/ThirdpartyToolchain.cmake | 110 +++++++++++++++++++----- docs/cmake_review.md | 14 ++- src/paimon/format/avro/CMakeLists.txt | 8 +- src/paimon/format/orc/CMakeLists.txt | 8 +- 8 files changed, 126 insertions(+), 63 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a203e9dd..228b916c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -422,6 +422,8 @@ if(PAIMON_BUILD_TESTS) endif() endif() +paimon_print_dependency_resolution_summary() + include(CMakePackageConfigHelpers) write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/PaimonConfigVersion.cmake" diff --git a/README.md b/README.md index 13584f002..3d61c5cea 100644 --- a/README.md +++ b/README.md @@ -157,7 +157,6 @@ The supported dependency source values are: * `AUTO`: use a system package when available, otherwise build bundled sources. * `BUNDLED`: always build bundled sources. * `SYSTEM`: require system packages and fail if they are not found. -* `CONDA`: use `$CONDA_PREFIX` as the default package prefix. You can also override individual dependencies. The supported dependency set includes Arrow/Parquet, ORC, Protobuf, Avro, RE2, fmt, RapidJSON, TBB, glog, @@ -180,17 +179,21 @@ $ cmake -B build \ -DPAIMON_PACKAGE_PREFIX=/opt/paimon-deps ``` -When `Arrow_SOURCE` is explicitly set to `SYSTEM`, `BUNDLED`, or `CONDA`, the -compression dependencies default to the same source unless individually -overridden. Mixing system and bundled copies of transitive dependencies can -cause ABI conflicts, so prefer keeping Arrow and its compression dependencies -from the same source unless you have a specific reason to override them. +When `Arrow_SOURCE` is explicitly set to `SYSTEM` or `BUNDLED`, the compression +dependencies default to the same source unless individually overridden. Mixing +system and bundled copies of transitive dependencies can cause ABI conflicts, +so prefer keeping Arrow and its compression dependencies from the same source +unless you have a specific reason to override them. When `ORC_SOURCE` is explicitly set, `Protobuf_SOURCE` defaults to the same source unless individually overridden. In `AUTO` mode, Paimon prechecks for a system ORC installation and defaults Protobuf to `SYSTEM` only when system ORC is found; otherwise Protobuf stays bundled with bundled ORC. +CMake prints a dependency resolution summary during configuration showing the +requested source, actual source, compatibility target, and search root for each +resolved dependency. + ## Contributing Paimon-cpp is an active open-source project and we welcome people who want to contribute or share good ideas! diff --git a/cmake_modules/BuildUtils.cmake b/cmake_modules/BuildUtils.cmake index bed258230..6a05549fb 100644 --- a/cmake_modules/BuildUtils.cmake +++ b/cmake_modules/BuildUtils.cmake @@ -71,6 +71,8 @@ function(add_paimon_lib LIB_NAME) endforeach() if(_paimon_objlib_deps) add_dependencies(${LIB_NAME}_objlib ${_paimon_objlib_deps}) + target_link_libraries(${LIB_NAME}_objlib + PRIVATE ${_paimon_objlib_deps}) endif() unset(_paimon_objlib_deps) unset(_paimon_dep) diff --git a/cmake_modules/DefineOptions.cmake b/cmake_modules/DefineOptions.cmake index 685748d5e..d6eec6b21 100644 --- a/cmake_modules/DefineOptions.cmake +++ b/cmake_modules/DefineOptions.cmake @@ -144,7 +144,7 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") define_option_string(PAIMON_DEPENDENCY_SOURCE "Default third-party dependency source" "AUTO" AUTO BUNDLED - SYSTEM CONDA) + SYSTEM) define_option_string(PAIMON_PACKAGE_PREFIX "Default prefix used to find third-party packages" "") @@ -153,33 +153,33 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") "Prefer shared libraries for system third-party packages" OFF) define_option_string(Arrow_SOURCE "Dependency source for Apache Arrow" "" AUTO - BUNDLED SYSTEM CONDA) + BUNDLED SYSTEM) define_option_string(zstd_SOURCE "Dependency source for zstd" "" AUTO BUNDLED - SYSTEM CONDA) + SYSTEM) define_option_string(Snappy_SOURCE "Dependency source for Snappy" "" AUTO - BUNDLED SYSTEM CONDA) + BUNDLED SYSTEM) define_option_string(LZ4_SOURCE "Dependency source for LZ4" "" AUTO BUNDLED - SYSTEM CONDA) + SYSTEM) define_option_string(ZLIB_SOURCE "Dependency source for ZLIB" "" AUTO BUNDLED - SYSTEM CONDA) + SYSTEM) define_option_string(RE2_SOURCE "Dependency source for RE2" "" AUTO BUNDLED - SYSTEM CONDA) + SYSTEM) define_option_string(Protobuf_SOURCE "Dependency source for Protobuf" "" AUTO - BUNDLED SYSTEM CONDA) + BUNDLED SYSTEM) define_option_string(ORC_SOURCE "Dependency source for Apache ORC" "" AUTO - BUNDLED SYSTEM CONDA) + BUNDLED SYSTEM) define_option_string(fmt_SOURCE "Dependency source for fmt" "" AUTO BUNDLED - SYSTEM CONDA) + SYSTEM) define_option_string(RapidJSON_SOURCE "Dependency source for RapidJSON" "" - AUTO BUNDLED SYSTEM CONDA) + AUTO BUNDLED SYSTEM) define_option_string(TBB_SOURCE "Dependency source for TBB" "" AUTO BUNDLED - SYSTEM CONDA) + SYSTEM) define_option_string(glog_SOURCE "Dependency source for glog" "" AUTO BUNDLED - SYSTEM CONDA) + SYSTEM) define_option_string(Avro_SOURCE "Dependency source for Avro C++" "" AUTO - BUNDLED SYSTEM CONDA) + BUNDLED SYSTEM) define_option_string(GTest_SOURCE "Dependency source for GoogleTest" "" AUTO - BUNDLED SYSTEM CONDA) + BUNDLED SYSTEM) endif() macro(validate_config) diff --git a/cmake_modules/ThirdpartyToolchain.cmake b/cmake_modules/ThirdpartyToolchain.cmake index 6b1302a9c..a21abb165 100644 --- a/cmake_modules/ThirdpartyToolchain.cmake +++ b/cmake_modules/ThirdpartyToolchain.cmake @@ -371,14 +371,14 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.30") list(APPEND EP_COMMON_CMAKE_ARGS -DCMAKE_POLICY_VERSION_MINIMUM=3.5) endif() -set(PAIMON_DEPENDENCY_SOURCE_VALUES AUTO BUNDLED SYSTEM CONDA) +set(PAIMON_DEPENDENCY_SOURCE_VALUES AUTO BUNDLED SYSTEM) function(paimon_validate_dependency_source SOURCE_VALUE OPTION_NAME) string(TOUPPER "${SOURCE_VALUE}" _source) list(FIND PAIMON_DEPENDENCY_SOURCE_VALUES "${_source}" _source_index) if(_source_index EQUAL -1) message(FATAL_ERROR "${OPTION_NAME} got invalid value '${SOURCE_VALUE}'. " - "Allowed values: AUTO, BUNDLED, SYSTEM, CONDA.") + "Allowed values: AUTO, BUNDLED, SYSTEM.") endif() endfunction() @@ -408,8 +408,7 @@ endfunction() function(paimon_apply_dependency_source_defaults) paimon_get_dependency_source(Arrow _arrow_source) - if(_arrow_source STREQUAL "SYSTEM" OR _arrow_source STREQUAL "BUNDLED" - OR _arrow_source STREQUAL "CONDA") + if(_arrow_source STREQUAL "SYSTEM" OR _arrow_source STREQUAL "BUNDLED") foreach(_dependency zstd Snappy LZ4 ZLIB RE2) paimon_set_dependency_source_default( ${_dependency} ${_arrow_source} @@ -437,8 +436,7 @@ function(paimon_apply_dependency_source_defaults) if(PAIMON_ENABLE_ORC) paimon_get_dependency_source(ORC _orc_source) - if(_orc_source STREQUAL "SYSTEM" OR _orc_source STREQUAL "BUNDLED" - OR _orc_source STREQUAL "CONDA") + if(_orc_source STREQUAL "SYSTEM" OR _orc_source STREQUAL "BUNDLED") paimon_set_dependency_source_default( Protobuf ${_orc_source} "follow ORC_SOURCE to avoid mixed transitive dependencies") @@ -462,21 +460,6 @@ endfunction() function(paimon_configure_dependency_root DEPENDENCY_NAME SOURCE_VALUE OUT_SOURCE) set(_root_var "${DEPENDENCY_NAME}_ROOT") - if(SOURCE_VALUE STREQUAL "CONDA") - if("$ENV{CONDA_PREFIX}" STREQUAL "") - message(FATAL_ERROR "${DEPENDENCY_NAME}_SOURCE=CONDA requires CONDA_PREFIX") - endif() - if(NOT DEFINED ${_root_var} OR "${${_root_var}}" STREQUAL "") - set(${_root_var} - "$ENV{CONDA_PREFIX}" - CACHE PATH "Root directory for ${DEPENDENCY_NAME}" FORCE) - endif() - set(${OUT_SOURCE} - "SYSTEM" - PARENT_SCOPE) - return() - endif() - if(NOT "${PAIMON_PACKAGE_PREFIX}" STREQUAL "" AND (NOT DEFINED ${_root_var} OR "${${_root_var}}" STREQUAL "")) set(${_root_var} @@ -489,6 +472,73 @@ function(paimon_configure_dependency_root DEPENDENCY_NAME SOURCE_VALUE OUT_SOURC PARENT_SCOPE) endfunction() +function(paimon_get_dependency_root DEPENDENCY_NAME OUT_VAR) + set(_root_var "${DEPENDENCY_NAME}_ROOT") + if(DEFINED ${_root_var} AND NOT "${${_root_var}}" STREQUAL "") + set(${OUT_VAR} + "${${_root_var}}" + PARENT_SCOPE) + else() + set(${OUT_VAR} + "" + PARENT_SCOPE) + endif() +endfunction() + +function(paimon_get_dependency_compat_target DEPENDENCY_NAME OUT_VAR) + if("${DEPENDENCY_NAME}" STREQUAL "Arrow") + set(_target arrow) + elseif("${DEPENDENCY_NAME}" STREQUAL "ORC") + set(_target orc::orc) + elseif("${DEPENDENCY_NAME}" STREQUAL "Protobuf") + set(_target libprotobuf) + elseif("${DEPENDENCY_NAME}" STREQUAL "GTest") + set(_target GTest::gtest) + else() + set(_target "${DEPENDENCY_NAME}") + endif() + + set(${OUT_VAR} + "${_target}" + PARENT_SCOPE) +endfunction() + +function(paimon_record_dependency_resolution DEPENDENCY_NAME REQUESTED_SOURCE + ACTUAL_SOURCE TARGET_NAME) + get_property(_dependencies GLOBAL PROPERTY PAIMON_RESOLVED_DEPENDENCIES) + list(APPEND _dependencies "${DEPENDENCY_NAME}") + list(REMOVE_DUPLICATES _dependencies) + set_property(GLOBAL PROPERTY PAIMON_RESOLVED_DEPENDENCIES "${_dependencies}") + + paimon_get_dependency_root("${DEPENDENCY_NAME}" _root) + set_property(GLOBAL PROPERTY "PAIMON_${DEPENDENCY_NAME}_REQUESTED_SOURCE" + "${REQUESTED_SOURCE}") + set_property(GLOBAL PROPERTY "PAIMON_${DEPENDENCY_NAME}_ACTUAL_SOURCE" + "${ACTUAL_SOURCE}") + set_property(GLOBAL PROPERTY "PAIMON_${DEPENDENCY_NAME}_ROOT" "${_root}") + set_property(GLOBAL PROPERTY "PAIMON_${DEPENDENCY_NAME}_TARGET" + "${TARGET_NAME}") +endfunction() + +function(paimon_print_dependency_resolution_summary) + get_property(_dependencies GLOBAL PROPERTY PAIMON_RESOLVED_DEPENDENCIES) + if(NOT _dependencies) + return() + endif() + + message(STATUS "Dependency resolution summary:") + foreach(_dependency IN LISTS _dependencies) + get_property(_requested GLOBAL + PROPERTY "PAIMON_${_dependency}_REQUESTED_SOURCE") + get_property(_actual GLOBAL PROPERTY "PAIMON_${_dependency}_ACTUAL_SOURCE") + get_property(_root GLOBAL PROPERTY "PAIMON_${_dependency}_ROOT") + get_property(_target GLOBAL PROPERTY "PAIMON_${_dependency}_TARGET") + message(STATUS + " ${_dependency}: requested=${_requested}, actual=${_actual}, target=${_target}, root=${_root}" + ) + endforeach() +endfunction() + macro(paimon_build_dependency DEPENDENCY_NAME) if("${DEPENDENCY_NAME}" STREQUAL "Arrow") build_arrow() @@ -544,6 +594,7 @@ macro(resolve_dependency DEPENDENCY_NAME) paimon_get_dependency_source(${DEPENDENCY_NAME} _paimon_requested_source) paimon_configure_dependency_root(${DEPENDENCY_NAME} "${_paimon_requested_source}" _paimon_resolved_source) + paimon_get_dependency_compat_target(${DEPENDENCY_NAME} _paimon_target_name) if(_paimon_resolved_source STREQUAL "BUNDLED") message(STATUS "Using bundled ${DEPENDENCY_NAME}") @@ -551,12 +602,18 @@ macro(resolve_dependency DEPENDENCY_NAME) set(PAIMON_${DEPENDENCY_NAME}_ACTUAL_SOURCE "BUNDLED" CACHE INTERNAL "Actual source for ${DEPENDENCY_NAME}") + paimon_record_dependency_resolution( + ${DEPENDENCY_NAME} "${_paimon_requested_source}" "BUNDLED" + "${_paimon_target_name}") elseif(_paimon_resolved_source STREQUAL "SYSTEM") message(STATUS "Using system ${DEPENDENCY_NAME}") find_package(${_paimon_alt_package_name} REQUIRED MODULE) set(PAIMON_${DEPENDENCY_NAME}_ACTUAL_SOURCE "${_paimon_requested_source}" CACHE INTERNAL "Actual source for ${DEPENDENCY_NAME}") + paimon_record_dependency_resolution( + ${DEPENDENCY_NAME} "${_paimon_requested_source}" + "${_paimon_requested_source}" "${_paimon_target_name}") elseif(_paimon_resolved_source STREQUAL "AUTO") message(STATUS "Resolving ${DEPENDENCY_NAME} with AUTO source") find_package(${_paimon_alt_package_name} QUIET MODULE) @@ -565,12 +622,18 @@ macro(resolve_dependency DEPENDENCY_NAME) set(PAIMON_${DEPENDENCY_NAME}_ACTUAL_SOURCE "SYSTEM" CACHE INTERNAL "Actual source for ${DEPENDENCY_NAME}") + paimon_record_dependency_resolution( + ${DEPENDENCY_NAME} "${_paimon_requested_source}" "SYSTEM" + "${_paimon_target_name}") else() message(STATUS "System ${DEPENDENCY_NAME} not found; using bundled") paimon_build_dependency(${DEPENDENCY_NAME}) set(PAIMON_${DEPENDENCY_NAME}_ACTUAL_SOURCE "BUNDLED" CACHE INTERNAL "Actual source for ${DEPENDENCY_NAME}") + paimon_record_dependency_resolution( + ${DEPENDENCY_NAME} "${_paimon_requested_source}" "BUNDLED" + "${_paimon_target_name}") endif() else() message(FATAL_ERROR "Unsupported source ${_paimon_resolved_source} " @@ -582,6 +645,7 @@ macro(resolve_dependency DEPENDENCY_NAME) unset(_paimon_found_var) unset(_paimon_requested_source) unset(_paimon_resolved_source) + unset(_paimon_target_name) endmacro() function(paimon_warn_if_mixed_arrow_dependencies) @@ -596,8 +660,8 @@ function(paimon_warn_if_mixed_arrow_dependencies) message(WARNING "Arrow resolved from ${PAIMON_Arrow_ACTUAL_SOURCE}, but " "${_dependency} resolved from " - "${PAIMON_${_dependency}_ACTUAL_SOURCE}. Mixing SYSTEM, " - "CONDA, and BUNDLED dependencies can cause ABI conflicts.") + "${PAIMON_${_dependency}_ACTUAL_SOURCE}. Mixing SYSTEM " + "and BUNDLED dependencies can cause ABI conflicts.") endif() endforeach() endfunction() diff --git a/docs/cmake_review.md b/docs/cmake_review.md index f4479f5f7..51376cad2 100644 --- a/docs/cmake_review.md +++ b/docs/cmake_review.md @@ -193,13 +193,15 @@ set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) 当前 issue #103 的实现思路是对的(仿 Arrow),但**仿 Arrow 是个坑**:Arrow 的 `ThirdpartyToolchain.cmake` 是十多年累积下来的工程债,行数已经 4000+,paimon-cpp 现在 1700 行只是开始。建议**重新评估**。 -### 推荐方案 A:vcpkg / Conan 作主路径,BUNDLED 退化为兜底 +### 推荐方案 A:评估 vcpkg / Conan 作主路径,BUNDLED 退化为兜底 **理由:** - vcpkg/Conan 已经把 Arrow、ORC、protobuf、zstd、snappy、lz4、glog、fmt、TBB、GTest 全部打包好了,它们解决了你现在自己在 ExternalProject 里手写的所有 patch、flags、依赖关系 - 用户接入只需 `cmake -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake` - BUNDLED 模式可以保留作为 fallback(CI / 离线环境) +这条路线需要单独设计讨论,当前 issue #103 的首个 PR 不应直接承诺具体包管理器集成。 + **改动量小**: ```json @@ -233,15 +235,9 @@ Arrow 的 ExternalProject 最大的问题是它在 build 阶段才执行,**编 > ⚠ 这是 ABI 风险点之一,比 issue #103 评论里讨论的"SYSTEM Avro vs BUNDLED Arrow 的 zstd"更紧迫,因为它在**当前 BUNDLED-only 路径下就已经存在**。 -#### D. CONDA 模式:用 `CMAKE_PREFIX_PATH=$CONDA_PREFIX` 一刀切 - -现在 [paimon_configure_dependency_root](../cmake_modules/ThirdpartyToolchain.cmake#L462) 对每个 dep 单独设 `_ROOT=$CONDA_PREFIX`。Conda 是单 prefix,直接: - -```cmake -list(PREPEND CMAKE_PREFIX_PATH $ENV{CONDA_PREFIX}) -``` +#### D. 包管理器模式需要后续单独设计 -一行解决,所有 `find_package` 自动生效。 +Conda、vcpkg、Conan 等包管理器各自有不同的 toolchain / prefix 约定。它们不应混进第一版 `AUTO` / `SYSTEM` / `BUNDLED` 解析框架里仓促定型,后续可以围绕 `CMAKE_PREFIX_PATH`、`CMAKE_TOOLCHAIN_FILE`、manifest 文件和版本锁定策略单独设计。 #### E. SYSTEM 模式需要版本下限检查 diff --git a/src/paimon/format/avro/CMakeLists.txt b/src/paimon/format/avro/CMakeLists.txt index dba1bb046..a2f4eb79b 100644 --- a/src/paimon/format/avro/CMakeLists.txt +++ b/src/paimon/format/avro/CMakeLists.txt @@ -29,8 +29,6 @@ if(PAIMON_ENABLE_AVRO) add_paimon_lib(paimon_avro_file_format SOURCES ${PAIMON_AVRO_FILE_FORMAT} - EXTRA_INCLUDES - ${AVRO_INCLUDE_DIR} DEPENDENCIES paimon_shared avro @@ -58,8 +56,6 @@ if(PAIMON_ENABLE_AVRO) avro_schema_converter_test.cpp avro_stats_extractor_test.cpp avro_writer_builder_test.cpp - EXTRA_INCLUDES - ${AVRO_INCLUDE_DIR} STATIC_LINK_LIBS paimon_shared test_utils_static @@ -67,7 +63,9 @@ if(PAIMON_ENABLE_AVRO) paimon_local_file_system_static paimon_avro_file_format_static "-Wl,--no-whole-archive" - ${GTEST_LINK_TOOLCHAIN}) + ${GTEST_LINK_TOOLCHAIN} + EXTRA_LINK_LIBS + avro) endif() diff --git a/src/paimon/format/orc/CMakeLists.txt b/src/paimon/format/orc/CMakeLists.txt index 4543fe93a..2b8aa8c6f 100644 --- a/src/paimon/format/orc/CMakeLists.txt +++ b/src/paimon/format/orc/CMakeLists.txt @@ -29,8 +29,6 @@ if(PAIMON_ENABLE_ORC) add_paimon_lib(paimon_orc_file_format SOURCES ${PAIMON_ORC_FILE_FORMAT} - EXTRA_INCLUDES - ${ORC_INCLUDE_DIR} DEPENDENCIES paimon_shared orc::orc @@ -60,8 +58,6 @@ if(PAIMON_ENABLE_ORC) orc_stats_extractor_test.cpp orc_format_writer_test.cpp orc_file_batch_reader_test.cpp - EXTRA_INCLUDES - ${ORC_INCLUDE_DIR} STATIC_LINK_LIBS paimon_shared test_utils_static @@ -69,6 +65,8 @@ if(PAIMON_ENABLE_ORC) paimon_local_file_system_static paimon_orc_file_format_static "-Wl,--no-whole-archive" - ${GTEST_LINK_TOOLCHAIN}) + ${GTEST_LINK_TOOLCHAIN} + EXTRA_LINK_LIBS + orc::orc) endif() endif() From c147a68094ed27146f9dc205319e2a56061a54ed Mon Sep 17 00:00:00 2001 From: Socrates Date: Thu, 30 Apr 2026 10:41:40 +0800 Subject: [PATCH 6/9] Document dependency source scope --- README.md | 5 +++ cmake_modules/ThirdpartyToolchain.cmake | 12 ++++++ docs/cmake_review.md | 21 ++++++++--- docs/source/building.rst | 49 +++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3d61c5cea..612903b94 100644 --- a/README.md +++ b/README.md @@ -179,6 +179,11 @@ $ cmake -B build \ -DPAIMON_PACKAGE_PREFIX=/opt/paimon-deps ``` +Package-manager-specific modes are intentionally out of scope for this first +dependency source interface. They can still be used through standard CMake +mechanisms such as `CMAKE_PREFIX_PATH` or `CMAKE_TOOLCHAIN_FILE`, while Paimon +keeps the dependency source values limited to `AUTO`, `BUNDLED`, and `SYSTEM`. + When `Arrow_SOURCE` is explicitly set to `SYSTEM` or `BUNDLED`, the compression dependencies default to the same source unless individually overridden. Mixing system and bundled copies of transitive dependencies can cause ABI conflicts, diff --git a/cmake_modules/ThirdpartyToolchain.cmake b/cmake_modules/ThirdpartyToolchain.cmake index a21abb165..93425adbf 100644 --- a/cmake_modules/ThirdpartyToolchain.cmake +++ b/cmake_modules/ThirdpartyToolchain.cmake @@ -494,6 +494,18 @@ function(paimon_get_dependency_compat_target DEPENDENCY_NAME OUT_VAR) set(_target libprotobuf) elseif("${DEPENDENCY_NAME}" STREQUAL "GTest") set(_target GTest::gtest) + elseif("${DEPENDENCY_NAME}" STREQUAL "RE2") + set(_target re2::re2) + elseif("${DEPENDENCY_NAME}" STREQUAL "Snappy") + set(_target snappy) + elseif("${DEPENDENCY_NAME}" STREQUAL "LZ4") + set(_target lz4) + elseif("${DEPENDENCY_NAME}" STREQUAL "ZLIB") + set(_target zlib) + elseif("${DEPENDENCY_NAME}" STREQUAL "TBB") + set(_target tbb) + elseif("${DEPENDENCY_NAME}" STREQUAL "Avro") + set(_target avro) else() set(_target "${DEPENDENCY_NAME}") endif() diff --git a/docs/cmake_review.md b/docs/cmake_review.md index 51376cad2..5a7651475 100644 --- a/docs/cmake_review.md +++ b/docs/cmake_review.md @@ -14,6 +14,17 @@ Issue #103 提出的"per-dependency `_SOURCE` + `resolve_dependency()` 框架"方向上没问题,但完全自己复刻 Arrow 的 `ThirdpartyToolchain.cmake`(Arrow 那份已 4000+ 行)是**长期高维护成本路径**。本文档同时给出工程层修复建议与依赖管理的替代方案。 +当前 issue #103 的首个 PR 建议收敛为: + +- 支持 `AUTO` / `BUNDLED` / `SYSTEM` 三种依赖来源 +- 支持主要第三方依赖的 per-dependency `_SOURCE` +- 用 `FindXxxAlt.cmake` 兼容不同系统包暴露出来的 target 名称 +- 内部继续消费稳定的兼容 imported targets +- 输出依赖解析 summary,帮助 reviewer 和用户判断实际走了 system 还是 bundled +- 不在首个 PR 中承诺具体包管理器模式 + +后续 CMake 现代化可以继续拆成独立 PR:package export、target namespace、directory-scope 命令清理、平台 linker flag 修复、版本约束和包管理器集成等。 + --- ## 一、CMake 工程层面的问题 @@ -237,7 +248,7 @@ Arrow 的 ExternalProject 最大的问题是它在 build 阶段才执行,**编 #### D. 包管理器模式需要后续单独设计 -Conda、vcpkg、Conan 等包管理器各自有不同的 toolchain / prefix 约定。它们不应混进第一版 `AUTO` / `SYSTEM` / `BUNDLED` 解析框架里仓促定型,后续可以围绕 `CMAKE_PREFIX_PATH`、`CMAKE_TOOLCHAIN_FILE`、manifest 文件和版本锁定策略单独设计。 +包管理器各自有不同的 toolchain / prefix 约定。它们不应混进第一版 `AUTO` / `SYSTEM` / `BUNDLED` 解析框架里仓促定型,后续可以围绕 `CMAKE_PREFIX_PATH`、`CMAKE_TOOLCHAIN_FILE`、manifest 文件和版本锁定策略单独设计。 #### E. SYSTEM 模式需要版本下限检查 @@ -265,7 +276,7 @@ find_package(Arrow CONFIG ${PAIMON_ARROW_BUILD_VERSION}) | **P0** | `string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE)` 改名 | 潜在 multi-config 兼容隐患 | | **P1** | 把 `add_definitions` / `include_directories` / `link_directories` 收编到 `paimon_compile_options` interface lib | 一次性还掉大笔技术债,让以后 SYSTEM/BUNDLED 切换不再靠"全局变量泄漏" | | **P1** | `build_*` macro → function | 迁移到 SYSTEM 时不会再悄无声息地 break | -| **P1** | 评估 vcpkg/CPM 方案,看是否能替代 issue #103 大部分手写代码 | 接下来要写的 Phase 3/4 会更轻松 | +| **P1** | 评估 vcpkg/CPM 方案,看是否能替代部分手写依赖代码 | 需要作为包管理器策略单独讨论 | | **P2** | 升级 cmake_minimum_required 到 3.22;引入 CMakePresets.json | 让 dev / CI 配置可复用 | | **P2** | 命名空间统一 | 长期可维护性 | | **P3** | 各种小清理(重复 set、debug print、shell 命令) | 代码卫生 | @@ -276,15 +287,15 @@ find_package(Arrow CONFIG ${PAIMON_ARROW_BUILD_VERSION}) 当前 CMake 工程是"能 work,但欠了不少现代化债" —— 沿用了 Arrow 2018 年左右的写法。 -Issue #103 的方向(SOURCE / ROOT / 软默认)本身没问题,但完全自己实现 `resolve_dependency` 框架可能不是最佳投入。建议: +Issue #103 的方向(SOURCE / ROOT / 软默认)本身没问题,但完全自己实现并长期扩展 `resolve_dependency` 框架可能不是最佳投入。建议: 1. **先解决 P0/P1**,特别是 `PaimonConfig.cmake.in` 与 macOS 兼容性 —— 这两条直接决定了项目能不能被外部用户消费。 -2. **把 vcpkg 作为 SYSTEM 的标准入口**;issue #103 的 Phase 3/4 可以收敛到"维护一份 `vcpkg.json` + 几个 `FindXxxAlt`",而不是 1700 行的 ExternalProject 蓝图。 +2. **单独评估包管理器入口**;vcpkg、Conan、CPM 等方案需要结合 CI、离线构建、版本锁定和下游用户体验再决定,不应混进 issue #103 的首个 PR 仓促定型。 3. **将 `paimon_compile_options` interface lib 落地**作为后续所有 target 的统一编译选项入口,是后续重构的"杠杆点"。 若需要可以分别针对: - `PaimonConfig.cmake.in` 重写 - `paimon_compile_options` 的具体实现 -- `vcpkg.json` 雏形 +- 包管理器集成方案对比 输出独立的改造草稿。 diff --git a/docs/source/building.rst b/docs/source/building.rst index bf90003c7..51189d2b8 100644 --- a/docs/source/building.rst +++ b/docs/source/building.rst @@ -124,6 +124,55 @@ boolean flags to ``cmake``. * ``-DPAIMON_ENABLE_JINDO=ON``: Support for Alibaba Jindo filesystems * ``-DPAIMON_ENABLE_LUMINA=ON``: Support for Lumina vector index, lumina is only supported on gcc9 or higher. +Third-party dependency source +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Paimon C++ can either build selected third-party dependencies from bundled +sources or use libraries already installed on the system. The default mode is +``AUTO``, which tries system packages first and falls back to bundled sources +when they are not found. + +.. code-block:: shell + + cmake -B build -DPAIMON_DEPENDENCY_SOURCE=AUTO + +The supported dependency source values are: + +* ``AUTO``: use a system package when available, otherwise build bundled sources. +* ``BUNDLED``: always build bundled sources. +* ``SYSTEM``: require system packages and fail if they are not found. + +You can override individual dependencies with ``_SOURCE``. The +supported dependency set includes Arrow/Parquet, ORC, Protobuf, Avro, RE2, fmt, +RapidJSON, TBB, glog, GoogleTest, and compression libraries. + +.. code-block:: shell + + cmake -B build \ + -DPAIMON_DEPENDENCY_SOURCE=AUTO \ + -DArrow_SOURCE=SYSTEM \ + -DArrow_ROOT=/opt/arrow \ + -Dzstd_SOURCE=BUNDLED + +Use ``PAIMON_PACKAGE_PREFIX`` to provide one common prefix for dependencies +whose own ``_ROOT`` variable is not set. + +.. code-block:: shell + + cmake -B build \ + -DPAIMON_DEPENDENCY_SOURCE=SYSTEM \ + -DPAIMON_PACKAGE_PREFIX=/opt/paimon-deps + +Package-manager-specific modes are intentionally out of scope for this first +dependency source interface. They can still be used through standard CMake +mechanisms such as ``CMAKE_PREFIX_PATH`` or ``CMAKE_TOOLCHAIN_FILE``, while +Paimon keeps the dependency source values limited to ``AUTO``, ``BUNDLED``, and +``SYSTEM``. + +During configuration, CMake prints a dependency resolution summary showing the +requested source, actual source, compatibility target, and search root for each +resolved dependency. + Optional Targets ~~~~~~~~~~~~~~~~ From a3002a0dc0348ea7b4ddc742db17f99cb6eeeaff Mon Sep 17 00:00:00 2001 From: Socrates Date: Thu, 30 Apr 2026 10:48:39 +0800 Subject: [PATCH 7/9] Remove CMake review notes from dependency PR --- docs/cmake_review.md | 301 ------------------------------------------- 1 file changed, 301 deletions(-) delete mode 100644 docs/cmake_review.md diff --git a/docs/cmake_review.md b/docs/cmake_review.md deleted file mode 100644 index 5a7651475..000000000 --- a/docs/cmake_review.md +++ /dev/null @@ -1,301 +0,0 @@ -# paimon-cpp CMake 工程评审与依赖管理建议 - -> 评审范围:根 `CMakeLists.txt`、`cmake_modules/`(21 个文件)、`src/paimon/CMakeLists.txt` 及各子目录、`PaimonConfig.cmake.in`、`examples/`。 -> -> 评审标准:CMake 现代化(target-based)最佳工程实践、跨平台可移植性、依赖管理可维护性。 -> -> 关联 issue:[#103](https://github.com/alibaba/paimon-cpp/issues/103) Flexible Third-Party Dependency Management System。 - ---- - -## 总体判断 - -当前 CMake 工程**能 work,但积累了较多现代化债**,整体风格沿用了 Apache Arrow 2018 年前后的写法(directory-scope `add_definitions` / `include_directories`、`macro()` 而非 `function()`、手写 `*Config.cmake.in`)。 - -Issue #103 提出的"per-dependency `_SOURCE` + `resolve_dependency()` 框架"方向上没问题,但完全自己复刻 Arrow 的 `ThirdpartyToolchain.cmake`(Arrow 那份已 4000+ 行)是**长期高维护成本路径**。本文档同时给出工程层修复建议与依赖管理的替代方案。 - -当前 issue #103 的首个 PR 建议收敛为: - -- 支持 `AUTO` / `BUNDLED` / `SYSTEM` 三种依赖来源 -- 支持主要第三方依赖的 per-dependency `_SOURCE` -- 用 `FindXxxAlt.cmake` 兼容不同系统包暴露出来的 target 名称 -- 内部继续消费稳定的兼容 imported targets -- 输出依赖解析 summary,帮助 reviewer 和用户判断实际走了 system 还是 bundled -- 不在首个 PR 中承诺具体包管理器模式 - -后续 CMake 现代化可以继续拆成独立 PR:package export、target namespace、directory-scope 命令清理、平台 linker flag 修复、版本约束和包管理器集成等。 - ---- - -## 一、CMake 工程层面的问题 - -### 🔴 严重:会产生功能性 bug - -#### 1. `PaimonConfig.cmake.in` 是手写伪导入目标,破坏可移植性 - -[PaimonConfig.cmake.in:15-145](../PaimonConfig.cmake.in#L15-L145) 对 ~20 个目标都用 `add_library(... IMPORTED)` + `IMPORTED_LOCATION "@CMAKE_INSTALL_PREFIX@/.../libpaimon.so"` 的硬编码方式。问题列表: - -- **写死 `.so`** —— 在 macOS 上根本找不到(应是 `.dylib`),整个 `find_package(Paimon)` 在 mac 上会"假性成功"但链接失败 -- **写死绝对路径** `@CMAKE_INSTALL_PREFIX@` —— 包不可重定位(用户把整个 install dir 移走就坏) -- **没有 `find_dependency(Arrow)` / `find_dependency(Protobuf)` / 等** —— 下游必须像 [examples/CMakeLists.txt:21-22](../examples/CMakeLists.txt#L21-L22) 那样自己手动 `find_package(Arrow)`,违反了 CMake package 自描述的契约 -- **没有命名空间** —— `paimon_shared` 这种裸名极易和下游冲突 -- [BuildUtils.cmake:135](../cmake_modules/BuildUtils.cmake#L135) 已经写了 `EXPORT ${LIB_NAME}_targets`,但**全局没有任何 `install(EXPORT ...)`** —— 这些 EXPORT 集合根本没被生成 - -**正确做法(标准 modern CMake 模式):** - -```cmake -# 在每个子目录里(或聚合到根) -install(EXPORT paimon_targets - FILE PaimonTargets.cmake - NAMESPACE Paimon:: - DESTINATION ${PAIMON_CMAKE_INSTALL_DIR}) - -# PaimonConfig.cmake.in 缩成 ~20 行 -include(CMakeFindDependencyMacro) -find_dependency(Arrow CONFIG) -find_dependency(Threads) -if(@PAIMON_ENABLE_ORC@) - find_dependency(Protobuf CONFIG) -endif() -include("${CMAKE_CURRENT_LIST_DIR}/PaimonTargets.cmake") -``` - -下游就只需 `find_package(Paimon CONFIG REQUIRED)` + `target_link_libraries(app PRIVATE Paimon::paimon)`。 - -#### 2. `option()` 与 `define_option()` 重复声明 - -[CMakeLists.txt:45-56](../CMakeLists.txt#L45-L56) 用 `option()` 定义了 `PAIMON_BUILD_STATIC` / `PAIMON_BUILD_SHARED` / `PAIMON_BUILD_TESTS` / 等;[DefineOptions.cmake:95-104](../cmake_modules/DefineOptions.cmake#L95-L104) 又用 `define_option()` 重复声明。这俩谁后赢取决于求值顺序(实际是 `include(DefineOptions)` 后赢,所以前面的 `option()` 块基本是无效代码),但容易让人改错地方。 - -#### 3. `string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE)` 自我覆盖 - -[SetupCxxFlags.cmake:44](../cmake_modules/SetupCxxFlags.cmake#L44) 直接把 `CMAKE_BUILD_TYPE` 自身改成大写。CMake 文档要求它保持原值(通常 mixed-case `Release`/`Debug`),多处 CMake 内置逻辑(如 `CMAKE_CXX_FLAGS_`)依赖标准大小写。这条改完之后还可能影响 multi-config 生成器。建议改名: - -```cmake -string(TOUPPER ${CMAKE_BUILD_TYPE} UPPERCASE_BUILD_TYPE) -``` - -#### 4. Linker flag 写死 GNU ld,破坏 macOS 构建 - -- [BuildUtils.cmake:127-132](../cmake_modules/BuildUtils.cmake#L127-L132) 用了 `-Wl,--exclude-libs,ALL`、`-Wl,-Bsymbolic`、`-Wl,-z,defs`、`-Wl,--gc-sections` -- [CMakeLists.txt:352-353](../CMakeLists.txt#L352-L353) 用了 `-Wl,--version-script=...` - -这些都是 GNU ld / LLD 专属。Apple ld 全部不识别,会直接 fail。需要 `if(NOT APPLE)` 或者用 generator expression 包起来: - -```cmake -target_link_options(${LIB_NAME}_shared PRIVATE - $<$>:-Wl,--exclude-libs,ALL> - $<$>:-Wl,-Bsymbolic> - $<$>:-Wl,-z,defs> - $<$>:-Wl,--gc-sections>) -``` - -#### 5. C/C++ flag 互相污染 - -[CMakeLists.txt:250-253](../CMakeLists.txt#L250-L253) 把 C++ flags 灌给 C 编译器再字符串删除 `-std=c++17`: - -```cmake -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CXX_COMMON_FLAGS} ${PAIMON_CXXFLAGS}") -string(REPLACE "-std=c++17" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) -``` - -CMake 自 3.3 起的官方做法是 `$` generator expression,按语言精准下发。一次 grep / replace 错了,C 文件就会用 C++ 标志编译,难定位。 - ---- - -### 🟡 中等:违反现代 CMake 最佳实践,技术债积累中 - -#### 6. 大量 directory-scope 命令(命令式 / 老式 CMake) - -通篇有: -- [CMakeLists.txt:59-91](../CMakeLists.txt#L59-L91) 的 `add_definitions(-DPAIMON_ENABLE_*)` -- [CMakeLists.txt:270-348](../CMakeLists.txt#L270-L348) 的 `include_directories(...)` -- [CMakeLists.txt:294,303](../CMakeLists.txt#L294) 的 `link_directories(...)` - -这些都是 directory-scope 副作用,导致: -- 第三方 ExternalProject 编译时也会"沾染"这些 flag -- include path 顺序难调试 -- 让 `target_*` 的 PRIVATE/PUBLIC/INTERFACE 语义失效 - -**Modern CMake 的统一替代:** - -```cmake -# 在 SetupCxxFlags 里 -add_library(paimon_compile_options INTERFACE) -target_compile_features(paimon_compile_options INTERFACE cxx_std_17) -target_compile_options(paimon_compile_options INTERFACE - $<$:${CXX_ONLY_FLAGS}> - ${CXX_COMMON_FLAGS}) -target_compile_definitions(paimon_compile_options INTERFACE - $<$:PAIMON_ENABLE_ORC> - $<$:PAIMON_ENABLE_AVRO> - _GLIBCXX_USE_CXX11_ABI=$,1,0>) -``` - -然后所有内部目标 `target_link_libraries(... PRIVATE paimon_compile_options)`。一处修改,全局生效,且不会泄漏到 ExternalProject。Apache Arrow 现在就这么用的(`arrow::flags::*` interface libs)。 - -#### 7. `EXTRA_INCLUDES ${ORC_INCLUDE_DIR}` / `${AVRO_INCLUDE_DIR}` 是冗余的 - -[orc/CMakeLists.txt:32-33](../src/paimon/format/orc/CMakeLists.txt#L32-L33)、[avro/CMakeLists.txt:32-33](../src/paimon/format/avro/CMakeLists.txt#L32-L33) 同时在 `EXTRA_INCLUDES` 里塞 `${ORC_INCLUDE_DIR}`,又把 `orc::orc` / `avro` 放进 `DEPENDENCIES`。后者已经通过 `INTERFACE_INCLUDE_DIRECTORIES` 自动传播 include 路径。前者是老 CMake 留下的"以防万一"——但当 Arrow/ORC 走 SYSTEM 路径时,`ARROW_INCLUDE_DIR` / `ORC_INCLUDE_DIR` 全局变量可能根本就不存在(因为是不同的 Find 模块设置的),会出现 silent miss。 - -#### 8. `build_*` 全是 `macro()` 而不是 `function()` - -[ThirdpartyToolchain.cmake](../cmake_modules/ThirdpartyToolchain.cmake) 里所有 `build_xxx` 都是 `macro`。macro 没有自己的作用域,所有 local 变量(`ARROW_PREFIX`、`ARROW_INCLUDE_DIR` 等)会泄漏到调用方,下游又靠这些变量名工作 —— 现在 [root CMakeLists.txt:344](../CMakeLists.txt#L344) 的 `include_directories(SYSTEM ${ARROW_INCLUDE_DIR})` 就依赖这个泄漏。一旦改 SYSTEM 模式,变量名约定就崩。 - -**修法**:改成 `function()`,所有产出走 `add_library(... IMPORTED)` + `set_target_properties(...)`,外部只通过 imported target 拿信息。 - -#### 9. 命名空间不一致 - -| 已命名空间化 | 未命名空间化 | -| --- | --- | -| `re2::re2` | `arrow` | -| `orc::orc` | `parquet` | -| `GTest::gtest` | `zstd` | -| `jindosdk::c_sdk` | `lz4` | -| `Threads::Threads` | `zlib` | -| | `snappy`, `fmt`, `glog`, `tbb`, `avro`, `libprotobuf`, `RapidJSON` | - -统一加上前缀(或保留每个上游官方命名空间,如 `Arrow::arrow_static`),可以彻底防止和下游 / 子项目重名。 - -#### 10. visibility 设置时机错误 - -[CMakeLists.txt:329](../CMakeLists.txt#L329) 的 `set(CMAKE_CXX_VISIBILITY_PRESET hidden)` 出现在 `add_subdirectory(third_party/...)` 之后。visibility 设置必须在创建 target 之前才会作用到那些 target。前面已经把 `roaring_bitmap`、`xxhash` 加进来了,对它们这条无效。 - -**修法**:挪到文件靠前位置(紧跟 `set(CMAKE_CXX_STANDARD 17)`),并补上: - -```cmake -set(CMAKE_CXX_VISIBILITY_PRESET hidden) -set(CMAKE_C_VISIBILITY_PRESET hidden) -set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) -``` - -#### 11. `cmake_minimum_required(VERSION 3.16)` 偏老 - -3.16 是 2019 年的版本。 - -| 版本 | 引入特性 | 对本项目意义 | -| --- | --- | --- | -| 3.19 | CMakePresets.json | 让 CI/dev 共享 build profile,替代 [build_and_package.sh](../build_and_package.sh) 的环境变量耦合 | -| 3.20 | `find_package(... CONFIG)` 行为更稳定 | 提升 SYSTEM 模式可靠性 | -| 3.24 | `FETCH_CONTENT_TRY_FIND_PACKAGE` | BUNDLED→SYSTEM 切换更优雅 | - -建议升到 **3.22**(Ubuntu 22.04 LTS 自带),兼顾新特性与发行版兼容性。 - -#### 12. 非可移植 shell 命令 - -- [build_jieba](../cmake_modules/ThirdpartyToolchain.cmake#L711) `INSTALL_COMMAND bash -c "cp -r ..."` -- [build_jindosdk_c](../cmake_modules/ThirdpartyToolchain.cmake#L1051) `bash -c "cp -r ..."` -- [build_boost](../cmake_modules/ThirdpartyToolchain.cmake#L831) `bash -c "mkdir -p ... && cp -r ..."` - -应该用 `${CMAKE_COMMAND} -E copy_directory ...` / `make_directory`,跨平台并能正确触发 build dependency。 - ---- - -### 🟢 轻微:值得整理但非紧急 - -13. [BuildUtils.cmake:257](../cmake_modules/BuildUtils.cmake#L257) 留了一行 `message(STATUS ${TEST_NAME})`,看起来是调试残留。 -14. `UPPERCASE_BUILD_TYPE` 在三个文件里被独立计算(root、SetupCxxFlags、ThirdpartyToolchain),DRY 一下。 -15. [CMakeLists.txt:289-290](../CMakeLists.txt#L289-L290) 有 `add_subdirectory(third_party/roaring_bitmap EXCLUDE_FROM_ALL)`,但 [CMakeLists.txt:333](../CMakeLists.txt#L333) 又 `include_directories("${CMAKE_SOURCE_DIR}/third_party/roaring_bitmap")` —— 后者冗余,因为 `roaring_bitmap` target 自身的 `INTERFACE_INCLUDE_DIRECTORIES` 已经传播了。 -16. [SetupCxxFlags.cmake:42](../cmake_modules/SetupCxxFlags.cmake#L42) 设了 `CMAKE_POSITION_INDEPENDENT_CODE ON`,但 [BuildUtils.cmake:56](../cmake_modules/BuildUtils.cmake#L56) 又对每个 objlib 单独设 `POSITION_INDEPENDENT_CODE 1`,冗余。 -17. [CMakeLists.txt:131-150](../CMakeLists.txt#L131-L150) 的 `COMMAND sed -i` 在 macOS 的 BSD sed 上语义不同(`-i` 强制要求一个空字符串参数)。 - ---- - -## 二、依赖管理建议 - -当前 issue #103 的实现思路是对的(仿 Arrow),但**仿 Arrow 是个坑**:Arrow 的 `ThirdpartyToolchain.cmake` 是十多年累积下来的工程债,行数已经 4000+,paimon-cpp 现在 1700 行只是开始。建议**重新评估**。 - -### 推荐方案 A:评估 vcpkg / Conan 作主路径,BUNDLED 退化为兜底 - -**理由:** -- vcpkg/Conan 已经把 Arrow、ORC、protobuf、zstd、snappy、lz4、glog、fmt、TBB、GTest 全部打包好了,它们解决了你现在自己在 ExternalProject 里手写的所有 patch、flags、依赖关系 -- 用户接入只需 `cmake -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake` -- BUNDLED 模式可以保留作为 fallback(CI / 离线环境) - -这条路线需要单独设计讨论,当前 issue #103 的首个 PR 不应直接承诺具体包管理器集成。 - -**改动量小**: - -```json -// vcpkg.json -{ - "name": "paimon-cpp", - "version": "0.1.0", - "dependencies": [ - "arrow", "protobuf", "zstd", "snappy", "lz4", "zlib", - "re2", "fmt", "glog", "tbb", "rapidjson", - {"name": "gtest", "host": true} - ] -} -``` - -`PAIMON_DEPENDENCY_SOURCE=AUTO` 时直接走 `find_package(...)`,找不到再 fallback 到 BUNDLED。这条路 Apache Arrow 自己也支持。 - -### 推荐方案 B:`CPM.cmake` 替代 ExternalProject - -Arrow 的 ExternalProject 最大的问题是它在 build 阶段才执行,**编译产物不在主项目的 build graph 里**。 - -`CPM.cmake`(一个单文件 wrapper)让 `FetchContent` 拥有缓存和 version pin 的能力,所有依赖都直接成为主 build graph 的一部分 —— `compile_commands.json` 包含第三方源码,IDE 跳转/补全、增量编译都正常工作。 - -**代价**:第一次配置慢(要拉所有源码),但有 `CPM_SOURCE_CACHE` 之后就和 ExternalProject 一样了。 - -### 不论选哪条路,下面这些改动是确定该做的 - -#### C. 用 `arrow_bundled_dependencies` 而不是单独构建一遍 - -现在 [build_arrow](../cmake_modules/ThirdpartyToolchain.cmake#L1339) 里你既单独 `build_zstd` / `build_snappy` / 等,又把 ROOT 透传给 Arrow。如果 Arrow 没真正 reuse(取决于它内部 `*_SOURCE` 的解析),最后会有两份 zstd 静态符号。建议加一个 build-time check:解开 `libarrow.a`,确认 `ZSTD_compress` 来自哪儿(应该只来自一处)。 - -> ⚠ 这是 ABI 风险点之一,比 issue #103 评论里讨论的"SYSTEM Avro vs BUNDLED Arrow 的 zstd"更紧迫,因为它在**当前 BUNDLED-only 路径下就已经存在**。 - -#### D. 包管理器模式需要后续单独设计 - -包管理器各自有不同的 toolchain / prefix 约定。它们不应混进第一版 `AUTO` / `SYSTEM` / `BUNDLED` 解析框架里仓促定型,后续可以围绕 `CMAKE_PREFIX_PATH`、`CMAKE_TOOLCHAIN_FILE`、manifest 文件和版本锁定策略单独设计。 - -#### E. SYSTEM 模式需要版本下限检查 - -现在 SYSTEM Arrow 不管什么版本都会被接受。`versions.txt` 里已经有 `PAIMON_ARROW_BUILD_VERSION=...`,把它作为 minimum: - -```cmake -find_package(Arrow CONFIG ${PAIMON_ARROW_BUILD_VERSION}) -# 找不到这个版本以上的就 fail / fallback -``` - -#### F. macOS 上 visibility 与 `--exclude-libs,ALL` 等价物 - -`--exclude-libs` 在 Apple ld 上没有等价物,唯一的 portable 方法是 **build BUNDLED deps 时编译期就 `-fvisibility=hidden -fvisibility-inlines-hidden`**。Apache Arrow 在 `EP_COMMON_TOOLCHAIN` 里就是这么干的。 - ---- - -## 三、优先级建议 - -按 ROI 排序: - -| 优先级 | 项 | 理由 | -| --- | --- | --- | -| **P0** | 修 `PaimonConfig.cmake.in`(用 `install(EXPORT)`) | 现在的设计在 macOS 上**根本不工作**;下游用户体验差 | -| **P0** | 把 `--exclude-libs,ALL` / `--version-script` 等 GNU 专属 flag 用 `if(NOT APPLE)` 包起来 | 同上 | -| **P0** | `string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE)` 改名 | 潜在 multi-config 兼容隐患 | -| **P1** | 把 `add_definitions` / `include_directories` / `link_directories` 收编到 `paimon_compile_options` interface lib | 一次性还掉大笔技术债,让以后 SYSTEM/BUNDLED 切换不再靠"全局变量泄漏" | -| **P1** | `build_*` macro → function | 迁移到 SYSTEM 时不会再悄无声息地 break | -| **P1** | 评估 vcpkg/CPM 方案,看是否能替代部分手写依赖代码 | 需要作为包管理器策略单独讨论 | -| **P2** | 升级 cmake_minimum_required 到 3.22;引入 CMakePresets.json | 让 dev / CI 配置可复用 | -| **P2** | 命名空间统一 | 长期可维护性 | -| **P3** | 各种小清理(重复 set、debug print、shell 命令) | 代码卫生 | - ---- - -## 四、结论 - -当前 CMake 工程是"能 work,但欠了不少现代化债" —— 沿用了 Arrow 2018 年左右的写法。 - -Issue #103 的方向(SOURCE / ROOT / 软默认)本身没问题,但完全自己实现并长期扩展 `resolve_dependency` 框架可能不是最佳投入。建议: - -1. **先解决 P0/P1**,特别是 `PaimonConfig.cmake.in` 与 macOS 兼容性 —— 这两条直接决定了项目能不能被外部用户消费。 -2. **单独评估包管理器入口**;vcpkg、Conan、CPM 等方案需要结合 CI、离线构建、版本锁定和下游用户体验再决定,不应混进 issue #103 的首个 PR 仓促定型。 -3. **将 `paimon_compile_options` interface lib 落地**作为后续所有 target 的统一编译选项入口,是后续重构的"杠杆点"。 - -若需要可以分别针对: -- `PaimonConfig.cmake.in` 重写 -- `paimon_compile_options` 的具体实现 -- 包管理器集成方案对比 - -输出独立的改造草稿。 From b3b5ceadd6911dd147402f4a43e774f8c454cbfb Mon Sep 17 00:00:00 2001 From: Socrates Date: Thu, 30 Apr 2026 11:07:28 +0800 Subject: [PATCH 8/9] Fix dependency CMake formatting and jieba target --- cmake_modules/BuildUtils.cmake | 3 +- cmake_modules/DefineOptions.cmake | 103 +++++++++++++++++++----- cmake_modules/FindArrowAlt.cmake | 36 +++------ cmake_modules/FindAvroAlt.cmake | 21 ++--- cmake_modules/FindGTestAlt.cmake | 49 +++++------ cmake_modules/FindLZ4Alt.cmake | 17 ++-- cmake_modules/FindORCAlt.cmake | 28 +++++-- cmake_modules/FindProtobufAlt.cmake | 79 +++++++++--------- cmake_modules/FindRE2Alt.cmake | 15 ++-- cmake_modules/FindRapidJSONAlt.cmake | 17 ++-- cmake_modules/FindSnappyAlt.cmake | 19 +++-- cmake_modules/FindTBBAlt.cmake | 21 ++--- cmake_modules/FindZLIBAlt.cmake | 9 ++- cmake_modules/FindfmtAlt.cmake | 22 ++--- cmake_modules/FindglogAlt.cmake | 25 +++--- cmake_modules/FindzstdAlt.cmake | 20 +++-- cmake_modules/ThirdpartyToolchain.cmake | 76 +++++++++-------- 17 files changed, 328 insertions(+), 232 deletions(-) diff --git a/cmake_modules/BuildUtils.cmake b/cmake_modules/BuildUtils.cmake index 6a05549fb..861ae8fbe 100644 --- a/cmake_modules/BuildUtils.cmake +++ b/cmake_modules/BuildUtils.cmake @@ -71,8 +71,7 @@ function(add_paimon_lib LIB_NAME) endforeach() if(_paimon_objlib_deps) add_dependencies(${LIB_NAME}_objlib ${_paimon_objlib_deps}) - target_link_libraries(${LIB_NAME}_objlib - PRIVATE ${_paimon_objlib_deps}) + target_link_libraries(${LIB_NAME}_objlib PRIVATE ${_paimon_objlib_deps}) endif() unset(_paimon_objlib_deps) unset(_paimon_dep) diff --git a/cmake_modules/DefineOptions.cmake b/cmake_modules/DefineOptions.cmake index d6eec6b21..587b50a1f 100644 --- a/cmake_modules/DefineOptions.cmake +++ b/cmake_modules/DefineOptions.cmake @@ -143,7 +143,10 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") set_option_category("Dependencies") define_option_string(PAIMON_DEPENDENCY_SOURCE - "Default third-party dependency source" "AUTO" AUTO BUNDLED + "Default third-party dependency source" + "AUTO" + AUTO + BUNDLED SYSTEM) define_option_string(PAIMON_PACKAGE_PREFIX @@ -152,34 +155,90 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") define_option(PAIMON_DEPENDENCY_USE_SHARED "Prefer shared libraries for system third-party packages" OFF) - define_option_string(Arrow_SOURCE "Dependency source for Apache Arrow" "" AUTO - BUNDLED SYSTEM) - define_option_string(zstd_SOURCE "Dependency source for zstd" "" AUTO BUNDLED + define_option_string(Arrow_SOURCE + "Dependency source for Apache Arrow" + "" + AUTO + BUNDLED SYSTEM) - define_option_string(Snappy_SOURCE "Dependency source for Snappy" "" AUTO - BUNDLED SYSTEM) - define_option_string(LZ4_SOURCE "Dependency source for LZ4" "" AUTO BUNDLED + define_option_string(zstd_SOURCE + "Dependency source for zstd" + "" + AUTO + BUNDLED SYSTEM) - define_option_string(ZLIB_SOURCE "Dependency source for ZLIB" "" AUTO BUNDLED + define_option_string(Snappy_SOURCE + "Dependency source for Snappy" + "" + AUTO + BUNDLED SYSTEM) - define_option_string(RE2_SOURCE "Dependency source for RE2" "" AUTO BUNDLED + define_option_string(LZ4_SOURCE + "Dependency source for LZ4" + "" + AUTO + BUNDLED SYSTEM) - define_option_string(Protobuf_SOURCE "Dependency source for Protobuf" "" AUTO - BUNDLED SYSTEM) - define_option_string(ORC_SOURCE "Dependency source for Apache ORC" "" AUTO - BUNDLED SYSTEM) - define_option_string(fmt_SOURCE "Dependency source for fmt" "" AUTO BUNDLED + define_option_string(ZLIB_SOURCE + "Dependency source for ZLIB" + "" + AUTO + BUNDLED SYSTEM) - define_option_string(RapidJSON_SOURCE "Dependency source for RapidJSON" "" - AUTO BUNDLED SYSTEM) - define_option_string(TBB_SOURCE "Dependency source for TBB" "" AUTO BUNDLED + define_option_string(RE2_SOURCE + "Dependency source for RE2" + "" + AUTO + BUNDLED SYSTEM) - define_option_string(glog_SOURCE "Dependency source for glog" "" AUTO BUNDLED + define_option_string(Protobuf_SOURCE + "Dependency source for Protobuf" + "" + AUTO + BUNDLED + SYSTEM) + define_option_string(ORC_SOURCE + "Dependency source for Apache ORC" + "" + AUTO + BUNDLED + SYSTEM) + define_option_string(fmt_SOURCE + "Dependency source for fmt" + "" + AUTO + BUNDLED + SYSTEM) + define_option_string(RapidJSON_SOURCE + "Dependency source for RapidJSON" + "" + AUTO + BUNDLED + SYSTEM) + define_option_string(TBB_SOURCE + "Dependency source for TBB" + "" + AUTO + BUNDLED + SYSTEM) + define_option_string(glog_SOURCE + "Dependency source for glog" + "" + AUTO + BUNDLED + SYSTEM) + define_option_string(Avro_SOURCE + "Dependency source for Avro C++" + "" + AUTO + BUNDLED + SYSTEM) + define_option_string(GTest_SOURCE + "Dependency source for GoogleTest" + "" + AUTO + BUNDLED SYSTEM) - define_option_string(Avro_SOURCE "Dependency source for Avro C++" "" AUTO - BUNDLED SYSTEM) - define_option_string(GTest_SOURCE "Dependency source for GoogleTest" "" AUTO - BUNDLED SYSTEM) endif() macro(validate_config) diff --git a/cmake_modules/FindArrowAlt.cmake b/cmake_modules/FindArrowAlt.cmake index 582bdd8d3..dd4b4860a 100644 --- a/cmake_modules/FindArrowAlt.cmake +++ b/cmake_modules/FindArrowAlt.cmake @@ -25,36 +25,29 @@ function(_paimon_select_first_target OUT_VAR) endfunction() if(PAIMON_DEPENDENCY_USE_SHARED) - _paimon_select_first_target(_PAIMON_ARROW_TARGET Arrow::arrow_shared - Arrow::arrow) + _paimon_select_first_target(_PAIMON_ARROW_TARGET Arrow::arrow_shared Arrow::arrow) _paimon_select_first_target(_PAIMON_PARQUET_TARGET Parquet::parquet_shared Parquet::parquet) _paimon_select_first_target(_PAIMON_ARROW_DATASET_TARGET ArrowDataset::arrow_dataset_shared - Arrow::arrow_dataset_shared - ArrowDataset::arrow_dataset) - _paimon_select_first_target(_PAIMON_ARROW_ACERO_TARGET - ArrowAcero::arrow_acero_shared + Arrow::arrow_dataset_shared ArrowDataset::arrow_dataset) + _paimon_select_first_target(_PAIMON_ARROW_ACERO_TARGET ArrowAcero::arrow_acero_shared Arrow::arrow_acero_shared ArrowAcero::arrow_acero) else() - _paimon_select_first_target(_PAIMON_ARROW_TARGET Arrow::arrow_static - Arrow::arrow) + _paimon_select_first_target(_PAIMON_ARROW_TARGET Arrow::arrow_static Arrow::arrow) _paimon_select_first_target(_PAIMON_PARQUET_TARGET Parquet::parquet_static Parquet::parquet) _paimon_select_first_target(_PAIMON_ARROW_DATASET_TARGET ArrowDataset::arrow_dataset_static - Arrow::arrow_dataset_static - ArrowDataset::arrow_dataset) - _paimon_select_first_target(_PAIMON_ARROW_ACERO_TARGET - ArrowAcero::arrow_acero_static + Arrow::arrow_dataset_static ArrowDataset::arrow_dataset) + _paimon_select_first_target(_PAIMON_ARROW_ACERO_TARGET ArrowAcero::arrow_acero_static Arrow::arrow_acero_static ArrowAcero::arrow_acero) endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args( - ArrowAlt - REQUIRED_VARS _PAIMON_ARROW_TARGET _PAIMON_PARQUET_TARGET - _PAIMON_ARROW_DATASET_TARGET _PAIMON_ARROW_ACERO_TARGET) + ArrowAlt REQUIRED_VARS _PAIMON_ARROW_TARGET _PAIMON_PARQUET_TARGET + _PAIMON_ARROW_DATASET_TARGET _PAIMON_ARROW_ACERO_TARGET) if(ArrowAlt_FOUND) get_target_property(ARROW_INCLUDE_DIR ${_PAIMON_ARROW_TARGET} @@ -64,28 +57,25 @@ if(ArrowAlt_FOUND) add_library(arrow INTERFACE IMPORTED) if(ARROW_INCLUDE_DIR) set_target_properties(arrow PROPERTIES INTERFACE_INCLUDE_DIRECTORIES - "${ARROW_INCLUDE_DIR}") + "${ARROW_INCLUDE_DIR}") endif() target_link_libraries(arrow INTERFACE ${_PAIMON_ARROW_TARGET}) endif() if(NOT TARGET arrow_acero) add_library(arrow_acero INTERFACE IMPORTED) - target_link_libraries(arrow_acero INTERFACE ${_PAIMON_ARROW_ACERO_TARGET} - arrow) + target_link_libraries(arrow_acero INTERFACE ${_PAIMON_ARROW_ACERO_TARGET} arrow) endif() if(NOT TARGET arrow_dataset) add_library(arrow_dataset INTERFACE IMPORTED) - target_link_libraries(arrow_dataset - INTERFACE ${_PAIMON_ARROW_DATASET_TARGET} - arrow_acero) + target_link_libraries(arrow_dataset INTERFACE ${_PAIMON_ARROW_DATASET_TARGET} + arrow_acero) endif() if(NOT TARGET parquet) add_library(parquet INTERFACE IMPORTED) - target_link_libraries(parquet INTERFACE ${_PAIMON_PARQUET_TARGET} - arrow_dataset) + target_link_libraries(parquet INTERFACE ${_PAIMON_PARQUET_TARGET} arrow_dataset) endif() endif() diff --git a/cmake_modules/FindAvroAlt.cmake b/cmake_modules/FindAvroAlt.cmake index 011d3abff..104b6f155 100644 --- a/cmake_modules/FindAvroAlt.cmake +++ b/cmake_modules/FindAvroAlt.cmake @@ -13,20 +13,23 @@ if(PkgConfig_FOUND) pkg_check_modules(PC_Avro QUIET avro-cpp) endif() -find_path(AVRO_INCLUDE_DIR NAMES avro/Decoder.hh ${_PAIMON_AVRO_FIND_ARGS} - HINTS ${PC_Avro_INCLUDE_DIRS} PATH_SUFFIXES include) -find_library(AVRO_LIBRARY NAMES avrocpp_s avrocpp ${_PAIMON_AVRO_FIND_ARGS} - HINTS ${PC_Avro_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) +find_path(AVRO_INCLUDE_DIR + NAMES avro/Decoder.hh ${_PAIMON_AVRO_FIND_ARGS} + HINTS ${PC_Avro_INCLUDE_DIRS} + PATH_SUFFIXES include) +find_library(AVRO_LIBRARY + NAMES avrocpp_s avrocpp ${_PAIMON_AVRO_FIND_ARGS} + HINTS ${PC_Avro_LIBRARY_DIRS} + PATH_SUFFIXES lib lib64) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(AvroAlt REQUIRED_VARS AVRO_LIBRARY - AVRO_INCLUDE_DIR) +find_package_handle_standard_args(AvroAlt REQUIRED_VARS AVRO_LIBRARY AVRO_INCLUDE_DIR) if(AvroAlt_FOUND AND NOT TARGET avro) add_library(avro UNKNOWN IMPORTED) - set_target_properties(avro PROPERTIES IMPORTED_LOCATION "${AVRO_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES - "${AVRO_INCLUDE_DIR}") + set_target_properties(avro + PROPERTIES IMPORTED_LOCATION "${AVRO_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${AVRO_INCLUDE_DIR}") foreach(_dependency zlib zstd snappy) if(TARGET ${_dependency}) target_link_libraries(avro INTERFACE ${_dependency}) diff --git a/cmake_modules/FindGTestAlt.cmake b/cmake_modules/FindGTestAlt.cmake index b0ed5db10..074bceeae 100644 --- a/cmake_modules/FindGTestAlt.cmake +++ b/cmake_modules/FindGTestAlt.cmake @@ -10,55 +10,58 @@ endif() find_package(GTest CONFIG QUIET ${_PAIMON_GTEST_FIND_ARGS}) -if(NOT TARGET GTest::gtest OR NOT TARGET GTest::gtest_main +if(NOT TARGET GTest::gtest + OR NOT TARGET GTest::gtest_main OR NOT TARGET GTest::gmock) - find_path(GTEST_INCLUDE_DIR NAMES gtest/gtest.h ${_PAIMON_GTEST_FIND_ARGS} + find_path(GTEST_INCLUDE_DIR + NAMES gtest/gtest.h ${_PAIMON_GTEST_FIND_ARGS} PATH_SUFFIXES include) - find_library(GTEST_LIBRARY NAMES gtest ${_PAIMON_GTEST_FIND_ARGS} + find_library(GTEST_LIBRARY + NAMES gtest ${_PAIMON_GTEST_FIND_ARGS} PATH_SUFFIXES lib lib64) - find_library(GTEST_MAIN_LIBRARY NAMES gtest_main ${_PAIMON_GTEST_FIND_ARGS} + find_library(GTEST_MAIN_LIBRARY + NAMES gtest_main ${_PAIMON_GTEST_FIND_ARGS} PATH_SUFFIXES lib lib64) - find_library(GMOCK_LIBRARY NAMES gmock ${_PAIMON_GTEST_FIND_ARGS} + find_library(GMOCK_LIBRARY + NAMES gmock ${_PAIMON_GTEST_FIND_ARGS} PATH_SUFFIXES lib lib64) include(FindPackageHandleStandardArgs) find_package_handle_standard_args( - GTestAlt REQUIRED_VARS GTEST_INCLUDE_DIR GTEST_LIBRARY - GTEST_MAIN_LIBRARY GMOCK_LIBRARY) + GTestAlt REQUIRED_VARS GTEST_INCLUDE_DIR GTEST_LIBRARY GTEST_MAIN_LIBRARY + GMOCK_LIBRARY) if(GTestAlt_FOUND) if(NOT TARGET GTest::gtest) add_library(GTest::gtest UNKNOWN IMPORTED) - set_target_properties( - GTest::gtest - PROPERTIES IMPORTED_LOCATION "${GTEST_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIR}") + set_target_properties(GTest::gtest + PROPERTIES IMPORTED_LOCATION "${GTEST_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${GTEST_INCLUDE_DIR}") endif() if(NOT TARGET GTest::gtest_main) add_library(GTest::gtest_main UNKNOWN IMPORTED) - set_target_properties( - GTest::gtest_main - PROPERTIES IMPORTED_LOCATION "${GTEST_MAIN_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIR}") + set_target_properties(GTest::gtest_main + PROPERTIES IMPORTED_LOCATION "${GTEST_MAIN_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${GTEST_INCLUDE_DIR}") endif() if(NOT TARGET GTest::gmock) add_library(GTest::gmock UNKNOWN IMPORTED) - set_target_properties( - GTest::gmock - PROPERTIES IMPORTED_LOCATION "${GMOCK_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIR}") + set_target_properties(GTest::gmock + PROPERTIES IMPORTED_LOCATION "${GMOCK_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${GTEST_INCLUDE_DIR}") endif() endif() else() - get_target_property(GTEST_INCLUDE_DIR GTest::gtest - INTERFACE_INCLUDE_DIRECTORIES) + get_target_property(GTEST_INCLUDE_DIR GTest::gtest INTERFACE_INCLUDE_DIRECTORIES) set(GTestAlt_FOUND TRUE) endif() if(GTestAlt_FOUND) find_package(Threads REQUIRED) - set(GTEST_LINK_TOOLCHAIN GTest::gtest_main GTest::gtest GTest::gmock - Threads::Threads) + set(GTEST_LINK_TOOLCHAIN GTest::gtest_main GTest::gtest GTest::gmock Threads::Threads) endif() unset(_PAIMON_GTEST_FIND_ARGS) diff --git a/cmake_modules/FindLZ4Alt.cmake b/cmake_modules/FindLZ4Alt.cmake index ebf0efc7a..929576c2a 100644 --- a/cmake_modules/FindLZ4Alt.cmake +++ b/cmake_modules/FindLZ4Alt.cmake @@ -26,7 +26,7 @@ if(_PAIMON_LZ4_TARGET) add_library(lz4 INTERFACE IMPORTED) if(LZ4_INCLUDE_DIR) set_target_properties(lz4 PROPERTIES INTERFACE_INCLUDE_DIRECTORIES - "${LZ4_INCLUDE_DIR}") + "${LZ4_INCLUDE_DIR}") endif() target_link_libraries(lz4 INTERFACE ${_PAIMON_LZ4_TARGET}) endif() @@ -38,14 +38,17 @@ else() pkg_check_modules(PC_LZ4 QUIET liblz4) endif() - find_path(LZ4_INCLUDE_DIR NAMES lz4.h ${_PAIMON_LZ4_FIND_ARGS} - HINTS ${PC_LZ4_INCLUDE_DIRS} PATH_SUFFIXES include) - find_library(LZ4_LIBRARY NAMES lz4 liblz4 ${_PAIMON_LZ4_FIND_ARGS} - HINTS ${PC_LZ4_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + find_path(LZ4_INCLUDE_DIR + NAMES lz4.h ${_PAIMON_LZ4_FIND_ARGS} + HINTS ${PC_LZ4_INCLUDE_DIRS} + PATH_SUFFIXES include) + find_library(LZ4_LIBRARY + NAMES lz4 liblz4 ${_PAIMON_LZ4_FIND_ARGS} + HINTS ${PC_LZ4_LIBRARY_DIRS} + PATH_SUFFIXES lib lib64) include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(LZ4Alt REQUIRED_VARS LZ4_LIBRARY - LZ4_INCLUDE_DIR) + find_package_handle_standard_args(LZ4Alt REQUIRED_VARS LZ4_LIBRARY LZ4_INCLUDE_DIR) if(LZ4Alt_FOUND AND NOT TARGET lz4) add_library(lz4 UNKNOWN IMPORTED) diff --git a/cmake_modules/FindORCAlt.cmake b/cmake_modules/FindORCAlt.cmake index 85906fa0b..16c5f7bad 100644 --- a/cmake_modules/FindORCAlt.cmake +++ b/cmake_modules/FindORCAlt.cmake @@ -25,7 +25,12 @@ if(_PAIMON_ORC_TARGET) target_link_libraries(orc::orc INTERFACE ${_PAIMON_ORC_TARGET}) endif() - foreach(_dependency zstd snappy lz4 zlib libprotobuf) + foreach(_dependency + zstd + snappy + lz4 + zlib + libprotobuf) if(TARGET ${_dependency}) target_link_libraries(orc::orc INTERFACE ${_dependency}) endif() @@ -39,15 +44,17 @@ else() pkg_check_modules(PC_ORC QUIET orc) endif() - find_path(ORC_INCLUDE_DIR NAMES orc/OrcFile.hh - ${_PAIMON_ORC_FIND_ARGS} HINTS ${PC_ORC_INCLUDE_DIRS} + find_path(ORC_INCLUDE_DIR + NAMES orc/OrcFile.hh ${_PAIMON_ORC_FIND_ARGS} + HINTS ${PC_ORC_INCLUDE_DIRS} PATH_SUFFIXES include) - find_library(ORC_LIBRARY NAMES orc ${_PAIMON_ORC_FIND_ARGS} - HINTS ${PC_ORC_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + find_library(ORC_LIBRARY + NAMES orc ${_PAIMON_ORC_FIND_ARGS} + HINTS ${PC_ORC_LIBRARY_DIRS} + PATH_SUFFIXES lib lib64) include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(ORCAlt REQUIRED_VARS ORC_LIBRARY - ORC_INCLUDE_DIR) + find_package_handle_standard_args(ORCAlt REQUIRED_VARS ORC_LIBRARY ORC_INCLUDE_DIR) if(ORCAlt_FOUND AND NOT TARGET orc::orc) add_library(orc::orc UNKNOWN IMPORTED) @@ -55,7 +62,12 @@ else() PROPERTIES IMPORTED_LOCATION "${ORC_LIBRARY}" INTERFACE_INCLUDE_DIRECTORIES "${ORC_INCLUDE_DIR}") - foreach(_dependency zstd snappy lz4 zlib libprotobuf) + foreach(_dependency + zstd + snappy + lz4 + zlib + libprotobuf) if(TARGET ${_dependency}) target_link_libraries(orc::orc INTERFACE ${_dependency}) endif() diff --git a/cmake_modules/FindProtobufAlt.cmake b/cmake_modules/FindProtobufAlt.cmake index 55a915a03..42cc2de05 100644 --- a/cmake_modules/FindProtobufAlt.cmake +++ b/cmake_modules/FindProtobufAlt.cmake @@ -2,18 +2,15 @@ # # Licensed under the Apache License, Version 2.0 (the "License"); -set(_PAIMON_PROTOBUF_ROOTS ${Protobuf_ROOT} ${PROTOBUF_ROOT} - ${PAIMON_PACKAGE_PREFIX}) +set(_PAIMON_PROTOBUF_ROOTS ${Protobuf_ROOT} ${PROTOBUF_ROOT} ${PAIMON_PACKAGE_PREFIX}) list(REMOVE_ITEM _PAIMON_PROTOBUF_ROOTS "") if(_PAIMON_PROTOBUF_ROOTS) - set(_PAIMON_PROTOBUF_FIND_ARGS HINTS ${_PAIMON_PROTOBUF_ROOTS} - NO_DEFAULT_PATH) + set(_PAIMON_PROTOBUF_FIND_ARGS HINTS ${_PAIMON_PROTOBUF_ROOTS} NO_DEFAULT_PATH) endif() find_package(Protobuf CONFIG QUIET ${_PAIMON_PROTOBUF_FIND_ARGS}) -set(_PAIMON_PROTOBUF_LIBRARY_TARGETS protobuf::libprotobuf - Protobuf::libprotobuf) +set(_PAIMON_PROTOBUF_LIBRARY_TARGETS protobuf::libprotobuf Protobuf::libprotobuf) foreach(_target IN LISTS _PAIMON_PROTOBUF_LIBRARY_TARGETS) if(TARGET ${_target}) set(_PAIMON_PROTOBUF_LIBRARY_TARGET ${_target}) @@ -33,33 +30,30 @@ set(_PAIMON_PROTOC_TARGETS protobuf::protoc Protobuf::protoc) foreach(_target IN LISTS _PAIMON_PROTOC_TARGETS) if(TARGET ${_target}) set(_PAIMON_PROTOC_TARGET ${_target}) - get_target_property(PROTOBUF_COMPILER ${_PAIMON_PROTOC_TARGET} - IMPORTED_LOCATION) + get_target_property(PROTOBUF_COMPILER ${_PAIMON_PROTOC_TARGET} IMPORTED_LOCATION) break() endif() endforeach() if(_PAIMON_PROTOBUF_LIBRARY_TARGET AND NOT PROTOBUF_COMPILER) - find_program(PROTOBUF_COMPILER NAMES protoc ${_PAIMON_PROTOBUF_FIND_ARGS} + find_program(PROTOBUF_COMPILER + NAMES protoc ${_PAIMON_PROTOBUF_FIND_ARGS} PATH_SUFFIXES bin) endif() if(_PAIMON_PROTOBUF_LIBRARY_TARGET) include(FindPackageHandleStandardArgs) find_package_handle_standard_args( - ProtobufAlt REQUIRED_VARS _PAIMON_PROTOBUF_LIBRARY_TARGET - PROTOBUF_COMPILER) + ProtobufAlt REQUIRED_VARS _PAIMON_PROTOBUF_LIBRARY_TARGET PROTOBUF_COMPILER) if(ProtobufAlt_FOUND) - get_target_property(PROTOBUF_INCLUDE_DIR - ${_PAIMON_PROTOBUF_LIBRARY_TARGET} + get_target_property(PROTOBUF_INCLUDE_DIR ${_PAIMON_PROTOBUF_LIBRARY_TARGET} INTERFACE_INCLUDE_DIRECTORIES) if(NOT TARGET libprotobuf) add_library(libprotobuf INTERFACE IMPORTED) if(PROTOBUF_INCLUDE_DIR) - set_target_properties( - libprotobuf PROPERTIES INTERFACE_INCLUDE_DIRECTORIES - "${PROTOBUF_INCLUDE_DIR}") + set_target_properties(libprotobuf PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${PROTOBUF_INCLUDE_DIR}") endif() target_link_libraries(libprotobuf INTERFACE ${_PAIMON_PROTOBUF_LIBRARY_TARGET}) @@ -68,18 +62,16 @@ if(_PAIMON_PROTOBUF_LIBRARY_TARGET) if(_PAIMON_PROTOC_LIBRARY_TARGET AND NOT TARGET libprotoc) add_library(libprotoc INTERFACE IMPORTED) if(PROTOBUF_INCLUDE_DIR) - set_target_properties( - libprotoc PROPERTIES INTERFACE_INCLUDE_DIRECTORIES - "${PROTOBUF_INCLUDE_DIR}") + set_target_properties(libprotoc PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${PROTOBUF_INCLUDE_DIR}") endif() - target_link_libraries(libprotoc - INTERFACE ${_PAIMON_PROTOC_LIBRARY_TARGET}) + target_link_libraries(libprotoc INTERFACE ${_PAIMON_PROTOC_LIBRARY_TARGET}) endif() if(NOT TARGET protoc) add_executable(protoc IMPORTED) set_target_properties(protoc PROPERTIES IMPORTED_LOCATION - "${PROTOBUF_COMPILER}") + "${PROTOBUF_COMPILER}") endif() set(PROTOBUF_LIBRARIES ${_PAIMON_PROTOBUF_LIBRARY_TARGET}) @@ -90,30 +82,33 @@ else() pkg_check_modules(PC_Protobuf QUIET protobuf) endif() - find_path(PROTOBUF_INCLUDE_DIR NAMES google/protobuf/message.h - ${_PAIMON_PROTOBUF_FIND_ARGS} HINTS ${PC_Protobuf_INCLUDE_DIRS} + find_path(PROTOBUF_INCLUDE_DIR + NAMES google/protobuf/message.h ${_PAIMON_PROTOBUF_FIND_ARGS} + HINTS ${PC_Protobuf_INCLUDE_DIRS} PATH_SUFFIXES include) - find_library(PROTOBUF_LIBRARY NAMES protobuf - ${_PAIMON_PROTOBUF_FIND_ARGS} - HINTS ${PC_Protobuf_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) - find_library(PROTOC_LIBRARY NAMES protoc ${_PAIMON_PROTOBUF_FIND_ARGS} - HINTS ${PC_Protobuf_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) - find_program(PROTOBUF_COMPILER NAMES protoc ${_PAIMON_PROTOBUF_FIND_ARGS} + find_library(PROTOBUF_LIBRARY + NAMES protobuf ${_PAIMON_PROTOBUF_FIND_ARGS} + HINTS ${PC_Protobuf_LIBRARY_DIRS} + PATH_SUFFIXES lib lib64) + find_library(PROTOC_LIBRARY + NAMES protoc ${_PAIMON_PROTOBUF_FIND_ARGS} + HINTS ${PC_Protobuf_LIBRARY_DIRS} + PATH_SUFFIXES lib lib64) + find_program(PROTOBUF_COMPILER + NAMES protoc ${_PAIMON_PROTOBUF_FIND_ARGS} PATH_SUFFIXES bin) include(FindPackageHandleStandardArgs) find_package_handle_standard_args( - ProtobufAlt REQUIRED_VARS PROTOBUF_LIBRARY PROTOBUF_INCLUDE_DIR - PROTOBUF_COMPILER) + ProtobufAlt REQUIRED_VARS PROTOBUF_LIBRARY PROTOBUF_INCLUDE_DIR PROTOBUF_COMPILER) if(ProtobufAlt_FOUND) if(NOT TARGET libprotobuf) add_library(libprotobuf UNKNOWN IMPORTED) - set_target_properties( - libprotobuf - PROPERTIES IMPORTED_LOCATION "${PROTOBUF_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES - "${PROTOBUF_INCLUDE_DIR}") + set_target_properties(libprotobuf + PROPERTIES IMPORTED_LOCATION "${PROTOBUF_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${PROTOBUF_INCLUDE_DIR}") if(TARGET zlib) target_link_libraries(libprotobuf INTERFACE zlib) endif() @@ -121,17 +116,17 @@ else() if(PROTOC_LIBRARY AND NOT TARGET libprotoc) add_library(libprotoc UNKNOWN IMPORTED) - set_target_properties( - libprotoc PROPERTIES IMPORTED_LOCATION "${PROTOC_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES - "${PROTOBUF_INCLUDE_DIR}") + set_target_properties(libprotoc + PROPERTIES IMPORTED_LOCATION "${PROTOC_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${PROTOBUF_INCLUDE_DIR}") target_link_libraries(libprotoc INTERFACE libprotobuf) endif() if(NOT TARGET protoc) add_executable(protoc IMPORTED) set_target_properties(protoc PROPERTIES IMPORTED_LOCATION - "${PROTOBUF_COMPILER}") + "${PROTOBUF_COMPILER}") endif() set(PROTOBUF_LIBRARIES "${PROTOBUF_LIBRARY}") diff --git a/cmake_modules/FindRE2Alt.cmake b/cmake_modules/FindRE2Alt.cmake index cafa397df..ceb84b810 100644 --- a/cmake_modules/FindRE2Alt.cmake +++ b/cmake_modules/FindRE2Alt.cmake @@ -20,14 +20,17 @@ else() pkg_check_modules(PC_RE2 QUIET re2) endif() - find_path(RE2_INCLUDE_DIR NAMES re2/re2.h ${_PAIMON_RE2_FIND_ARGS} - HINTS ${PC_RE2_INCLUDE_DIRS} PATH_SUFFIXES include) - find_library(RE2_LIBRARY NAMES re2 ${_PAIMON_RE2_FIND_ARGS} - HINTS ${PC_RE2_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + find_path(RE2_INCLUDE_DIR + NAMES re2/re2.h ${_PAIMON_RE2_FIND_ARGS} + HINTS ${PC_RE2_INCLUDE_DIRS} + PATH_SUFFIXES include) + find_library(RE2_LIBRARY + NAMES re2 ${_PAIMON_RE2_FIND_ARGS} + HINTS ${PC_RE2_LIBRARY_DIRS} + PATH_SUFFIXES lib lib64) include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(RE2Alt REQUIRED_VARS RE2_LIBRARY - RE2_INCLUDE_DIR) + find_package_handle_standard_args(RE2Alt REQUIRED_VARS RE2_LIBRARY RE2_INCLUDE_DIR) if(RE2Alt_FOUND) add_library(re2::re2 UNKNOWN IMPORTED) diff --git a/cmake_modules/FindRapidJSONAlt.cmake b/cmake_modules/FindRapidJSONAlt.cmake index 710d0006e..c68a9a170 100644 --- a/cmake_modules/FindRapidJSONAlt.cmake +++ b/cmake_modules/FindRapidJSONAlt.cmake @@ -2,12 +2,10 @@ # # Licensed under the Apache License, Version 2.0 (the "License"); -set(_PAIMON_RAPIDJSON_ROOTS ${RapidJSON_ROOT} ${RAPIDJSON_ROOT} - ${PAIMON_PACKAGE_PREFIX}) +set(_PAIMON_RAPIDJSON_ROOTS ${RapidJSON_ROOT} ${RAPIDJSON_ROOT} ${PAIMON_PACKAGE_PREFIX}) list(REMOVE_ITEM _PAIMON_RAPIDJSON_ROOTS "") if(_PAIMON_RAPIDJSON_ROOTS) - set(_PAIMON_RAPIDJSON_FIND_ARGS HINTS ${_PAIMON_RAPIDJSON_ROOTS} - NO_DEFAULT_PATH) + set(_PAIMON_RAPIDJSON_FIND_ARGS HINTS ${_PAIMON_RAPIDJSON_ROOTS} NO_DEFAULT_PATH) endif() find_package(RapidJSON CONFIG QUIET ${_PAIMON_RAPIDJSON_FIND_ARGS}) @@ -25,16 +23,15 @@ if(_PAIMON_RAPIDJSON_TARGET) add_library(RapidJSON INTERFACE IMPORTED) target_link_libraries(RapidJSON INTERFACE ${_PAIMON_RAPIDJSON_TARGET}) endif() - get_target_property(RAPIDJSON_INCLUDE_DIR RapidJSON - INTERFACE_INCLUDE_DIRECTORIES) + get_target_property(RAPIDJSON_INCLUDE_DIR RapidJSON INTERFACE_INCLUDE_DIRECTORIES) set(RapidJSONAlt_FOUND TRUE) else() - find_path(RAPIDJSON_INCLUDE_DIR NAMES rapidjson/rapidjson.h - ${_PAIMON_RAPIDJSON_FIND_ARGS} PATH_SUFFIXES include) + find_path(RAPIDJSON_INCLUDE_DIR + NAMES rapidjson/rapidjson.h ${_PAIMON_RAPIDJSON_FIND_ARGS} + PATH_SUFFIXES include) include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(RapidJSONAlt - REQUIRED_VARS RAPIDJSON_INCLUDE_DIR) + find_package_handle_standard_args(RapidJSONAlt REQUIRED_VARS RAPIDJSON_INCLUDE_DIR) if(RapidJSONAlt_FOUND AND NOT TARGET RapidJSON) add_library(RapidJSON INTERFACE IMPORTED) diff --git a/cmake_modules/FindSnappyAlt.cmake b/cmake_modules/FindSnappyAlt.cmake index 8b2b461ca..81336dea1 100644 --- a/cmake_modules/FindSnappyAlt.cmake +++ b/cmake_modules/FindSnappyAlt.cmake @@ -5,8 +5,7 @@ set(_PAIMON_SNAPPY_ROOTS ${Snappy_ROOT} ${SNAPPY_ROOT} ${PAIMON_PACKAGE_PREFIX}) list(REMOVE_ITEM _PAIMON_SNAPPY_ROOTS "") if(_PAIMON_SNAPPY_ROOTS) - set(_PAIMON_SNAPPY_FIND_ARGS HINTS ${_PAIMON_SNAPPY_ROOTS} - NO_DEFAULT_PATH) + set(_PAIMON_SNAPPY_FIND_ARGS HINTS ${_PAIMON_SNAPPY_ROOTS} NO_DEFAULT_PATH) endif() find_package(Snappy CONFIG QUIET ${_PAIMON_SNAPPY_FIND_ARGS}) @@ -26,7 +25,7 @@ if(_PAIMON_SNAPPY_TARGET) add_library(snappy INTERFACE IMPORTED) if(SNAPPY_INCLUDE_DIR) set_target_properties(snappy PROPERTIES INTERFACE_INCLUDE_DIRECTORIES - "${SNAPPY_INCLUDE_DIR}") + "${SNAPPY_INCLUDE_DIR}") endif() target_link_libraries(snappy INTERFACE ${_PAIMON_SNAPPY_TARGET}) endif() @@ -38,14 +37,18 @@ else() pkg_check_modules(PC_Snappy QUIET snappy) endif() - find_path(SNAPPY_INCLUDE_DIR NAMES snappy.h ${_PAIMON_SNAPPY_FIND_ARGS} - HINTS ${PC_Snappy_INCLUDE_DIRS} PATH_SUFFIXES include) - find_library(SNAPPY_LIBRARY NAMES snappy ${_PAIMON_SNAPPY_FIND_ARGS} - HINTS ${PC_Snappy_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + find_path(SNAPPY_INCLUDE_DIR + NAMES snappy.h ${_PAIMON_SNAPPY_FIND_ARGS} + HINTS ${PC_Snappy_INCLUDE_DIRS} + PATH_SUFFIXES include) + find_library(SNAPPY_LIBRARY + NAMES snappy ${_PAIMON_SNAPPY_FIND_ARGS} + HINTS ${PC_Snappy_LIBRARY_DIRS} + PATH_SUFFIXES lib lib64) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(SnappyAlt REQUIRED_VARS SNAPPY_LIBRARY - SNAPPY_INCLUDE_DIR) + SNAPPY_INCLUDE_DIR) if(SnappyAlt_FOUND AND NOT TARGET snappy) add_library(snappy UNKNOWN IMPORTED) diff --git a/cmake_modules/FindTBBAlt.cmake b/cmake_modules/FindTBBAlt.cmake index 240dc3c0b..406436f73 100644 --- a/cmake_modules/FindTBBAlt.cmake +++ b/cmake_modules/FindTBBAlt.cmake @@ -36,21 +36,24 @@ else() pkg_check_modules(PC_TBB QUIET tbb) endif() - find_path(TBB_INCLUDE_DIR NAMES tbb/tbb.h oneapi/tbb/tbb.h - ${_PAIMON_TBB_FIND_ARGS} HINTS ${PC_TBB_INCLUDE_DIRS} + find_path(TBB_INCLUDE_DIR + NAMES tbb/tbb.h oneapi/tbb/tbb.h ${_PAIMON_TBB_FIND_ARGS} + HINTS ${PC_TBB_INCLUDE_DIRS} PATH_SUFFIXES include) - find_library(TBB_LIBRARY NAMES tbb ${_PAIMON_TBB_FIND_ARGS} - HINTS ${PC_TBB_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + find_library(TBB_LIBRARY + NAMES tbb ${_PAIMON_TBB_FIND_ARGS} + HINTS ${PC_TBB_LIBRARY_DIRS} + PATH_SUFFIXES lib lib64) include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(TBBAlt REQUIRED_VARS TBB_LIBRARY - TBB_INCLUDE_DIR) + find_package_handle_standard_args(TBBAlt REQUIRED_VARS TBB_LIBRARY TBB_INCLUDE_DIR) if(TBBAlt_FOUND AND NOT TARGET tbb) add_library(tbb UNKNOWN IMPORTED) - set_target_properties(tbb PROPERTIES IMPORTED_LOCATION "${TBB_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES - "${TBB_INCLUDE_DIR}") + set_target_properties(tbb + PROPERTIES IMPORTED_LOCATION "${TBB_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${TBB_INCLUDE_DIR}") endif() endif() diff --git a/cmake_modules/FindZLIBAlt.cmake b/cmake_modules/FindZLIBAlt.cmake index 713bcf930..3ee283ebb 100644 --- a/cmake_modules/FindZLIBAlt.cmake +++ b/cmake_modules/FindZLIBAlt.cmake @@ -30,14 +30,15 @@ if(TARGET ZLIB::ZLIB) set(ZLIB_LIBRARIES ZLIB::ZLIB) set(ZLIBAlt_FOUND TRUE) else() - find_path(ZLIB_INCLUDE_DIR NAMES zlib.h ${_PAIMON_ZLIB_FIND_ARGS} + find_path(ZLIB_INCLUDE_DIR + NAMES zlib.h ${_PAIMON_ZLIB_FIND_ARGS} PATH_SUFFIXES include) - find_library(ZLIB_LIBRARY NAMES z zlib ${_PAIMON_ZLIB_FIND_ARGS} + find_library(ZLIB_LIBRARY + NAMES z zlib ${_PAIMON_ZLIB_FIND_ARGS} PATH_SUFFIXES lib lib64) include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(ZLIBAlt REQUIRED_VARS ZLIB_LIBRARY - ZLIB_INCLUDE_DIR) + find_package_handle_standard_args(ZLIBAlt REQUIRED_VARS ZLIB_LIBRARY ZLIB_INCLUDE_DIR) if(ZLIBAlt_FOUND AND NOT TARGET zlib) add_library(zlib UNKNOWN IMPORTED) diff --git a/cmake_modules/FindfmtAlt.cmake b/cmake_modules/FindfmtAlt.cmake index 50319dcdf..2c3586d37 100644 --- a/cmake_modules/FindfmtAlt.cmake +++ b/cmake_modules/FindfmtAlt.cmake @@ -37,20 +37,24 @@ else() pkg_check_modules(PC_fmt QUIET fmt) endif() - find_path(FMT_INCLUDE_DIR NAMES fmt/core.h ${_PAIMON_FMT_FIND_ARGS} - HINTS ${PC_fmt_INCLUDE_DIRS} PATH_SUFFIXES include) - find_library(FMT_LIBRARY NAMES fmt ${_PAIMON_FMT_FIND_ARGS} - HINTS ${PC_fmt_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + find_path(FMT_INCLUDE_DIR + NAMES fmt/core.h ${_PAIMON_FMT_FIND_ARGS} + HINTS ${PC_fmt_INCLUDE_DIRS} + PATH_SUFFIXES include) + find_library(FMT_LIBRARY + NAMES fmt ${_PAIMON_FMT_FIND_ARGS} + HINTS ${PC_fmt_LIBRARY_DIRS} + PATH_SUFFIXES lib lib64) include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(fmtAlt REQUIRED_VARS FMT_INCLUDE_DIR - FMT_LIBRARY) + find_package_handle_standard_args(fmtAlt REQUIRED_VARS FMT_INCLUDE_DIR FMT_LIBRARY) if(fmtAlt_FOUND AND NOT TARGET fmt) add_library(fmt UNKNOWN IMPORTED) - set_target_properties(fmt PROPERTIES IMPORTED_LOCATION "${FMT_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES - "${FMT_INCLUDE_DIR}") + set_target_properties(fmt + PROPERTIES IMPORTED_LOCATION "${FMT_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${FMT_INCLUDE_DIR}") set(FMT_LIBRARIES "${FMT_LIBRARY}") endif() endif() diff --git a/cmake_modules/FindglogAlt.cmake b/cmake_modules/FindglogAlt.cmake index b5c4fe1d4..db26c83c1 100644 --- a/cmake_modules/FindglogAlt.cmake +++ b/cmake_modules/FindglogAlt.cmake @@ -36,21 +36,26 @@ else() pkg_check_modules(PC_glog QUIET libglog) endif() - find_path(GLOG_INCLUDE_DIR NAMES glog/logging.h ${_PAIMON_GLOG_FIND_ARGS} - HINTS ${PC_glog_INCLUDE_DIRS} PATH_SUFFIXES include) - find_library(GLOG_LIBRARY NAMES glog ${_PAIMON_GLOG_FIND_ARGS} - HINTS ${PC_glog_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + find_path(GLOG_INCLUDE_DIR + NAMES glog/logging.h ${_PAIMON_GLOG_FIND_ARGS} + HINTS ${PC_glog_INCLUDE_DIRS} + PATH_SUFFIXES include) + find_library(GLOG_LIBRARY + NAMES glog ${_PAIMON_GLOG_FIND_ARGS} + HINTS ${PC_glog_LIBRARY_DIRS} + PATH_SUFFIXES lib lib64) include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(glogAlt REQUIRED_VARS GLOG_LIBRARY - GLOG_INCLUDE_DIR) + find_package_handle_standard_args(glogAlt REQUIRED_VARS GLOG_LIBRARY GLOG_INCLUDE_DIR) if(glogAlt_FOUND AND NOT TARGET glog) add_library(glog UNKNOWN IMPORTED) - set_target_properties( - glog PROPERTIES IMPORTED_LOCATION "${GLOG_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${GLOG_INCLUDE_DIR}" - INTERFACE_COMPILE_DEFINITIONS "GLOG_USE_GLOG_EXPORT") + set_target_properties(glog + PROPERTIES IMPORTED_LOCATION "${GLOG_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${GLOG_INCLUDE_DIR}" + INTERFACE_COMPILE_DEFINITIONS + "GLOG_USE_GLOG_EXPORT") find_library(LIBUNWIND_LIBRARY NAMES unwind) if(LIBUNWIND_LIBRARY) target_link_libraries(glog INTERFACE ${LIBUNWIND_LIBRARY}) diff --git a/cmake_modules/FindzstdAlt.cmake b/cmake_modules/FindzstdAlt.cmake index f7d59e694..db4baa906 100644 --- a/cmake_modules/FindzstdAlt.cmake +++ b/cmake_modules/FindzstdAlt.cmake @@ -14,7 +14,10 @@ set(_PAIMON_ZSTD_TARGETS) if(PAIMON_DEPENDENCY_USE_SHARED) list(APPEND _PAIMON_ZSTD_TARGETS zstd::libzstd_shared zstd::libzstd) endif() -list(APPEND _PAIMON_ZSTD_TARGETS zstd::libzstd_static zstd::libzstd +list(APPEND + _PAIMON_ZSTD_TARGETS + zstd::libzstd_static + zstd::libzstd zstd::zstd) foreach(_target IN LISTS _PAIMON_ZSTD_TARGETS) @@ -43,14 +46,17 @@ else() pkg_check_modules(PC_zstd QUIET libzstd) endif() - find_path(ZSTD_INCLUDE_DIR NAMES zstd.h ${_PAIMON_ZSTD_FIND_ARGS} - HINTS ${PC_zstd_INCLUDE_DIRS} PATH_SUFFIXES include) - find_library(ZSTD_LIBRARY NAMES zstd libzstd ${_PAIMON_ZSTD_FIND_ARGS} - HINTS ${PC_zstd_LIBRARY_DIRS} PATH_SUFFIXES lib lib64) + find_path(ZSTD_INCLUDE_DIR + NAMES zstd.h ${_PAIMON_ZSTD_FIND_ARGS} + HINTS ${PC_zstd_INCLUDE_DIRS} + PATH_SUFFIXES include) + find_library(ZSTD_LIBRARY + NAMES zstd libzstd ${_PAIMON_ZSTD_FIND_ARGS} + HINTS ${PC_zstd_LIBRARY_DIRS} + PATH_SUFFIXES lib lib64) include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(zstdAlt REQUIRED_VARS ZSTD_LIBRARY - ZSTD_INCLUDE_DIR) + find_package_handle_standard_args(zstdAlt REQUIRED_VARS ZSTD_LIBRARY ZSTD_INCLUDE_DIR) if(zstdAlt_FOUND AND NOT TARGET zstd) add_library(zstd UNKNOWN IMPORTED) diff --git a/cmake_modules/ThirdpartyToolchain.cmake b/cmake_modules/ThirdpartyToolchain.cmake index 93425adbf..5b88873cb 100644 --- a/cmake_modules/ThirdpartyToolchain.cmake +++ b/cmake_modules/ThirdpartyToolchain.cmake @@ -401,22 +401,26 @@ function(paimon_set_dependency_source_default DEPENDENCY_NAME SOURCE_VALUE REASO CACHE STRING "Dependency source for ${DEPENDENCY_NAME}" FORCE) set_property(CACHE ${DEPENDENCY_NAME}_SOURCE PROPERTY STRINGS ${PAIMON_DEPENDENCY_SOURCE_VALUES}) - message(STATUS - "Defaulting ${DEPENDENCY_NAME}_SOURCE to ${SOURCE_VALUE}: ${REASON}") + message(STATUS "Defaulting ${DEPENDENCY_NAME}_SOURCE to ${SOURCE_VALUE}: ${REASON}" + ) endif() endfunction() function(paimon_apply_dependency_source_defaults) paimon_get_dependency_source(Arrow _arrow_source) if(_arrow_source STREQUAL "SYSTEM" OR _arrow_source STREQUAL "BUNDLED") - foreach(_dependency zstd Snappy LZ4 ZLIB RE2) + foreach(_dependency + zstd + Snappy + LZ4 + ZLIB + RE2) paimon_set_dependency_source_default( ${_dependency} ${_arrow_source} "follow Arrow_SOURCE to avoid mixed transitive dependencies") endforeach() elseif(_arrow_source STREQUAL "AUTO") - paimon_configure_dependency_root(Arrow "${_arrow_source}" - _arrow_resolved_source) + paimon_configure_dependency_root(Arrow "${_arrow_source}" _arrow_resolved_source) find_package(ArrowAlt QUIET MODULE) if(ArrowAlt_FOUND) set(_arrow_dependency_default SYSTEM) @@ -427,10 +431,14 @@ function(paimon_apply_dependency_source_defaults) set(_arrow_dependency_reason "system Arrow not found during AUTO dependency precheck") endif() - foreach(_dependency zstd Snappy LZ4 ZLIB RE2) + foreach(_dependency + zstd + Snappy + LZ4 + ZLIB + RE2) paimon_set_dependency_source_default( - ${_dependency} ${_arrow_dependency_default} - "${_arrow_dependency_reason}") + ${_dependency} ${_arrow_dependency_default} "${_arrow_dependency_reason}") endforeach() endif() @@ -441,13 +449,11 @@ function(paimon_apply_dependency_source_defaults) Protobuf ${_orc_source} "follow ORC_SOURCE to avoid mixed transitive dependencies") elseif(_orc_source STREQUAL "AUTO") - paimon_configure_dependency_root(ORC "${_orc_source}" - _orc_resolved_source) + paimon_configure_dependency_root(ORC "${_orc_source}" _orc_resolved_source) find_package(ORCAlt QUIET MODULE) if(ORCAlt_FOUND) paimon_set_dependency_source_default( - Protobuf SYSTEM - "system ORC found during AUTO dependency precheck") + Protobuf SYSTEM "system ORC found during AUTO dependency precheck") else() paimon_set_dependency_source_default( Protobuf BUNDLED @@ -460,8 +466,8 @@ endfunction() function(paimon_configure_dependency_root DEPENDENCY_NAME SOURCE_VALUE OUT_SOURCE) set(_root_var "${DEPENDENCY_NAME}_ROOT") - if(NOT "${PAIMON_PACKAGE_PREFIX}" STREQUAL "" - AND (NOT DEFINED ${_root_var} OR "${${_root_var}}" STREQUAL "")) + if(NOT "${PAIMON_PACKAGE_PREFIX}" STREQUAL "" AND (NOT DEFINED ${_root_var} + OR "${${_root_var}}" STREQUAL "")) set(${_root_var} "${PAIMON_PACKAGE_PREFIX}" CACHE PATH "Root directory for ${DEPENDENCY_NAME}" FORCE) @@ -515,8 +521,11 @@ function(paimon_get_dependency_compat_target DEPENDENCY_NAME OUT_VAR) PARENT_SCOPE) endfunction() -function(paimon_record_dependency_resolution DEPENDENCY_NAME REQUESTED_SOURCE - ACTUAL_SOURCE TARGET_NAME) +function(paimon_record_dependency_resolution + DEPENDENCY_NAME + REQUESTED_SOURCE + ACTUAL_SOURCE + TARGET_NAME) get_property(_dependencies GLOBAL PROPERTY PAIMON_RESOLVED_DEPENDENCIES) list(APPEND _dependencies "${DEPENDENCY_NAME}") list(REMOVE_DUPLICATES _dependencies) @@ -524,12 +533,11 @@ function(paimon_record_dependency_resolution DEPENDENCY_NAME REQUESTED_SOURCE paimon_get_dependency_root("${DEPENDENCY_NAME}" _root) set_property(GLOBAL PROPERTY "PAIMON_${DEPENDENCY_NAME}_REQUESTED_SOURCE" - "${REQUESTED_SOURCE}") + "${REQUESTED_SOURCE}") set_property(GLOBAL PROPERTY "PAIMON_${DEPENDENCY_NAME}_ACTUAL_SOURCE" - "${ACTUAL_SOURCE}") + "${ACTUAL_SOURCE}") set_property(GLOBAL PROPERTY "PAIMON_${DEPENDENCY_NAME}_ROOT" "${_root}") - set_property(GLOBAL PROPERTY "PAIMON_${DEPENDENCY_NAME}_TARGET" - "${TARGET_NAME}") + set_property(GLOBAL PROPERTY "PAIMON_${DEPENDENCY_NAME}_TARGET" "${TARGET_NAME}") endfunction() function(paimon_print_dependency_resolution_summary) @@ -540,13 +548,11 @@ function(paimon_print_dependency_resolution_summary) message(STATUS "Dependency resolution summary:") foreach(_dependency IN LISTS _dependencies) - get_property(_requested GLOBAL - PROPERTY "PAIMON_${_dependency}_REQUESTED_SOURCE") + get_property(_requested GLOBAL PROPERTY "PAIMON_${_dependency}_REQUESTED_SOURCE") get_property(_actual GLOBAL PROPERTY "PAIMON_${_dependency}_ACTUAL_SOURCE") get_property(_root GLOBAL PROPERTY "PAIMON_${_dependency}_ROOT") get_property(_target GLOBAL PROPERTY "PAIMON_${_dependency}_TARGET") - message(STATUS - " ${_dependency}: requested=${_requested}, actual=${_actual}, target=${_target}, root=${_root}" + message(STATUS " ${_dependency}: requested=${_requested}, actual=${_actual}, target=${_target}, root=${_root}" ) endforeach() endfunction() @@ -665,15 +671,19 @@ function(paimon_warn_if_mixed_arrow_dependencies) return() endif() - foreach(_dependency zstd Snappy LZ4 ZLIB RE2) + foreach(_dependency + zstd + Snappy + LZ4 + ZLIB + RE2) if(DEFINED PAIMON_${_dependency}_ACTUAL_SOURCE AND NOT "${PAIMON_${_dependency}_ACTUAL_SOURCE}" STREQUAL - "${PAIMON_Arrow_ACTUAL_SOURCE}") - message(WARNING - "Arrow resolved from ${PAIMON_Arrow_ACTUAL_SOURCE}, but " - "${_dependency} resolved from " - "${PAIMON_${_dependency}_ACTUAL_SOURCE}. Mixing SYSTEM " - "and BUNDLED dependencies can cause ABI conflicts.") + "${PAIMON_Arrow_ACTUAL_SOURCE}") + message(WARNING "Arrow resolved from ${PAIMON_Arrow_ACTUAL_SOURCE}, but " + "${_dependency} resolved from " + "${PAIMON_${_dependency}_ACTUAL_SOURCE}. Mixing SYSTEM " + "and BUNDLED dependencies can cause ABI conflicts.") endif() endforeach() endfunction() @@ -791,8 +801,8 @@ macro(build_jieba) # The include directory must exist before it is referenced by a target. include_directories(SYSTEM ${JIEBA_INCLUDE_DIR} ${JIEBA_DICT_DIR}) add_library(jieba INTERFACE IMPORTED) - target_include_directories(jieba SYSTEM - INTERFACE "${JIEBA_INCLUDE_DIR} ${JIEBA_DICT_DIR}") + target_include_directories(jieba SYSTEM INTERFACE ${JIEBA_INCLUDE_DIR} + ${JIEBA_DICT_DIR}) add_dependencies(jieba_ep limonp_ep) add_dependencies(jieba jieba_ep) endmacro() From bfd27209ba3d783d915573b0d02e67b0878b8bd6 Mon Sep 17 00:00:00 2001 From: Socrates Date: Thu, 30 Apr 2026 15:16:14 +0800 Subject: [PATCH 9/9] Fix sanitizer object dependency propagation --- cmake_modules/BuildUtils.cmake | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/cmake_modules/BuildUtils.cmake b/cmake_modules/BuildUtils.cmake index 861ae8fbe..0bc75b64b 100644 --- a/cmake_modules/BuildUtils.cmake +++ b/cmake_modules/BuildUtils.cmake @@ -52,11 +52,15 @@ function(add_paimon_lib LIB_NAME) # Generate a single "objlib" from all C++ modules and link # that "objlib" into each library kind, to avoid compiling twice add_library(${LIB_NAME}_objlib OBJECT ${ARG_SOURCES}) + if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + target_compile_options(${LIB_NAME}_objlib PRIVATE -Wno-global-constructors) + endif() # Necessary to make static linking into other shared libraries work properly set_property(TARGET ${LIB_NAME}_objlib PROPERTY POSITION_INDEPENDENT_CODE 1) if(ARG_DEPENDENCIES) # In static-only builds, some dependency names are still declared as # *_shared. Map them to *_static when the shared target is unavailable. + set(_paimon_objlib_link_deps) set(_paimon_objlib_deps) foreach(_paimon_dep IN LISTS ARG_DEPENDENCIES) set(_paimon_mapped_dep "${_paimon_dep}") @@ -65,15 +69,24 @@ function(add_paimon_lib LIB_NAME) "${_paimon_dep}") endif() if(TARGET ${_paimon_mapped_dep}) + get_target_property(_paimon_is_internal_lib ${_paimon_mapped_dep} + PAIMON_INTERNAL_LIBRARY) list(APPEND _paimon_objlib_deps ${_paimon_mapped_dep}) + if(NOT _paimon_is_internal_lib) + list(APPEND _paimon_objlib_link_deps ${_paimon_mapped_dep}) + endif() + unset(_paimon_is_internal_lib) endif() unset(_paimon_mapped_dep) endforeach() if(_paimon_objlib_deps) add_dependencies(${LIB_NAME}_objlib ${_paimon_objlib_deps}) - target_link_libraries(${LIB_NAME}_objlib PRIVATE ${_paimon_objlib_deps}) + endif() + if(_paimon_objlib_link_deps) + target_link_libraries(${LIB_NAME}_objlib PRIVATE ${_paimon_objlib_link_deps}) endif() unset(_paimon_objlib_deps) + unset(_paimon_objlib_link_deps) unset(_paimon_dep) endif() set(LIB_DEPS $) @@ -104,6 +117,7 @@ function(add_paimon_lib LIB_NAME) target_include_directories(${LIB_NAME}_shared PRIVATE ${ARG_PRIVATE_INCLUDES}) endif() + set_property(TARGET ${LIB_NAME}_shared PROPERTY PAIMON_INTERNAL_LIBRARY TRUE) set_target_properties(${LIB_NAME}_shared PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}" @@ -158,6 +172,7 @@ function(add_paimon_lib LIB_NAME) set(LIB_NAME_STATIC ${LIB_NAME}) + set_property(TARGET ${LIB_NAME}_static PROPERTY PAIMON_INTERNAL_LIBRARY TRUE) set_target_properties(${LIB_NAME}_static PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}"