diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f09d1596..228b916c3 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 @@ -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 eff93320f..612903b94 100644 --- a/README.md +++ b/README.md @@ -140,6 +140,65 @@ $ 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. + +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 \ + -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 +``` + +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, +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..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,14 +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}) 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 $) @@ -103,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}" @@ -157,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}" diff --git a/cmake_modules/DefineOptions.cmake b/cmake_modules/DefineOptions.cmake index 9fa3629e2..587b50a1f 100644 --- a/cmake_modules/DefineOptions.cmake +++ b/cmake_modules/DefineOptions.cmake @@ -138,6 +138,107 @@ 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) + + 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) + define_option_string(zstd_SOURCE + "Dependency source for zstd" + "" + 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 + SYSTEM) + define_option_string(ZLIB_SOURCE + "Dependency source for ZLIB" + "" + AUTO + BUNDLED + SYSTEM) + define_option_string(RE2_SOURCE + "Dependency source for RE2" + "" + 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 + 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) endif() macro(validate_config) diff --git a/cmake_modules/FindArrowAlt.cmake b/cmake_modules/FindArrowAlt.cmake new file mode 100644 index 000000000..dd4b4860a --- /dev/null +++ b/cmake_modules/FindArrowAlt.cmake @@ -0,0 +1,87 @@ +# 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/FindAvroAlt.cmake b/cmake_modules/FindAvroAlt.cmake new file mode 100644 index 000000000..104b6f155 --- /dev/null +++ b/cmake_modules/FindAvroAlt.cmake @@ -0,0 +1,42 @@ +# 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..074bceeae --- /dev/null +++ b/cmake_modules/FindGTestAlt.cmake @@ -0,0 +1,68 @@ +# 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/FindLZ4Alt.cmake b/cmake_modules/FindLZ4Alt.cmake new file mode 100644 index 000000000..929576c2a --- /dev/null +++ b/cmake_modules/FindLZ4Alt.cmake @@ -0,0 +1,66 @@ +# 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/FindORCAlt.cmake b/cmake_modules/FindORCAlt.cmake new file mode 100644 index 000000000..16c5f7bad --- /dev/null +++ b/cmake_modules/FindORCAlt.cmake @@ -0,0 +1,81 @@ +# 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..42cc2de05 --- /dev/null +++ b/cmake_modules/FindProtobufAlt.cmake @@ -0,0 +1,143 @@ +# 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/FindRE2Alt.cmake b/cmake_modules/FindRE2Alt.cmake new file mode 100644 index 000000000..ceb84b810 --- /dev/null +++ b/cmake_modules/FindRE2Alt.cmake @@ -0,0 +1,46 @@ +# 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/FindRapidJSONAlt.cmake b/cmake_modules/FindRapidJSONAlt.cmake new file mode 100644 index 000000000..c68a9a170 --- /dev/null +++ b/cmake_modules/FindRapidJSONAlt.cmake @@ -0,0 +1,45 @@ +# 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/FindSnappyAlt.cmake b/cmake_modules/FindSnappyAlt.cmake new file mode 100644 index 000000000..81336dea1 --- /dev/null +++ b/cmake_modules/FindSnappyAlt.cmake @@ -0,0 +1,66 @@ +# 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/FindTBBAlt.cmake b/cmake_modules/FindTBBAlt.cmake new file mode 100644 index 000000000..406436f73 --- /dev/null +++ b/cmake_modules/FindTBBAlt.cmake @@ -0,0 +1,63 @@ +# 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/FindZLIBAlt.cmake b/cmake_modules/FindZLIBAlt.cmake new file mode 100644 index 000000000..3ee283ebb --- /dev/null +++ b/cmake_modules/FindZLIBAlt.cmake @@ -0,0 +1,54 @@ +# 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/FindfmtAlt.cmake b/cmake_modules/FindfmtAlt.cmake new file mode 100644 index 000000000..2c3586d37 --- /dev/null +++ b/cmake_modules/FindfmtAlt.cmake @@ -0,0 +1,65 @@ +# 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..db26c83c1 --- /dev/null +++ b/cmake_modules/FindglogAlt.cmake @@ -0,0 +1,69 @@ +# 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/FindzstdAlt.cmake b/cmake_modules/FindzstdAlt.cmake new file mode 100644 index 000000000..db4baa906 --- /dev/null +++ b/cmake_modules/FindzstdAlt.cmake @@ -0,0 +1,74 @@ +# 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..5b88873cb 100644 --- a/cmake_modules/ThirdpartyToolchain.cmake +++ b/cmake_modules/ThirdpartyToolchain.cmake @@ -371,6 +371,323 @@ 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) + +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.") + 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") + 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() + + if(PAIMON_ENABLE_ORC) + paimon_get_dependency_source(ORC _orc_source) + 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") + 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) + set(_root_var "${DEPENDENCY_NAME}_ROOT") + + 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() + +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) + 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() + + 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() + 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") + build_snappy() + elseif("${DEPENDENCY_NAME}" STREQUAL "LZ4") + build_lz4() + elseif("${DEPENDENCY_NAME}" STREQUAL "ZLIB") + build_zlib() + elseif("${DEPENDENCY_NAME}" STREQUAL "RE2") + build_re2() + elseif("${DEPENDENCY_NAME}" STREQUAL "Protobuf") + 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() +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) + paimon_get_dependency_compat_target(${DEPENDENCY_NAME} _paimon_target_name) + + 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}") + 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) + if(${_paimon_found_var}) + message(STATUS "Using system ${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} " + "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) + unset(_paimon_target_name) +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 " + "and BUNDLED dependencies can cause ABI conflicts.") + endif() + endforeach() +endfunction() + macro(build_lucene) message(STATUS "Building lucene from source") @@ -484,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() @@ -1438,23 +1755,25 @@ macro(build_glog) endif() endmacro() -build_fmt() -build_rapidjson() -build_re2() -build_snappy() -build_zstd() -build_zlib() -build_lz4() -build_arrow() -build_tbb() -build_glog() +resolve_dependency(fmt) +resolve_dependency(RapidJSON) +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() +resolve_dependency(TBB) +resolve_dependency(glog) if(PAIMON_ENABLE_AVRO) - build_avro() + resolve_dependency(Avro) endif() if(PAIMON_ENABLE_ORC) - build_protobuf() - build_orc() + resolve_dependency(Protobuf) + resolve_dependency(ORC) endif() if(PAIMON_ENABLE_JINDO) build_jindosdk_c() 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 ~~~~~~~~~~~~~~~~ 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()