diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
commit | e6918187568dbd01842d8d1d2c808ce16a894239 (patch) | |
tree | 64f88b554b444a49f656b6c656111a145cbbaa28 /src/arrow/cpp/cmake_modules | |
parent | Initial commit. (diff) | |
download | ceph-e6918187568dbd01842d8d1d2c808ce16a894239.tar.xz ceph-e6918187568dbd01842d8d1d2c808ce16a894239.zip |
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/arrow/cpp/cmake_modules')
40 files changed, 10203 insertions, 0 deletions
diff --git a/src/arrow/cpp/cmake_modules/BuildUtils.cmake b/src/arrow/cpp/cmake_modules/BuildUtils.cmake new file mode 100644 index 000000000..cd8290d1b --- /dev/null +++ b/src/arrow/cpp/cmake_modules/BuildUtils.cmake @@ -0,0 +1,936 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Common path suffixes to be searched by find_library or find_path. +# Windows artifacts may be found under "<root>/Library", so +# search there as well. +set(ARROW_LIBRARY_PATH_SUFFIXES + "${CMAKE_LIBRARY_ARCHITECTURE}" + "lib/${CMAKE_LIBRARY_ARCHITECTURE}" + "lib64" + "lib32" + "lib" + "bin" + "Library" + "Library/lib" + "Library/bin") +set(ARROW_INCLUDE_PATH_SUFFIXES "include" "Library" "Library/include") + +set(ARROW_BOOST_PROCESS_COMPILE_DEFINITIONS) +if(WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # boost/process/detail/windows/handle_workaround.hpp doesn't work + # without BOOST_USE_WINDOWS_H with MinGW because MinGW doesn't + # provide __kernel_entry without winternl.h. + # + # See also: + # https://github.com/boostorg/process/blob/develop/include/boost/process/detail/windows/handle_workaround.hpp + # + # You can use this like the following: + # + # target_compile_definitions(target PRIVATE + # ${ARROW_BOOST_PROCESS_COMPILE_DEFINITIONS}) + list(APPEND ARROW_BOOST_PROCESS_COMPILE_DEFINITIONS "BOOST_USE_WINDOWS_H=1") +endif() + +function(ADD_THIRDPARTY_LIB LIB_NAME) + set(options) + set(one_value_args SHARED_LIB STATIC_LIB) + set(multi_value_args DEPS INCLUDE_DIRECTORIES) + cmake_parse_arguments(ARG + "${options}" + "${one_value_args}" + "${multi_value_args}" + ${ARGN}) + if(ARG_UNPARSED_ARGUMENTS) + message(SEND_ERROR "Error: unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}") + endif() + + if(ARG_STATIC_LIB AND ARG_SHARED_LIB) + set(AUG_LIB_NAME "${LIB_NAME}_static") + add_library(${AUG_LIB_NAME} STATIC IMPORTED) + set_target_properties(${AUG_LIB_NAME} PROPERTIES IMPORTED_LOCATION + "${ARG_STATIC_LIB}") + if(ARG_DEPS) + set_target_properties(${AUG_LIB_NAME} PROPERTIES INTERFACE_LINK_LIBRARIES + "${ARG_DEPS}") + endif() + message(STATUS "Added static library dependency ${AUG_LIB_NAME}: ${ARG_STATIC_LIB}") + if(ARG_INCLUDE_DIRECTORIES) + set_target_properties(${AUG_LIB_NAME} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${ARG_INCLUDE_DIRECTORIES}") + endif() + + set(AUG_LIB_NAME "${LIB_NAME}_shared") + add_library(${AUG_LIB_NAME} SHARED IMPORTED) + + if(WIN32) + # Mark the ".lib" location as part of a Windows DLL + set_target_properties(${AUG_LIB_NAME} PROPERTIES IMPORTED_IMPLIB + "${ARG_SHARED_LIB}") + else() + set_target_properties(${AUG_LIB_NAME} PROPERTIES IMPORTED_LOCATION + "${ARG_SHARED_LIB}") + endif() + if(ARG_DEPS) + set_target_properties(${AUG_LIB_NAME} PROPERTIES INTERFACE_LINK_LIBRARIES + "${ARG_DEPS}") + endif() + message(STATUS "Added shared library dependency ${AUG_LIB_NAME}: ${ARG_SHARED_LIB}") + if(ARG_INCLUDE_DIRECTORIES) + set_target_properties(${AUG_LIB_NAME} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${ARG_INCLUDE_DIRECTORIES}") + endif() + elseif(ARG_STATIC_LIB) + set(AUG_LIB_NAME "${LIB_NAME}_static") + add_library(${AUG_LIB_NAME} STATIC IMPORTED) + set_target_properties(${AUG_LIB_NAME} PROPERTIES IMPORTED_LOCATION + "${ARG_STATIC_LIB}") + if(ARG_DEPS) + set_target_properties(${AUG_LIB_NAME} PROPERTIES INTERFACE_LINK_LIBRARIES + "${ARG_DEPS}") + endif() + message(STATUS "Added static library dependency ${AUG_LIB_NAME}: ${ARG_STATIC_LIB}") + if(ARG_INCLUDE_DIRECTORIES) + set_target_properties(${AUG_LIB_NAME} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${ARG_INCLUDE_DIRECTORIES}") + endif() + elseif(ARG_SHARED_LIB) + set(AUG_LIB_NAME "${LIB_NAME}_shared") + add_library(${AUG_LIB_NAME} SHARED IMPORTED) + + if(WIN32) + # Mark the ".lib" location as part of a Windows DLL + set_target_properties(${AUG_LIB_NAME} PROPERTIES IMPORTED_IMPLIB + "${ARG_SHARED_LIB}") + else() + set_target_properties(${AUG_LIB_NAME} PROPERTIES IMPORTED_LOCATION + "${ARG_SHARED_LIB}") + endif() + message(STATUS "Added shared library dependency ${AUG_LIB_NAME}: ${ARG_SHARED_LIB}") + if(ARG_DEPS) + set_target_properties(${AUG_LIB_NAME} PROPERTIES INTERFACE_LINK_LIBRARIES + "${ARG_DEPS}") + endif() + if(ARG_INCLUDE_DIRECTORIES) + set_target_properties(${AUG_LIB_NAME} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${ARG_INCLUDE_DIRECTORIES}") + endif() + else() + message(FATAL_ERROR "No static or shared library provided for ${LIB_NAME}") + endif() +endfunction() + +function(REUSE_PRECOMPILED_HEADER_LIB TARGET_NAME LIB_NAME) + if(ARROW_USE_PRECOMPILED_HEADERS) + target_precompile_headers(${TARGET_NAME} REUSE_FROM ${LIB_NAME}) + endif() +endfunction() + +# Based on MIT-licensed +# https://gist.github.com/cristianadam/ef920342939a89fae3e8a85ca9459b49 +function(create_merged_static_lib output_target) + set(options) + set(one_value_args NAME ROOT) + set(multi_value_args TO_MERGE) + cmake_parse_arguments(ARG + "${options}" + "${one_value_args}" + "${multi_value_args}" + ${ARGN}) + if(ARG_UNPARSED_ARGUMENTS) + message(SEND_ERROR "Error: unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}") + endif() + + set(output_lib_path + ${BUILD_OUTPUT_ROOT_DIRECTORY}${CMAKE_STATIC_LIBRARY_PREFIX}${ARG_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX} + ) + + set(all_library_paths $<TARGET_FILE:${ARG_ROOT}>) + foreach(lib ${ARG_TO_MERGE}) + list(APPEND all_library_paths $<TARGET_FILE:${lib}>) + endforeach() + + if(APPLE) + set(BUNDLE_COMMAND "libtool" "-no_warning_for_no_symbols" "-static" "-o" + ${output_lib_path} ${all_library_paths}) + elseif(CMAKE_CXX_COMPILER_ID MATCHES "^(Clang|GNU|Intel)$") + set(ar_script_path ${CMAKE_BINARY_DIR}/${ARG_NAME}.ar) + + file(WRITE ${ar_script_path}.in "CREATE ${output_lib_path}\n") + file(APPEND ${ar_script_path}.in "ADDLIB $<TARGET_FILE:${ARG_ROOT}>\n") + + foreach(lib ${ARG_TO_MERGE}) + file(APPEND ${ar_script_path}.in "ADDLIB $<TARGET_FILE:${lib}>\n") + endforeach() + + file(APPEND ${ar_script_path}.in "SAVE\nEND\n") + file(GENERATE + OUTPUT ${ar_script_path} + INPUT ${ar_script_path}.in) + set(ar_tool ${CMAKE_AR}) + + if(CMAKE_INTERPROCEDURAL_OPTIMIZATION) + set(ar_tool ${CMAKE_CXX_COMPILER_AR}) + endif() + + set(BUNDLE_COMMAND ${ar_tool} -M < ${ar_script_path}) + + elseif(MSVC) + if(NOT CMAKE_LIBTOOL) + find_program(lib_tool lib HINTS "${CMAKE_CXX_COMPILER}/..") + if("${lib_tool}" STREQUAL "lib_tool-NOTFOUND") + message(FATAL_ERROR "Cannot locate libtool to bundle libraries") + endif() + else() + set(${lib_tool} ${CMAKE_LIBTOOL}) + endif() + set(BUNDLE_TOOL ${lib_tool}) + set(BUNDLE_COMMAND ${BUNDLE_TOOL} /NOLOGO /OUT:${output_lib_path} + ${all_library_paths}) + else() + message(FATAL_ERROR "Unknown bundle scenario!") + endif() + + add_custom_command(COMMAND ${BUNDLE_COMMAND} + OUTPUT ${output_lib_path} + COMMENT "Bundling ${output_lib_path}" + VERBATIM) + + message(STATUS "Creating bundled static library target ${output_target} at ${output_lib_path}" + ) + + add_custom_target(${output_target} ALL DEPENDS ${output_lib_path}) + add_dependencies(${output_target} ${ARG_ROOT} ${ARG_TO_MERGE}) + install(FILES ${output_lib_path} DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endfunction() + +# \arg OUTPUTS list to append built targets to +function(ADD_ARROW_LIB LIB_NAME) + set(options) + set(one_value_args + BUILD_SHARED + BUILD_STATIC + CMAKE_PACKAGE_NAME + PKG_CONFIG_NAME + SHARED_LINK_FLAGS + PRECOMPILED_HEADER_LIB) + set(multi_value_args + SOURCES + PRECOMPILED_HEADERS + OUTPUTS + STATIC_LINK_LIBS + SHARED_LINK_LIBS + SHARED_PRIVATE_LINK_LIBS + EXTRA_INCLUDES + PRIVATE_INCLUDES + DEPENDENCIES + SHARED_INSTALL_INTERFACE_LIBS + STATIC_INSTALL_INTERFACE_LIBS + OUTPUT_PATH) + cmake_parse_arguments(ARG + "${options}" + "${one_value_args}" + "${multi_value_args}" + ${ARGN}) + if(ARG_UNPARSED_ARGUMENTS) + message(SEND_ERROR "Error: unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}") + endif() + + if(ARG_OUTPUTS) + set(${ARG_OUTPUTS}) + endif() + + # Allow overriding ARROW_BUILD_SHARED and ARROW_BUILD_STATIC + if(DEFINED ARG_BUILD_SHARED) + set(BUILD_SHARED ${ARG_BUILD_SHARED}) + else() + set(BUILD_SHARED ${ARROW_BUILD_SHARED}) + endif() + if(DEFINED ARG_BUILD_STATIC) + set(BUILD_STATIC ${ARG_BUILD_STATIC}) + else() + set(BUILD_STATIC ${ARROW_BUILD_STATIC}) + endif() + if(ARG_OUTPUT_PATH) + set(OUTPUT_PATH ${ARG_OUTPUT_PATH}) + else() + set(OUTPUT_PATH ${BUILD_OUTPUT_ROOT_DIRECTORY}) + endif() + + if(WIN32 OR (CMAKE_GENERATOR STREQUAL Xcode)) + # We need to compile C++ separately for each library kind (shared and static) + # because of dllexport declarations on Windows. + # The Xcode generator doesn't reliably work with Xcode as target names are not + # guessed correctly. + set(USE_OBJLIB OFF) + else() + set(USE_OBJLIB ON) + endif() + + if(USE_OBJLIB) + # 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}) + # 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) + add_dependencies(${LIB_NAME}_objlib ${ARG_DEPENDENCIES}) + endif() + if(ARG_PRECOMPILED_HEADER_LIB) + reuse_precompiled_header_lib(${LIB_NAME}_objlib ${ARG_PRECOMPILED_HEADER_LIB}) + endif() + if(ARG_PRECOMPILED_HEADERS AND ARROW_USE_PRECOMPILED_HEADERS) + target_precompile_headers(${LIB_NAME}_objlib PRIVATE ${ARG_PRECOMPILED_HEADERS}) + endif() + set(LIB_DEPS $<TARGET_OBJECTS:${LIB_NAME}_objlib>) + set(LIB_INCLUDES) + set(EXTRA_DEPS) + + if(ARG_OUTPUTS) + list(APPEND ${ARG_OUTPUTS} ${LIB_NAME}_objlib) + endif() + + if(ARG_EXTRA_INCLUDES) + target_include_directories(${LIB_NAME}_objlib SYSTEM PUBLIC ${ARG_EXTRA_INCLUDES}) + endif() + if(ARG_PRIVATE_INCLUDES) + target_include_directories(${LIB_NAME}_objlib PRIVATE ${ARG_PRIVATE_INCLUDES}) + endif() + else() + # Prepare arguments for separate compilation of static and shared libs below + # TODO: add PCH directives + set(LIB_DEPS ${ARG_SOURCES}) + set(EXTRA_DEPS ${ARG_DEPENDENCIES}) + + if(ARG_EXTRA_INCLUDES) + set(LIB_INCLUDES ${ARG_EXTRA_INCLUDES}) + endif() + endif() + + set(RUNTIME_INSTALL_DIR bin) + + if(BUILD_SHARED) + add_library(${LIB_NAME}_shared SHARED ${LIB_DEPS}) + if(EXTRA_DEPS) + add_dependencies(${LIB_NAME}_shared ${EXTRA_DEPS}) + endif() + + if(ARG_PRECOMPILED_HEADER_LIB) + reuse_precompiled_header_lib(${LIB_NAME}_shared ${ARG_PRECOMPILED_HEADER_LIB}) + endif() + + if(ARG_OUTPUTS) + list(APPEND ${ARG_OUTPUTS} ${LIB_NAME}_shared) + endif() + + if(LIB_INCLUDES) + target_include_directories(${LIB_NAME}_shared SYSTEM PUBLIC ${ARG_EXTRA_INCLUDES}) + endif() + + if(ARG_PRIVATE_INCLUDES) + target_include_directories(${LIB_NAME}_shared PRIVATE ${ARG_PRIVATE_INCLUDES}) + endif() + + # On iOS, specifying -undefined conflicts with enabling bitcode + if(APPLE + AND NOT IOS + AND NOT DEFINED ENV{EMSCRIPTEN}) + # On OS X, you can avoid linking at library load time and instead + # expecting that the symbols have been loaded separately. This happens + # with libpython* where there can be conflicts between system Python and + # the Python from a thirdparty distribution + # + # When running with the Emscripten Compiler, we need not worry about + # python, and the Emscripten Compiler does not support this option. + set(ARG_SHARED_LINK_FLAGS "-undefined dynamic_lookup ${ARG_SHARED_LINK_FLAGS}") + endif() + + set_target_properties(${LIB_NAME}_shared + PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${OUTPUT_PATH}" + RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_PATH}" + PDB_OUTPUT_DIRECTORY "${OUTPUT_PATH}" + LINK_FLAGS "${ARG_SHARED_LINK_FLAGS}" + OUTPUT_NAME ${LIB_NAME} + VERSION "${ARROW_FULL_SO_VERSION}" + SOVERSION "${ARROW_SO_VERSION}") + + target_link_libraries(${LIB_NAME}_shared + LINK_PUBLIC + "$<BUILD_INTERFACE:${ARG_SHARED_LINK_LIBS}>" + "$<INSTALL_INTERFACE:${ARG_SHARED_INSTALL_INTERFACE_LIBS}>" + LINK_PRIVATE + ${ARG_SHARED_PRIVATE_LINK_LIBS}) + + if(ARROW_RPATH_ORIGIN) + if(APPLE) + set(_lib_install_rpath "@loader_path") + else() + set(_lib_install_rpath "\$ORIGIN") + endif() + set_target_properties(${LIB_NAME}_shared PROPERTIES INSTALL_RPATH + ${_lib_install_rpath}) + endif() + + if(APPLE) + if(ARROW_INSTALL_NAME_RPATH) + set(_lib_install_name "@rpath") + else() + set(_lib_install_name "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") + endif() + set_target_properties(${LIB_NAME}_shared + PROPERTIES BUILD_WITH_INSTALL_RPATH ON INSTALL_NAME_DIR + "${_lib_install_name}") + endif() + + install(TARGETS ${LIB_NAME}_shared ${INSTALL_IS_OPTIONAL} + EXPORT ${LIB_NAME}_targets + RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + endif() + + if(BUILD_STATIC) + add_library(${LIB_NAME}_static STATIC ${LIB_DEPS}) + if(EXTRA_DEPS) + add_dependencies(${LIB_NAME}_static ${EXTRA_DEPS}) + endif() + + if(ARG_PRECOMPILED_HEADER_LIB) + reuse_precompiled_header_lib(${LIB_NAME}_static ${ARG_PRECOMPILED_HEADER_LIB}) + endif() + + if(ARG_OUTPUTS) + list(APPEND ${ARG_OUTPUTS} ${LIB_NAME}_static) + endif() + + if(LIB_INCLUDES) + target_include_directories(${LIB_NAME}_static SYSTEM PUBLIC ${ARG_EXTRA_INCLUDES}) + endif() + + if(ARG_PRIVATE_INCLUDES) + target_include_directories(${LIB_NAME}_static PRIVATE ${ARG_PRIVATE_INCLUDES}) + endif() + + if(MSVC_TOOLCHAIN) + set(LIB_NAME_STATIC ${LIB_NAME}_static) + else() + set(LIB_NAME_STATIC ${LIB_NAME}) + endif() + + if(ARROW_BUILD_STATIC AND WIN32) + target_compile_definitions(${LIB_NAME}_static PUBLIC ARROW_STATIC) + endif() + + set_target_properties(${LIB_NAME}_static + PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${OUTPUT_PATH}" + OUTPUT_NAME ${LIB_NAME_STATIC}) + + if(ARG_STATIC_INSTALL_INTERFACE_LIBS) + target_link_libraries(${LIB_NAME}_static LINK_PUBLIC + "$<INSTALL_INTERFACE:${ARG_STATIC_INSTALL_INTERFACE_LIBS}>") + endif() + + if(ARG_STATIC_LINK_LIBS) + target_link_libraries(${LIB_NAME}_static LINK_PRIVATE + "$<BUILD_INTERFACE:${ARG_STATIC_LINK_LIBS}>") + endif() + + install(TARGETS ${LIB_NAME}_static ${INSTALL_IS_OPTIONAL} + EXPORT ${LIB_NAME}_targets + RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + endif() + + if(ARG_CMAKE_PACKAGE_NAME) + arrow_install_cmake_find_module("${ARG_CMAKE_PACKAGE_NAME}") + + set(TARGETS_CMAKE "${ARG_CMAKE_PACKAGE_NAME}Targets.cmake") + install(EXPORT ${LIB_NAME}_targets + FILE "${TARGETS_CMAKE}" + DESTINATION "${ARROW_CMAKE_INSTALL_DIR}") + + set(CONFIG_CMAKE "${ARG_CMAKE_PACKAGE_NAME}Config.cmake") + set(BUILT_CONFIG_CMAKE "${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_CMAKE}") + configure_package_config_file("${CONFIG_CMAKE}.in" "${BUILT_CONFIG_CMAKE}" + INSTALL_DESTINATION "${ARROW_CMAKE_INSTALL_DIR}") + install(FILES "${BUILT_CONFIG_CMAKE}" DESTINATION "${ARROW_CMAKE_INSTALL_DIR}") + + set(CONFIG_VERSION_CMAKE "${ARG_CMAKE_PACKAGE_NAME}ConfigVersion.cmake") + set(BUILT_CONFIG_VERSION_CMAKE "${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_VERSION_CMAKE}") + write_basic_package_version_file( + "${BUILT_CONFIG_VERSION_CMAKE}" + VERSION ${${PROJECT_NAME}_VERSION} + COMPATIBILITY AnyNewerVersion) + install(FILES "${BUILT_CONFIG_VERSION_CMAKE}" + DESTINATION "${ARROW_CMAKE_INSTALL_DIR}") + endif() + + if(ARG_PKG_CONFIG_NAME) + arrow_add_pkg_config("${ARG_PKG_CONFIG_NAME}") + endif() + + # Modify variable in calling scope + if(ARG_OUTPUTS) + set(${ARG_OUTPUTS} + ${${ARG_OUTPUTS}} + PARENT_SCOPE) + endif() +endfunction() + +# +# Benchmarking +# +# Add a new micro benchmark, with or without an executable that should be built. +# If benchmarks are enabled then they will be run along side unit tests with ctest. +# 'make benchmark' and 'make unittest' to build/run only benchmark or unittests, +# respectively. +# +# REL_BENCHMARK_NAME is the name of the benchmark app. It may be a single component +# (e.g. monotime-benchmark) or contain additional components (e.g. +# net/net_util-benchmark). Either way, the last component must be a globally +# unique name. + +# The benchmark will registered as unit test with ctest with a label +# of 'benchmark'. +# +# Arguments after the test name will be passed to set_tests_properties(). +# +# \arg PREFIX a string to append to the name of the benchmark executable. For +# example, if you have src/arrow/foo/bar-benchmark.cc, then PREFIX "foo" will +# create test executable foo-bar-benchmark +# \arg LABELS the benchmark label or labels to assign the unit tests to. By +# default, benchmarks will go in the "benchmark" group. Custom targets for the +# group names must exist +function(ADD_BENCHMARK REL_BENCHMARK_NAME) + set(options) + set(one_value_args) + set(multi_value_args + EXTRA_LINK_LIBS + STATIC_LINK_LIBS + DEPENDENCIES + PREFIX + LABELS) + cmake_parse_arguments(ARG + "${options}" + "${one_value_args}" + "${multi_value_args}" + ${ARGN}) + if(ARG_UNPARSED_ARGUMENTS) + message(SEND_ERROR "Error: unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}") + endif() + + if(NO_BENCHMARKS) + return() + endif() + get_filename_component(BENCHMARK_NAME ${REL_BENCHMARK_NAME} NAME_WE) + + if(ARG_PREFIX) + set(BENCHMARK_NAME "${ARG_PREFIX}-${BENCHMARK_NAME}") + endif() + + # Make sure the executable name contains only hyphens, not underscores + string(REPLACE "_" "-" BENCHMARK_NAME ${BENCHMARK_NAME}) + + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${REL_BENCHMARK_NAME}.cc) + # This benchmark has a corresponding .cc file, set it up as an executable. + set(BENCHMARK_PATH "${EXECUTABLE_OUTPUT_PATH}/${BENCHMARK_NAME}") + add_executable(${BENCHMARK_NAME} "${REL_BENCHMARK_NAME}.cc") + + if(ARG_STATIC_LINK_LIBS) + # Customize link libraries + target_link_libraries(${BENCHMARK_NAME} PRIVATE ${ARG_STATIC_LINK_LIBS}) + else() + target_link_libraries(${BENCHMARK_NAME} PRIVATE ${ARROW_BENCHMARK_LINK_LIBS}) + endif() + add_dependencies(benchmark ${BENCHMARK_NAME}) + set(NO_COLOR "--color_print=false") + + if(ARG_EXTRA_LINK_LIBS) + target_link_libraries(${BENCHMARK_NAME} PRIVATE ${ARG_EXTRA_LINK_LIBS}) + endif() + else() + # No executable, just invoke the benchmark (probably a script) directly. + set(BENCHMARK_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${REL_BENCHMARK_NAME}) + set(NO_COLOR "") + endif() + + # With OSX and conda, we need to set the correct RPATH so that dependencies + # are found. The installed libraries with conda have an RPATH that matches + # for executables and libraries lying in $ENV{CONDA_PREFIX}/bin or + # $ENV{CONDA_PREFIX}/lib but our test libraries and executables are not + # installed there. + if(NOT "$ENV{CONDA_PREFIX}" STREQUAL "" AND APPLE) + set_target_properties(${BENCHMARK_NAME} + PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE + INSTALL_RPATH_USE_LINK_PATH TRUE + INSTALL_RPATH + "$ENV{CONDA_PREFIX}/lib;${EXECUTABLE_OUTPUT_PATH}") + endif() + + # Add test as dependency of relevant label targets + add_dependencies(all-benchmarks ${BENCHMARK_NAME}) + foreach(TARGET ${ARG_LABELS}) + add_dependencies(${TARGET} ${BENCHMARK_NAME}) + endforeach() + + if(ARG_DEPENDENCIES) + add_dependencies(${BENCHMARK_NAME} ${ARG_DEPENDENCIES}) + endif() + + if(ARG_LABELS) + set(ARG_LABELS "benchmark;${ARG_LABELS}") + else() + set(ARG_LABELS benchmark) + endif() + + add_test(${BENCHMARK_NAME} + ${BUILD_SUPPORT_DIR}/run-test.sh + ${CMAKE_BINARY_DIR} + benchmark + ${BENCHMARK_PATH} + ${NO_COLOR}) + set_property(TEST ${BENCHMARK_NAME} + APPEND + PROPERTY LABELS ${ARG_LABELS}) +endfunction() + +# +# Testing +# +# Add a new test case, with or without an executable that should be built. +# +# REL_TEST_NAME is the name of the test. It may be a single component +# (e.g. monotime-test) or contain additional components (e.g. +# net/net_util-test). Either way, the last component must be a globally +# unique name. +# +# If given, SOURCES is the list of C++ source files to compile into the test +# executable. Otherwise, "REL_TEST_NAME.cc" is used. +# +# The unit test is added with a label of "unittest" to support filtering with +# ctest. +# +# Arguments after the test name will be passed to set_tests_properties(). +# +# \arg ENABLED if passed, add this unit test even if ARROW_BUILD_TESTS is off +# \arg PREFIX a string to append to the name of the test executable. For +# example, if you have src/arrow/foo/bar-test.cc, then PREFIX "foo" will create +# test executable foo-bar-test +# \arg LABELS the unit test label or labels to assign the unit tests +# to. By default, unit tests will go in the "unittest" group, but if we have +# multiple unit tests in some subgroup, you can assign a test to multiple +# groups use the syntax unittest;GROUP2;GROUP3. Custom targets for the group +# names must exist +function(ADD_TEST_CASE REL_TEST_NAME) + set(options NO_VALGRIND ENABLED) + set(one_value_args PRECOMPILED_HEADER_LIB) + set(multi_value_args + SOURCES + PRECOMPILED_HEADERS + STATIC_LINK_LIBS + EXTRA_LINK_LIBS + EXTRA_INCLUDES + EXTRA_DEPENDENCIES + LABELS + EXTRA_LABELS + PREFIX) + cmake_parse_arguments(ARG + "${options}" + "${one_value_args}" + "${multi_value_args}" + ${ARGN}) + if(ARG_UNPARSED_ARGUMENTS) + message(SEND_ERROR "Error: unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}") + endif() + + if(NO_TESTS AND NOT ARG_ENABLED) + return() + endif() + get_filename_component(TEST_NAME ${REL_TEST_NAME} NAME_WE) + + if(ARG_PREFIX) + set(TEST_NAME "${ARG_PREFIX}-${TEST_NAME}") + endif() + + if(ARG_SOURCES) + set(SOURCES ${ARG_SOURCES}) + else() + set(SOURCES "${REL_TEST_NAME}.cc") + endif() + + # Make sure the executable name contains only hyphens, not underscores + string(REPLACE "_" "-" TEST_NAME ${TEST_NAME}) + + set(TEST_PATH "${EXECUTABLE_OUTPUT_PATH}/${TEST_NAME}") + add_executable(${TEST_NAME} ${SOURCES}) + + # With OSX and conda, we need to set the correct RPATH so that dependencies + # are found. The installed libraries with conda have an RPATH that matches + # for executables and libraries lying in $ENV{CONDA_PREFIX}/bin or + # $ENV{CONDA_PREFIX}/lib but our test libraries and executables are not + # installed there. + if(NOT "$ENV{CONDA_PREFIX}" STREQUAL "" AND APPLE) + set_target_properties(${TEST_NAME} + PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE + INSTALL_RPATH_USE_LINK_PATH TRUE + INSTALL_RPATH + "${EXECUTABLE_OUTPUT_PATH};$ENV{CONDA_PREFIX}/lib") + endif() + + if(ARG_STATIC_LINK_LIBS) + # Customize link libraries + target_link_libraries(${TEST_NAME} PRIVATE ${ARG_STATIC_LINK_LIBS}) + else() + target_link_libraries(${TEST_NAME} PRIVATE ${ARROW_TEST_LINK_LIBS}) + endif() + + if(ARG_PRECOMPILED_HEADER_LIB) + reuse_precompiled_header_lib(${TEST_NAME} ${ARG_PRECOMPILED_HEADER_LIB}) + endif() + + if(ARG_PRECOMPILED_HEADERS AND ARROW_USE_PRECOMPILED_HEADERS) + target_precompile_headers(${TEST_NAME} PRIVATE ${ARG_PRECOMPILED_HEADERS}) + endif() + + if(ARG_EXTRA_LINK_LIBS) + target_link_libraries(${TEST_NAME} PRIVATE ${ARG_EXTRA_LINK_LIBS}) + endif() + + if(ARG_EXTRA_INCLUDES) + target_include_directories(${TEST_NAME} SYSTEM PUBLIC ${ARG_EXTRA_INCLUDES}) + endif() + + if(ARG_EXTRA_DEPENDENCIES) + add_dependencies(${TEST_NAME} ${ARG_EXTRA_DEPENDENCIES}) + endif() + + if(ARROW_TEST_MEMCHECK AND NOT ARG_NO_VALGRIND) + add_test(${TEST_NAME} + bash + -c + "cd '${CMAKE_SOURCE_DIR}'; \ + valgrind --suppressions=valgrind.supp --tool=memcheck --gen-suppressions=all \ + --num-callers=500 --leak-check=full --leak-check-heuristics=stdstring \ + --error-exitcode=1 ${TEST_PATH}") + elseif(WIN32) + add_test(${TEST_NAME} ${TEST_PATH}) + else() + add_test(${TEST_NAME} + ${BUILD_SUPPORT_DIR}/run-test.sh + ${CMAKE_BINARY_DIR} + test + ${TEST_PATH}) + endif() + + # Add test as dependency of relevant targets + add_dependencies(all-tests ${TEST_NAME}) + foreach(TARGET ${ARG_LABELS}) + add_dependencies(${TARGET} ${TEST_NAME}) + endforeach() + + set(LABELS) + list(APPEND LABELS "unittest") + if(ARG_LABELS) + list(APPEND LABELS ${ARG_LABELS}) + endif() + # EXTRA_LABELS don't create their own dependencies, they are only used + # to ease running certain test categories. + if(ARG_EXTRA_LABELS) + list(APPEND LABELS ${ARG_EXTRA_LABELS}) + endif() + + foreach(LABEL ${ARG_LABELS}) + # ensure there is a cmake target which exercises tests with this LABEL + set(LABEL_TEST_NAME "test-${LABEL}") + if(NOT TARGET ${LABEL_TEST_NAME}) + add_custom_target(${LABEL_TEST_NAME} + ctest -L "${LABEL}" --output-on-failure + USES_TERMINAL) + endif() + # ensure the test is (re)built before the LABEL test runs + add_dependencies(${LABEL_TEST_NAME} ${TEST_NAME}) + endforeach() + + set_property(TEST ${TEST_NAME} + APPEND + PROPERTY LABELS ${LABELS}) +endfunction() + +# +# Examples +# +# Add a new example, with or without an executable that should be built. +# If examples are enabled then they will be run along side unit tests with ctest. +# 'make runexample' to build/run only examples. +# +# REL_EXAMPLE_NAME is the name of the example app. It may be a single component +# (e.g. monotime-example) or contain additional components (e.g. +# net/net_util-example). Either way, the last component must be a globally +# unique name. + +# The example will registered as unit test with ctest with a label +# of 'example'. +# +# Arguments after the test name will be passed to set_tests_properties(). +# +# \arg PREFIX a string to append to the name of the example executable. For +# example, if you have src/arrow/foo/bar-example.cc, then PREFIX "foo" will +# create test executable foo-bar-example +function(ADD_ARROW_EXAMPLE REL_EXAMPLE_NAME) + set(options) + set(one_value_args) + set(multi_value_args EXTRA_LINK_LIBS DEPENDENCIES PREFIX) + cmake_parse_arguments(ARG + "${options}" + "${one_value_args}" + "${multi_value_args}" + ${ARGN}) + if(ARG_UNPARSED_ARGUMENTS) + message(SEND_ERROR "Error: unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}") + endif() + + if(NO_EXAMPLES) + return() + endif() + get_filename_component(EXAMPLE_NAME ${REL_EXAMPLE_NAME} NAME_WE) + + if(ARG_PREFIX) + set(EXAMPLE_NAME "${ARG_PREFIX}-${EXAMPLE_NAME}") + endif() + + if(EXISTS ${CMAKE_SOURCE_DIR}/examples/arrow/${REL_EXAMPLE_NAME}.cc) + # This example has a corresponding .cc file, set it up as an executable. + set(EXAMPLE_PATH "${EXECUTABLE_OUTPUT_PATH}/${EXAMPLE_NAME}") + add_executable(${EXAMPLE_NAME} "${REL_EXAMPLE_NAME}.cc") + target_link_libraries(${EXAMPLE_NAME} ${ARROW_EXAMPLE_LINK_LIBS}) + add_dependencies(runexample ${EXAMPLE_NAME}) + set(NO_COLOR "--color_print=false") + + if(ARG_EXTRA_LINK_LIBS) + target_link_libraries(${EXAMPLE_NAME} ${ARG_EXTRA_LINK_LIBS}) + endif() + endif() + + if(ARG_DEPENDENCIES) + add_dependencies(${EXAMPLE_NAME} ${ARG_DEPENDENCIES}) + endif() + + add_test(${EXAMPLE_NAME} ${EXAMPLE_PATH}) + set_tests_properties(${EXAMPLE_NAME} PROPERTIES LABELS "example") +endfunction() + +# +# Fuzzing +# +# Add new fuzz target executable. +# +# The single source file must define a function: +# extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +# +# No main function must be present within the source file! +# +function(ADD_FUZZ_TARGET REL_FUZZING_NAME) + set(options) + set(one_value_args PREFIX) + set(multi_value_args LINK_LIBS) + cmake_parse_arguments(ARG + "${options}" + "${one_value_args}" + "${multi_value_args}" + ${ARGN}) + if(ARG_UNPARSED_ARGUMENTS) + message(SEND_ERROR "Error: unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}") + endif() + + if(NO_FUZZING) + return() + endif() + + get_filename_component(FUZZING_NAME ${REL_FUZZING_NAME} NAME_WE) + + # Make sure the executable name contains only hyphens, not underscores + string(REPLACE "_" "-" FUZZING_NAME ${FUZZING_NAME}) + + if(ARG_PREFIX) + set(FUZZING_NAME "${ARG_PREFIX}-${FUZZING_NAME}") + endif() + + # For OSS-Fuzz + # (https://google.github.io/oss-fuzz/advanced-topics/ideal-integration/) + if(DEFINED ENV{LIB_FUZZING_ENGINE}) + set(FUZZ_LDFLAGS $ENV{LIB_FUZZING_ENGINE}) + else() + set(FUZZ_LDFLAGS "-fsanitize=fuzzer") + endif() + + add_executable(${FUZZING_NAME} "${REL_FUZZING_NAME}.cc") + target_link_libraries(${FUZZING_NAME} ${LINK_LIBS}) + target_compile_options(${FUZZING_NAME} PRIVATE ${FUZZ_LDFLAGS}) + set_target_properties(${FUZZING_NAME} PROPERTIES LINK_FLAGS ${FUZZ_LDFLAGS} LABELS + "fuzzing") +endfunction() + +function(ARROW_INSTALL_ALL_HEADERS PATH) + set(options) + set(one_value_args) + set(multi_value_args PATTERN) + cmake_parse_arguments(ARG + "${options}" + "${one_value_args}" + "${multi_value_args}" + ${ARGN}) + if(NOT ARG_PATTERN) + # The .hpp extension is used by some vendored libraries + set(ARG_PATTERN "*.h" "*.hpp") + endif() + file(GLOB CURRENT_DIRECTORY_HEADERS ${ARG_PATTERN}) + + set(PUBLIC_HEADERS) + foreach(HEADER ${CURRENT_DIRECTORY_HEADERS}) + get_filename_component(HEADER_BASENAME ${HEADER} NAME) + if(HEADER_BASENAME MATCHES "internal") + continue() + endif() + list(APPEND PUBLIC_HEADERS ${HEADER}) + endforeach() + install(FILES ${PUBLIC_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PATH}") +endfunction() + +function(ARROW_ADD_PKG_CONFIG MODULE) + configure_file(${MODULE}.pc.in "${CMAKE_CURRENT_BINARY_DIR}/${MODULE}.pc" @ONLY) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${MODULE}.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/") +endfunction() + +function(ARROW_INSTALL_CMAKE_FIND_MODULE MODULE) + install(FILES "${ARROW_SOURCE_DIR}/cmake_modules/Find${MODULE}.cmake" + DESTINATION "${ARROW_CMAKE_INSTALL_DIR}") +endfunction() + +# Implementations of lisp "car" and "cdr" functions +macro(ARROW_CAR var) + set(${var} ${ARGV1}) +endmacro() + +macro(ARROW_CDR var rest) + set(${var} ${ARGN}) +endmacro() diff --git a/src/arrow/cpp/cmake_modules/DefineOptions.cmake b/src/arrow/cpp/cmake_modules/DefineOptions.cmake new file mode 100644 index 000000000..3568887fa --- /dev/null +++ b/src/arrow/cpp/cmake_modules/DefineOptions.cmake @@ -0,0 +1,589 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +macro(set_option_category name) + set(ARROW_OPTION_CATEGORY ${name}) + list(APPEND "ARROW_OPTION_CATEGORIES" ${name}) +endmacro() + +function(check_description_length name description) + foreach(description_line ${description}) + string(LENGTH ${description_line} line_length) + if(${line_length} GREATER 80) + message(FATAL_ERROR "description for ${name} contained a\n\ + line ${line_length} characters long!\n\ + (max is 80). Split it into more lines with semicolons") + endif() + endforeach() +endfunction() + +function(list_join lst glue out) + if("${${lst}}" STREQUAL "") + set(${out} + "" + PARENT_SCOPE) + return() + endif() + + list(GET ${lst} 0 joined) + list(REMOVE_AT ${lst} 0) + foreach(item ${${lst}}) + set(joined "${joined}${glue}${item}") + endforeach() + set(${out} + ${joined} + PARENT_SCOPE) +endfunction() + +macro(define_option name description default) + check_description_length(${name} ${description}) + list_join(description "\n" multiline_description) + + option(${name} "${multiline_description}" ${default}) + + list(APPEND "ARROW_${ARROW_OPTION_CATEGORY}_OPTION_NAMES" ${name}) + set("${name}_OPTION_DESCRIPTION" ${description}) + set("${name}_OPTION_DEFAULT" ${default}) + set("${name}_OPTION_TYPE" "bool") +endmacro() + +macro(define_option_string name description default) + check_description_length(${name} ${description}) + list_join(description "\n" multiline_description) + + set(${name} + ${default} + CACHE STRING "${multiline_description}") + + list(APPEND "ARROW_${ARROW_OPTION_CATEGORY}_OPTION_NAMES" ${name}) + set("${name}_OPTION_DESCRIPTION" ${description}) + set("${name}_OPTION_DEFAULT" "\"${default}\"") + set("${name}_OPTION_TYPE" "string") + set("${name}_OPTION_POSSIBLE_VALUES" ${ARGN}) + + list_join("${name}_OPTION_POSSIBLE_VALUES" "|" "${name}_OPTION_ENUM") + if(NOT ("${${name}_OPTION_ENUM}" STREQUAL "")) + set_property(CACHE ${name} PROPERTY STRINGS "${name}_OPTION_POSSIBLE_VALUES") + endif() +endmacro() + +# Top level cmake dir +if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") + #---------------------------------------------------------------------- + set_option_category("Compile and link") + + define_option_string(ARROW_CXXFLAGS "Compiler flags to append when compiling Arrow" "") + + define_option(ARROW_BUILD_STATIC "Build static libraries" ON) + + define_option(ARROW_BUILD_SHARED "Build shared libraries" ON) + + define_option_string(ARROW_PACKAGE_KIND + "Arbitrary string that identifies the kind of package;\ +(for informational purposes)" "") + + define_option_string(ARROW_GIT_ID "The Arrow git commit id (if any)" "") + + define_option_string(ARROW_GIT_DESCRIPTION "The Arrow git commit description (if any)" + "") + + define_option(ARROW_NO_DEPRECATED_API "Exclude deprecated APIs from build" OFF) + + define_option(ARROW_USE_CCACHE "Use ccache when compiling (if available)" ON) + + define_option(ARROW_USE_LD_GOLD "Use ld.gold for linking on Linux (if available)" OFF) + + define_option(ARROW_USE_PRECOMPILED_HEADERS "Use precompiled headers when compiling" + OFF) + + define_option_string(ARROW_SIMD_LEVEL + "Compile-time SIMD optimization level" + "DEFAULT" # default to SSE4_2 on x86, NEON on Arm, NONE otherwise + "NONE" + "SSE4_2" + "AVX2" + "AVX512" + "NEON" + "DEFAULT") + + define_option_string(ARROW_RUNTIME_SIMD_LEVEL + "Max runtime SIMD optimization level" + "MAX" # default to max supported by compiler + "NONE" + "SSE4_2" + "AVX2" + "AVX512" + "MAX") + + # Arm64 architectures and extensions can lead to exploding combinations. + # So set it directly through cmake command line. + # + # If you change this, you need to change the definition in + # python/CMakeLists.txt too. + define_option_string(ARROW_ARMV8_ARCH + "Arm64 arch and extensions" + "armv8-a" # Default + "armv8-a" + "armv8-a+crc+crypto") + + define_option(ARROW_ALTIVEC "Build with Altivec if compiler has support" ON) + + define_option(ARROW_RPATH_ORIGIN "Build Arrow libraries with RATH set to \$ORIGIN" OFF) + + define_option(ARROW_INSTALL_NAME_RPATH + "Build Arrow libraries with install_name set to @rpath" ON) + + define_option(ARROW_GGDB_DEBUG "Pass -ggdb flag to debug builds" ON) + + #---------------------------------------------------------------------- + set_option_category("Test and benchmark") + + define_option(ARROW_BUILD_EXAMPLES "Build the Arrow examples" OFF) + + define_option(ARROW_BUILD_TESTS "Build the Arrow googletest unit tests" OFF) + + define_option(ARROW_ENABLE_TIMING_TESTS "Enable timing-sensitive tests" ON) + + define_option(ARROW_BUILD_INTEGRATION "Build the Arrow integration test executables" + OFF) + + define_option(ARROW_BUILD_BENCHMARKS "Build the Arrow micro benchmarks" OFF) + + # Reference benchmarks are used to compare to naive implementation, or + # discover various hardware limits. + define_option(ARROW_BUILD_BENCHMARKS_REFERENCE + "Build the Arrow micro reference benchmarks" OFF) + + if(ARROW_BUILD_SHARED) + set(ARROW_TEST_LINKAGE_DEFAULT "shared") + else() + set(ARROW_TEST_LINKAGE_DEFAULT "static") + endif() + + define_option_string(ARROW_TEST_LINKAGE + "Linkage of Arrow libraries with unit tests executables." + "${ARROW_TEST_LINKAGE_DEFAULT}" + "shared" + "static") + + define_option(ARROW_FUZZING "Build Arrow Fuzzing executables" OFF) + + define_option(ARROW_LARGE_MEMORY_TESTS "Enable unit tests which use large memory" OFF) + + #---------------------------------------------------------------------- + set_option_category("Lint") + + define_option(ARROW_ONLY_LINT "Only define the lint and check-format targets" OFF) + + define_option(ARROW_VERBOSE_LINT + "If off, 'quiet' flags will be passed to linting tools" OFF) + + define_option(ARROW_GENERATE_COVERAGE "Build with C++ code coverage enabled" OFF) + + #---------------------------------------------------------------------- + set_option_category("Checks") + + define_option(ARROW_TEST_MEMCHECK "Run the test suite using valgrind --tool=memcheck" + OFF) + + define_option(ARROW_USE_ASAN "Enable Address Sanitizer checks" OFF) + + define_option(ARROW_USE_TSAN "Enable Thread Sanitizer checks" OFF) + + define_option(ARROW_USE_UBSAN "Enable Undefined Behavior sanitizer checks" OFF) + + #---------------------------------------------------------------------- + set_option_category("Project component") + + define_option(ARROW_BUILD_UTILITIES "Build Arrow commandline utilities" OFF) + + define_option(ARROW_COMPUTE "Build the Arrow Compute Modules" OFF) + + define_option(ARROW_CSV "Build the Arrow CSV Parser Module" OFF) + + define_option(ARROW_CUDA "Build the Arrow CUDA extensions (requires CUDA toolkit)" OFF) + + define_option(ARROW_DATASET "Build the Arrow Dataset Modules" OFF) + + define_option(ARROW_FILESYSTEM "Build the Arrow Filesystem Layer" OFF) + + define_option(ARROW_FLIGHT + "Build the Arrow Flight RPC System (requires GRPC, Protocol Buffers)" OFF) + + define_option(ARROW_GANDIVA "Build the Gandiva libraries" OFF) + + define_option(ARROW_GCS + "Build Arrow with GCS support (requires the GCloud SDK for C++)" OFF) + mark_as_advanced(ARROW_GCS) # TODO(ARROW-1231) - remove once completed + + define_option(ARROW_HDFS "Build the Arrow HDFS bridge" OFF) + + define_option(ARROW_HIVESERVER2 "Build the HiveServer2 client and Arrow adapter" OFF) + + define_option(ARROW_IPC "Build the Arrow IPC extensions" ON) + + set(ARROW_JEMALLOC_DESCRIPTION "Build the Arrow jemalloc-based allocator") + if(WIN32 OR "${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD") + # jemalloc is not supported on Windows. + # + # jemalloc is the default malloc implementation on FreeBSD and can't + # be built with --disable-libdl on FreeBSD. Because lazy-lock feature + # is required on FreeBSD. Lazy-lock feature requires libdl. + define_option(ARROW_JEMALLOC ${ARROW_JEMALLOC_DESCRIPTION} OFF) + else() + define_option(ARROW_JEMALLOC ${ARROW_JEMALLOC_DESCRIPTION} ON) + endif() + + define_option(ARROW_JNI "Build the Arrow JNI lib" OFF) + + define_option(ARROW_JSON "Build Arrow with JSON support (requires RapidJSON)" OFF) + + define_option(ARROW_MIMALLOC "Build the Arrow mimalloc-based allocator" OFF) + + define_option(ARROW_PARQUET "Build the Parquet libraries" OFF) + + define_option(ARROW_ORC "Build the Arrow ORC adapter" OFF) + + define_option(ARROW_PLASMA "Build the plasma object store along with Arrow" OFF) + + define_option(ARROW_PLASMA_JAVA_CLIENT "Build the plasma object store java client" OFF) + + define_option(ARROW_PYTHON "Build the Arrow CPython extensions" OFF) + + define_option(ARROW_S3 "Build Arrow with S3 support (requires the AWS SDK for C++)" OFF) + + define_option(ARROW_TENSORFLOW "Build Arrow with TensorFlow support enabled" OFF) + + define_option(ARROW_TESTING "Build the Arrow testing libraries" OFF) + + #---------------------------------------------------------------------- + set_option_category("Thirdparty toolchain") + + # Determine how we will look for dependencies + # * AUTO: Guess which packaging systems we're running in and pull the + # dependencies from there. Build any missing ones through the + # ExternalProject setup. This is the default unless the CONDA_PREFIX + # environment variable is set, in which case the CONDA method is used + # * BUNDLED: Build dependencies through CMake's ExternalProject facility. If + # you wish to build individual dependencies from source instead of using + # one of the other methods, pass -D$NAME_SOURCE=BUNDLED + # * SYSTEM: Use CMake's find_package and find_library without any custom + # paths. If individual packages are on non-default locations, you can pass + # $NAME_ROOT arguments to CMake, or set environment variables for the same + # with CMake 3.11 and higher. If your system packages are in a non-default + # location, or if you are using a non-standard toolchain, you can also pass + # ARROW_PACKAGE_PREFIX to set the *_ROOT variables to look in that + # directory + # * CONDA: Same as SYSTEM but set all *_ROOT variables to + # ENV{CONDA_PREFIX}. If this is run within an active conda environment, + # then ENV{CONDA_PREFIX} will be used for dependencies unless + # ARROW_DEPENDENCY_SOURCE is set explicitly to one of the other options + # * VCPKG: Searches for dependencies installed by vcpkg. + # * BREW: Use SYSTEM but search for select packages with brew. + if(NOT "$ENV{CONDA_PREFIX}" STREQUAL "") + set(ARROW_DEPENDENCY_SOURCE_DEFAULT "CONDA") + else() + set(ARROW_DEPENDENCY_SOURCE_DEFAULT "AUTO") + endif() + define_option_string(ARROW_DEPENDENCY_SOURCE + "Method to use for acquiring arrow's build dependencies" + "${ARROW_DEPENDENCY_SOURCE_DEFAULT}" + "AUTO" + "BUNDLED" + "SYSTEM" + "CONDA" + "VCPKG" + "BREW") + + define_option(ARROW_VERBOSE_THIRDPARTY_BUILD + "Show output from ExternalProjects rather than just logging to files" OFF) + + define_option(ARROW_DEPENDENCY_USE_SHARED "Link to shared libraries" ON) + + define_option(ARROW_BOOST_USE_SHARED "Rely on boost shared libraries where relevant" + ${ARROW_DEPENDENCY_USE_SHARED}) + + define_option(ARROW_BROTLI_USE_SHARED "Rely on Brotli shared libraries where relevant" + ${ARROW_DEPENDENCY_USE_SHARED}) + + define_option(ARROW_BZ2_USE_SHARED "Rely on Bz2 shared libraries where relevant" + ${ARROW_DEPENDENCY_USE_SHARED}) + + define_option(ARROW_GFLAGS_USE_SHARED "Rely on GFlags shared libraries where relevant" + ${ARROW_DEPENDENCY_USE_SHARED}) + + define_option(ARROW_GRPC_USE_SHARED "Rely on gRPC shared libraries where relevant" + ${ARROW_DEPENDENCY_USE_SHARED}) + + define_option(ARROW_LZ4_USE_SHARED "Rely on lz4 shared libraries where relevant" + ${ARROW_DEPENDENCY_USE_SHARED}) + + define_option(ARROW_OPENSSL_USE_SHARED + "Rely on OpenSSL shared libraries where relevant" + ${ARROW_DEPENDENCY_USE_SHARED}) + + define_option(ARROW_PROTOBUF_USE_SHARED + "Rely on Protocol Buffers shared libraries where relevant" + ${ARROW_DEPENDENCY_USE_SHARED}) + + if(WIN32) + # It seems that Thrift doesn't support DLL well yet. + # MSYS2, conda-forge and vcpkg don't build shared library. + set(ARROW_THRIFT_USE_SHARED_DEFAULT OFF) + else() + set(ARROW_THRIFT_USE_SHARED_DEFAULT ${ARROW_DEPENDENCY_USE_SHARED}) + endif() + define_option(ARROW_THRIFT_USE_SHARED "Rely on thrift shared libraries where relevant" + ${ARROW_THRIFT_USE_SHARED_DEFAULT}) + + define_option(ARROW_UTF8PROC_USE_SHARED + "Rely on utf8proc shared libraries where relevant" + ${ARROW_DEPENDENCY_USE_SHARED}) + + define_option(ARROW_SNAPPY_USE_SHARED "Rely on snappy shared libraries where relevant" + ${ARROW_DEPENDENCY_USE_SHARED}) + + define_option(ARROW_UTF8PROC_USE_SHARED + "Rely on utf8proc shared libraries where relevant" + ${ARROW_DEPENDENCY_USE_SHARED}) + + define_option(ARROW_ZSTD_USE_SHARED "Rely on zstd shared libraries where relevant" + ${ARROW_DEPENDENCY_USE_SHARED}) + + define_option(ARROW_USE_GLOG "Build libraries with glog support for pluggable logging" + OFF) + + define_option(ARROW_WITH_BACKTRACE "Build with backtrace support" ON) + + define_option(ARROW_WITH_BROTLI "Build with Brotli compression" OFF) + define_option(ARROW_WITH_BZ2 "Build with BZ2 compression" OFF) + define_option(ARROW_WITH_LZ4 "Build with lz4 compression" OFF) + define_option(ARROW_WITH_SNAPPY "Build with Snappy compression" OFF) + define_option(ARROW_WITH_ZLIB "Build with zlib compression" OFF) + define_option(ARROW_WITH_ZSTD "Build with zstd compression" OFF) + + define_option(ARROW_WITH_UTF8PROC + "Build with support for Unicode properties using the utf8proc library;(only used if ARROW_COMPUTE is ON or ARROW_GANDIVA is ON)" + ON) + define_option(ARROW_WITH_RE2 + "Build with support for regular expressions using the re2 library;(only used if ARROW_COMPUTE or ARROW_GANDIVA is ON)" + ON) + + #---------------------------------------------------------------------- + if(MSVC_TOOLCHAIN) + set_option_category("MSVC") + + define_option(MSVC_LINK_VERBOSE + "Pass verbose linking options when linking libraries and executables" + OFF) + + define_option_string(BROTLI_MSVC_STATIC_LIB_SUFFIX + "Brotli static lib suffix used on Windows with MSVC" "-static") + + define_option_string(PROTOBUF_MSVC_STATIC_LIB_SUFFIX + "Protobuf static lib suffix used on Windows with MSVC" "") + + define_option_string(RE2_MSVC_STATIC_LIB_SUFFIX + "re2 static lib suffix used on Windows with MSVC" "_static") + + if(DEFINED ENV{CONDA_PREFIX}) + # Conda package changes the output name. + # https://github.com/conda-forge/snappy-feedstock/blob/master/recipe/windows-static-lib-name.patch + set(SNAPPY_MSVC_STATIC_LIB_SUFFIX_DEFAULT "_static") + else() + set(SNAPPY_MSVC_STATIC_LIB_SUFFIX_DEFAULT "") + endif() + define_option_string(SNAPPY_MSVC_STATIC_LIB_SUFFIX + "Snappy static lib suffix used on Windows with MSVC" + "${SNAPPY_MSVC_STATIC_LIB_SUFFIX_DEFAULT}") + + define_option_string(LZ4_MSVC_STATIC_LIB_SUFFIX + "Lz4 static lib suffix used on Windows with MSVC" "_static") + + define_option_string(ZSTD_MSVC_STATIC_LIB_SUFFIX + "ZStd static lib suffix used on Windows with MSVC" "_static") + + define_option(ARROW_USE_STATIC_CRT "Build Arrow with statically linked CRT" OFF) + endif() + + #---------------------------------------------------------------------- + set_option_category("Parquet") + + define_option(PARQUET_MINIMAL_DEPENDENCY + "Depend only on Thirdparty headers to build libparquet.;\ +Always OFF if building binaries" OFF) + + define_option(PARQUET_BUILD_EXECUTABLES + "Build the Parquet executable CLI tools. Requires static libraries to be built." + OFF) + + define_option(PARQUET_BUILD_EXAMPLES + "Build the Parquet examples. Requires static libraries to be built." OFF) + + define_option(PARQUET_REQUIRE_ENCRYPTION + "Build support for encryption. Fail if OpenSSL is not found" OFF) + + #---------------------------------------------------------------------- + set_option_category("Gandiva") + + define_option(ARROW_GANDIVA_JAVA "Build the Gandiva JNI wrappers" OFF) + + # ARROW-3860: Temporary workaround + define_option(ARROW_GANDIVA_STATIC_LIBSTDCPP + "Include -static-libstdc++ -static-libgcc when linking with;Gandiva static libraries" + OFF) + + define_option_string(ARROW_GANDIVA_PC_CXX_FLAGS + "Compiler flags to append when pre-compiling Gandiva operations" + "") + + #---------------------------------------------------------------------- + set_option_category("Advanced developer") + + define_option(ARROW_EXTRA_ERROR_CONTEXT + "Compile with extra error context (line numbers, code)" OFF) + + define_option(ARROW_OPTIONAL_INSTALL + "If enabled install ONLY targets that have already been built. Please be;\ +advised that if this is enabled 'install' will fail silently on components;\ +that have not been built" + OFF) + + option(ARROW_BUILD_CONFIG_SUMMARY_JSON "Summarize build configuration in a JSON file" + ON) +endif() + +macro(validate_config) + foreach(category ${ARROW_OPTION_CATEGORIES}) + set(option_names ${ARROW_${category}_OPTION_NAMES}) + + foreach(name ${option_names}) + set(possible_values ${${name}_OPTION_POSSIBLE_VALUES}) + set(value "${${name}}") + if(possible_values) + if(NOT "${value}" IN_LIST possible_values) + message(FATAL_ERROR "Configuration option ${name} got invalid value '${value}'. " + "Allowed values: ${${name}_OPTION_ENUM}.") + endif() + endif() + endforeach() + + endforeach() +endmacro() + +macro(config_summary_message) + message(STATUS "---------------------------------------------------------------------") + message(STATUS "Arrow version: ${ARROW_VERSION}") + message(STATUS) + message(STATUS "Build configuration summary:") + + message(STATUS " Generator: ${CMAKE_GENERATOR}") + message(STATUS " Build type: ${CMAKE_BUILD_TYPE}") + message(STATUS " Source directory: ${CMAKE_CURRENT_SOURCE_DIR}") + message(STATUS " Install prefix: ${CMAKE_INSTALL_PREFIX}") + if(${CMAKE_EXPORT_COMPILE_COMMANDS}) + message(STATUS " Compile commands: ${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json" + ) + endif() + + foreach(category ${ARROW_OPTION_CATEGORIES}) + + message(STATUS) + message(STATUS "${category} options:") + message(STATUS) + + set(option_names ${ARROW_${category}_OPTION_NAMES}) + + foreach(name ${option_names}) + set(value "${${name}}") + if("${value}" STREQUAL "") + set(value "\"\"") + endif() + + set(description ${${name}_OPTION_DESCRIPTION}) + + if(NOT ("${${name}_OPTION_ENUM}" STREQUAL "")) + set(summary "=${value} [default=${${name}_OPTION_ENUM}]") + else() + set(summary "=${value} [default=${${name}_OPTION_DEFAULT}]") + endif() + + message(STATUS " ${name}${summary}") + foreach(description_line ${description}) + message(STATUS " ${description_line}") + endforeach() + endforeach() + + endforeach() + +endmacro() + +macro(config_summary_json) + set(summary "${CMAKE_CURRENT_BINARY_DIR}/cmake_summary.json") + message(STATUS " Outputting build configuration summary to ${summary}") + file(WRITE ${summary} "{\n") + + foreach(category ${ARROW_OPTION_CATEGORIES}) + foreach(name ${ARROW_${category}_OPTION_NAMES}) + file(APPEND ${summary} "\"${name}\": \"${${name}}\",\n") + endforeach() + endforeach() + + file(APPEND ${summary} "\"generator\": \"${CMAKE_GENERATOR}\",\n") + file(APPEND ${summary} "\"build_type\": \"${CMAKE_BUILD_TYPE}\",\n") + file(APPEND ${summary} "\"source_dir\": \"${CMAKE_CURRENT_SOURCE_DIR}\",\n") + if(${CMAKE_EXPORT_COMPILE_COMMANDS}) + file(APPEND ${summary} "\"compile_commands\": " + "\"${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json\",\n") + endif() + file(APPEND ${summary} "\"install_prefix\": \"${CMAKE_INSTALL_PREFIX}\",\n") + file(APPEND ${summary} "\"arrow_version\": \"${ARROW_VERSION}\"\n") + file(APPEND ${summary} "}\n") +endmacro() + +macro(config_summary_cmake_setters path) + file(WRITE ${path} "# Options used to build arrow:") + + foreach(category ${ARROW_OPTION_CATEGORIES}) + file(APPEND ${path} "\n\n## ${category} options:") + foreach(name ${ARROW_${category}_OPTION_NAMES}) + set(description ${${name}_OPTION_DESCRIPTION}) + foreach(description_line ${description}) + file(APPEND ${path} "\n### ${description_line}") + endforeach() + file(APPEND ${path} "\nset(${name} \"${${name}}\")") + endforeach() + endforeach() + +endmacro() + +#---------------------------------------------------------------------- +# Compute default values for omitted variables + +if(NOT ARROW_GIT_ID) + execute_process(COMMAND "git" "log" "-n1" "--format=%H" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE ARROW_GIT_ID + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() +if(NOT ARROW_GIT_DESCRIPTION) + execute_process(COMMAND "git" "describe" "--tags" "--dirty" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + ERROR_QUIET + OUTPUT_VARIABLE ARROW_GIT_DESCRIPTION + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() diff --git a/src/arrow/cpp/cmake_modules/FindArrow.cmake b/src/arrow/cpp/cmake_modules/FindArrow.cmake new file mode 100644 index 000000000..68024cc27 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindArrow.cmake @@ -0,0 +1,466 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# - Find Arrow (arrow/api.h, libarrow.a, libarrow.so) +# This module defines +# ARROW_FOUND, whether Arrow has been found +# ARROW_FULL_SO_VERSION, full shared object version of found Arrow "100.0.0" +# ARROW_IMPORT_LIB, path to libarrow's import library (Windows only) +# ARROW_INCLUDE_DIR, directory containing headers +# ARROW_LIBS, deprecated. Use ARROW_LIB_DIR instead +# ARROW_LIB_DIR, directory containing Arrow libraries +# ARROW_SHARED_IMP_LIB, deprecated. Use ARROW_IMPORT_LIB instead +# ARROW_SHARED_LIB, path to libarrow's shared library +# ARROW_SO_VERSION, shared object version of found Arrow such as "100" +# ARROW_STATIC_LIB, path to libarrow.a +# ARROW_VERSION, version of found Arrow +# ARROW_VERSION_MAJOR, major version of found Arrow +# ARROW_VERSION_MINOR, minor version of found Arrow +# ARROW_VERSION_PATCH, patch version of found Arrow + +if(DEFINED ARROW_FOUND) + return() +endif() + +include(FindPkgConfig) +include(FindPackageHandleStandardArgs) + +if(WIN32 AND NOT MINGW) + # This is used to handle builds using e.g. clang in an MSVC setting. + set(MSVC_TOOLCHAIN TRUE) +else() + set(MSVC_TOOLCHAIN FALSE) +endif() + +set(ARROW_SEARCH_LIB_PATH_SUFFIXES) +if(CMAKE_LIBRARY_ARCHITECTURE) + list(APPEND ARROW_SEARCH_LIB_PATH_SUFFIXES "lib/${CMAKE_LIBRARY_ARCHITECTURE}") +endif() +list(APPEND + ARROW_SEARCH_LIB_PATH_SUFFIXES + "lib64" + "lib32" + "lib" + "bin") +set(ARROW_CONFIG_SUFFIXES + "_RELEASE" + "_RELWITHDEBINFO" + "_MINSIZEREL" + "_DEBUG" + "") +if(CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} ARROW_CONFIG_SUFFIX_PREFERRED) + set(ARROW_CONFIG_SUFFIX_PREFERRED "_${ARROW_CONFIG_SUFFIX_PREFERRED}") + list(INSERT ARROW_CONFIG_SUFFIXES 0 "${ARROW_CONFIG_SUFFIX_PREFERRED}") +endif() + +if(NOT DEFINED ARROW_MSVC_STATIC_LIB_SUFFIX) + if(MSVC_TOOLCHAIN) + set(ARROW_MSVC_STATIC_LIB_SUFFIX "_static") + else() + set(ARROW_MSVC_STATIC_LIB_SUFFIX "") + endif() +endif() + +# Internal function. +# +# Set shared library name for ${base_name} to ${output_variable}. +# +# Example: +# arrow_build_shared_library_name(ARROW_SHARED_LIBRARY_NAME arrow) +# # -> ARROW_SHARED_LIBRARY_NAME=libarrow.so on Linux +# # -> ARROW_SHARED_LIBRARY_NAME=libarrow.dylib on macOS +# # -> ARROW_SHARED_LIBRARY_NAME=arrow.dll with MSVC on Windows +# # -> ARROW_SHARED_LIBRARY_NAME=libarrow.dll with MinGW on Windows +function(arrow_build_shared_library_name output_variable base_name) + set(${output_variable} + "${CMAKE_SHARED_LIBRARY_PREFIX}${base_name}${CMAKE_SHARED_LIBRARY_SUFFIX}" + PARENT_SCOPE) +endfunction() + +# Internal function. +# +# Set import library name for ${base_name} to ${output_variable}. +# This is useful only for MSVC build. Import library is used only +# with MSVC build. +# +# Example: +# arrow_build_import_library_name(ARROW_IMPORT_LIBRARY_NAME arrow) +# # -> ARROW_IMPORT_LIBRARY_NAME=arrow on Linux (meaningless) +# # -> ARROW_IMPORT_LIBRARY_NAME=arrow on macOS (meaningless) +# # -> ARROW_IMPORT_LIBRARY_NAME=arrow.lib with MSVC on Windows +# # -> ARROW_IMPORT_LIBRARY_NAME=libarrow.dll.a with MinGW on Windows +function(arrow_build_import_library_name output_variable base_name) + set(${output_variable} + "${CMAKE_IMPORT_LIBRARY_PREFIX}${base_name}${CMAKE_IMPORT_LIBRARY_SUFFIX}" + PARENT_SCOPE) +endfunction() + +# Internal function. +# +# Set static library name for ${base_name} to ${output_variable}. +# +# Example: +# arrow_build_static_library_name(ARROW_STATIC_LIBRARY_NAME arrow) +# # -> ARROW_STATIC_LIBRARY_NAME=libarrow.a on Linux +# # -> ARROW_STATIC_LIBRARY_NAME=libarrow.a on macOS +# # -> ARROW_STATIC_LIBRARY_NAME=arrow.lib with MSVC on Windows +# # -> ARROW_STATIC_LIBRARY_NAME=libarrow.dll.a with MinGW on Windows +function(arrow_build_static_library_name output_variable base_name) + set(${output_variable} + "${CMAKE_STATIC_LIBRARY_PREFIX}${base_name}${ARROW_MSVC_STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}" + PARENT_SCOPE) +endfunction() + +# Internal function. +# +# Set macro value for ${macro_name} in ${header_content} to ${output_variable}. +# +# Example: +# arrow_extract_macro_value(version_major +# "ARROW_VERSION_MAJOR" +# "#define ARROW_VERSION_MAJOR 1.0.0") +# # -> version_major=1.0.0 +function(arrow_extract_macro_value output_variable macro_name header_content) + string(REGEX MATCH "#define +${macro_name} +[^\r\n]+" macro_definition + "${header_content}") + string(REGEX REPLACE "^#define +${macro_name} +(.+)$" "\\1" macro_value + "${macro_definition}") + set(${output_variable} + "${macro_value}" + PARENT_SCOPE) +endfunction() + +# Internal macro only for arrow_find_package. +# +# Find package in HOME. +macro(arrow_find_package_home) + find_path(${prefix}_include_dir "${header_path}" + PATHS "${home}" + PATH_SUFFIXES "include" + NO_DEFAULT_PATH) + set(include_dir "${${prefix}_include_dir}") + set(${prefix}_INCLUDE_DIR + "${include_dir}" + PARENT_SCOPE) + + if(MSVC_TOOLCHAIN) + set(CMAKE_SHARED_LIBRARY_SUFFIXES_ORIGINAL ${CMAKE_FIND_LIBRARY_SUFFIXES}) + # .dll isn't found by find_library with MSVC because .dll isn't included in + # CMAKE_FIND_LIBRARY_SUFFIXES. + list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_SHARED_LIBRARY_SUFFIX}") + endif() + find_library(${prefix}_shared_lib + NAMES "${shared_lib_name}" + PATHS "${home}" + PATH_SUFFIXES ${ARROW_SEARCH_LIB_PATH_SUFFIXES} + NO_DEFAULT_PATH) + if(MSVC_TOOLCHAIN) + set(CMAKE_SHARED_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_ORIGINAL}) + endif() + set(shared_lib "${${prefix}_shared_lib}") + set(${prefix}_SHARED_LIB + "${shared_lib}" + PARENT_SCOPE) + if(shared_lib) + add_library(${target_shared} SHARED IMPORTED) + set_target_properties(${target_shared} PROPERTIES IMPORTED_LOCATION "${shared_lib}") + if(include_dir) + set_target_properties(${target_shared} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${include_dir}") + endif() + find_library(${prefix}_import_lib + NAMES "${import_lib_name}" + PATHS "${home}" + PATH_SUFFIXES ${ARROW_SEARCH_LIB_PATH_SUFFIXES} + NO_DEFAULT_PATH) + set(import_lib "${${prefix}_import_lib}") + set(${prefix}_IMPORT_LIB + "${import_lib}" + PARENT_SCOPE) + if(import_lib) + set_target_properties(${target_shared} PROPERTIES IMPORTED_IMPLIB "${import_lib}") + endif() + endif() + + find_library(${prefix}_static_lib + NAMES "${static_lib_name}" + PATHS "${home}" + PATH_SUFFIXES ${ARROW_SEARCH_LIB_PATH_SUFFIXES} + NO_DEFAULT_PATH) + set(static_lib "${${prefix}_static_lib}") + set(${prefix}_STATIC_LIB + "${static_lib}" + PARENT_SCOPE) + if(static_lib) + add_library(${target_static} STATIC IMPORTED) + set_target_properties(${target_static} PROPERTIES IMPORTED_LOCATION "${static_lib}") + if(include_dir) + set_target_properties(${target_static} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${include_dir}") + endif() + endif() +endmacro() + +# Internal macro only for arrow_find_package. +# +# Find package by CMake package configuration. +macro(arrow_find_package_cmake_package_configuration) + find_package(${cmake_package_name} CONFIG) + if(${cmake_package_name}_FOUND) + set(${prefix}_USE_CMAKE_PACKAGE_CONFIG + TRUE + PARENT_SCOPE) + if(TARGET ${target_shared}) + foreach(suffix ${ARROW_CONFIG_SUFFIXES}) + get_target_property(shared_lib ${target_shared} IMPORTED_LOCATION${suffix}) + if(shared_lib) + # Remove shared library version: + # libarrow.so.100.0.0 -> libarrow.so + # Because ARROW_HOME and pkg-config approaches don't add + # shared library version. + string(REGEX REPLACE "(${CMAKE_SHARED_LIBRARY_SUFFIX})[.0-9]+$" "\\1" + shared_lib "${shared_lib}") + set(${prefix}_SHARED_LIB + "${shared_lib}" + PARENT_SCOPE) + break() + endif() + endforeach() + endif() + if(TARGET ${target_static}) + foreach(suffix ${ARROW_CONFIG_SUFFIXES}) + get_target_property(static_lib ${target_static} IMPORTED_LOCATION${suffix}) + if(static_lib) + set(${prefix}_STATIC_LIB + "${static_lib}" + PARENT_SCOPE) + break() + endif() + endforeach() + endif() + endif() +endmacro() + +# Internal macro only for arrow_find_package. +# +# Find package by pkg-config. +macro(arrow_find_package_pkg_config) + pkg_check_modules(${prefix}_PC ${pkg_config_name}) + if(${prefix}_PC_FOUND) + set(${prefix}_USE_PKG_CONFIG + TRUE + PARENT_SCOPE) + + set(include_dir "${${prefix}_PC_INCLUDEDIR}") + set(lib_dir "${${prefix}_PC_LIBDIR}") + set(shared_lib_paths "${${prefix}_PC_LINK_LIBRARIES}") + # Use the first shared library path as the IMPORTED_LOCATION + # for ${target_shared}. This assumes that the first shared library + # path is the shared library path for this module. + list(GET shared_lib_paths 0 first_shared_lib_path) + # Use the rest shared library paths as the INTERFACE_LINK_LIBRARIES + # for ${target_shared}. This assumes that the rest shared library + # paths are dependency library paths for this module. + list(LENGTH shared_lib_paths n_shared_lib_paths) + if(n_shared_lib_paths LESS_EQUAL 1) + set(rest_shared_lib_paths) + else() + list(SUBLIST + shared_lib_paths + 1 + -1 + rest_shared_lib_paths) + endif() + + set(${prefix}_VERSION + "${${prefix}_PC_VERSION}" + PARENT_SCOPE) + set(${prefix}_INCLUDE_DIR + "${include_dir}" + PARENT_SCOPE) + set(${prefix}_SHARED_LIB + "${first_shared_lib_path}" + PARENT_SCOPE) + + add_library(${target_shared} SHARED IMPORTED) + set_target_properties(${target_shared} + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${include_dir}" + INTERFACE_LINK_LIBRARIES "${rest_shared_lib_paths}" + IMPORTED_LOCATION "${first_shared_lib_path}") + get_target_property(shared_lib ${target_shared} IMPORTED_LOCATION) + + find_library(${prefix}_static_lib + NAMES "${static_lib_name}" + PATHS "${lib_dir}" + NO_DEFAULT_PATH) + set(static_lib "${${prefix}_static_lib}") + set(${prefix}_STATIC_LIB + "${static_lib}" + PARENT_SCOPE) + if(static_lib) + add_library(${target_static} STATIC IMPORTED) + set_target_properties(${target_static} + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${include_dir}" + IMPORTED_LOCATION "${static_lib}") + endif() + endif() +endmacro() + +function(arrow_find_package + prefix + home + base_name + header_path + cmake_package_name + pkg_config_name) + arrow_build_shared_library_name(shared_lib_name ${base_name}) + arrow_build_import_library_name(import_lib_name ${base_name}) + arrow_build_static_library_name(static_lib_name ${base_name}) + + set(target_shared ${base_name}_shared) + set(target_static ${base_name}_static) + + if(home) + arrow_find_package_home() + set(${prefix}_FIND_APPROACH + "HOME: ${home}" + PARENT_SCOPE) + else() + arrow_find_package_cmake_package_configuration() + if(${cmake_package_name}_FOUND) + set(${prefix}_FIND_APPROACH + "CMake package configuration: ${cmake_package_name}" + PARENT_SCOPE) + else() + arrow_find_package_pkg_config() + set(${prefix}_FIND_APPROACH + "pkg-config: ${pkg_config_name}" + PARENT_SCOPE) + endif() + endif() + + if(NOT include_dir) + if(TARGET ${target_shared}) + get_target_property(include_dir ${target_shared} INTERFACE_INCLUDE_DIRECTORIES) + elseif(TARGET ${target_static}) + get_target_property(include_dir ${target_static} INTERFACE_INCLUDE_DIRECTORIES) + endif() + endif() + if(include_dir) + set(${prefix}_INCLUDE_DIR + "${include_dir}" + PARENT_SCOPE) + endif() + + if(shared_lib) + get_filename_component(lib_dir "${shared_lib}" DIRECTORY) + elseif(static_lib) + get_filename_component(lib_dir "${static_lib}" DIRECTORY) + else() + set(lib_dir NOTFOUND) + endif() + set(${prefix}_LIB_DIR + "${lib_dir}" + PARENT_SCOPE) + # For backward compatibility + set(${prefix}_LIBS + "${lib_dir}" + PARENT_SCOPE) +endfunction() + +if(NOT "$ENV{ARROW_HOME}" STREQUAL "") + file(TO_CMAKE_PATH "$ENV{ARROW_HOME}" ARROW_HOME) +endif() +arrow_find_package(ARROW + "${ARROW_HOME}" + arrow + arrow/api.h + Arrow + arrow) + +if(ARROW_HOME) + if(ARROW_INCLUDE_DIR) + file(READ "${ARROW_INCLUDE_DIR}/arrow/util/config.h" ARROW_CONFIG_H_CONTENT) + arrow_extract_macro_value(ARROW_VERSION_MAJOR "ARROW_VERSION_MAJOR" + "${ARROW_CONFIG_H_CONTENT}") + arrow_extract_macro_value(ARROW_VERSION_MINOR "ARROW_VERSION_MINOR" + "${ARROW_CONFIG_H_CONTENT}") + arrow_extract_macro_value(ARROW_VERSION_PATCH "ARROW_VERSION_PATCH" + "${ARROW_CONFIG_H_CONTENT}") + if("${ARROW_VERSION_MAJOR}" STREQUAL "" + OR "${ARROW_VERSION_MINOR}" STREQUAL "" + OR "${ARROW_VERSION_PATCH}" STREQUAL "") + set(ARROW_VERSION "0.0.0") + else() + set(ARROW_VERSION + "${ARROW_VERSION_MAJOR}.${ARROW_VERSION_MINOR}.${ARROW_VERSION_PATCH}") + endif() + + arrow_extract_macro_value(ARROW_SO_VERSION_QUOTED "ARROW_SO_VERSION" + "${ARROW_CONFIG_H_CONTENT}") + string(REGEX REPLACE "^\"(.+)\"$" "\\1" ARROW_SO_VERSION "${ARROW_SO_VERSION_QUOTED}") + arrow_extract_macro_value(ARROW_FULL_SO_VERSION_QUOTED "ARROW_FULL_SO_VERSION" + "${ARROW_CONFIG_H_CONTENT}") + string(REGEX REPLACE "^\"(.+)\"$" "\\1" ARROW_FULL_SO_VERSION + "${ARROW_FULL_SO_VERSION_QUOTED}") + endif() +else() + if(ARROW_USE_CMAKE_PACKAGE_CONFIG) + find_package(Arrow CONFIG) + elseif(ARROW_USE_PKG_CONFIG) + pkg_get_variable(ARROW_SO_VERSION arrow so_version) + pkg_get_variable(ARROW_FULL_SO_VERSION arrow full_so_version) + endif() +endif() + +set(ARROW_ABI_VERSION ${ARROW_SO_VERSION}) + +mark_as_advanced(ARROW_ABI_VERSION + ARROW_CONFIG_SUFFIXES + ARROW_FULL_SO_VERSION + ARROW_IMPORT_LIB + ARROW_INCLUDE_DIR + ARROW_LIBS + ARROW_LIB_DIR + ARROW_SEARCH_LIB_PATH_SUFFIXES + ARROW_SHARED_IMP_LIB + ARROW_SHARED_LIB + ARROW_SO_VERSION + ARROW_STATIC_LIB + ARROW_VERSION + ARROW_VERSION_MAJOR + ARROW_VERSION_MINOR + ARROW_VERSION_PATCH) + +find_package_handle_standard_args( + Arrow + REQUIRED_VARS # The first required variable is shown + # in the found message. So this list is + # not sorted alphabetically. + ARROW_INCLUDE_DIR ARROW_LIB_DIR ARROW_FULL_SO_VERSION ARROW_SO_VERSION + VERSION_VAR ARROW_VERSION) +set(ARROW_FOUND ${Arrow_FOUND}) + +if(Arrow_FOUND AND NOT Arrow_FIND_QUIETLY) + message(STATUS "Arrow version: ${ARROW_VERSION} (${ARROW_FIND_APPROACH})") + message(STATUS "Arrow SO and ABI version: ${ARROW_SO_VERSION}") + message(STATUS "Arrow full SO version: ${ARROW_FULL_SO_VERSION}") + message(STATUS "Found the Arrow core shared library: ${ARROW_SHARED_LIB}") + message(STATUS "Found the Arrow core import library: ${ARROW_IMPORT_LIB}") + message(STATUS "Found the Arrow core static library: ${ARROW_STATIC_LIB}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindArrowCUDA.cmake b/src/arrow/cpp/cmake_modules/FindArrowCUDA.cmake new file mode 100644 index 000000000..014386f30 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindArrowCUDA.cmake @@ -0,0 +1,88 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# - Find Arrow CUDA (arrow/gpu/cuda_api.h, libarrow_cuda.a, libarrow_cuda.so) +# +# This module requires Arrow from which it uses +# arrow_find_package() +# +# This module defines +# ARROW_CUDA_FOUND, whether Arrow CUDA has been found +# ARROW_CUDA_IMPORT_LIB, path to libarrow_cuda's import library (Windows only) +# ARROW_CUDA_INCLUDE_DIR, directory containing headers +# ARROW_CUDA_LIBS, deprecated. Use ARROW_CUDA_LIB_DIR instead +# ARROW_CUDA_LIB_DIR, directory containing Arrow CUDA libraries +# ARROW_CUDA_SHARED_IMP_LIB, deprecated. Use ARROW_CUDA_IMPORT_LIB instead +# ARROW_CUDA_SHARED_LIB, path to libarrow_cuda's shared library +# ARROW_CUDA_STATIC_LIB, path to libarrow_cuda.a + +if(DEFINED ARROW_CUDA_FOUND) + return() +endif() + +set(find_package_arguments) +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION) + list(APPEND find_package_arguments "${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION}") +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) + list(APPEND find_package_arguments REQUIRED) +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) + list(APPEND find_package_arguments QUIET) +endif() +find_package(Arrow ${find_package_arguments}) + +if(ARROW_FOUND) + arrow_find_package(ARROW_CUDA + "${ARROW_HOME}" + arrow_cuda + arrow/gpu/cuda_api.h + ArrowCUDA + arrow-cuda) + if(NOT ARROW_CUDA_VERSION) + set(ARROW_CUDA_VERSION "${ARROW_VERSION}") + endif() +endif() + +if("${ARROW_CUDA_VERSION}" VERSION_EQUAL "${ARROW_VERSION}") + set(ARROW_CUDA_VERSION_MATCH TRUE) +else() + set(ARROW_CUDA_VERSION_MATCH FALSE) +endif() + +mark_as_advanced(ARROW_CUDA_IMPORT_LIB + ARROW_CUDA_INCLUDE_DIR + ARROW_CUDA_LIBS + ARROW_CUDA_LIB_DIR + ARROW_CUDA_SHARED_IMP_LIB + ARROW_CUDA_SHARED_LIB + ARROW_CUDA_STATIC_LIB + ARROW_CUDA_VERSION + ARROW_CUDA_VERSION_MATCH) + +find_package_handle_standard_args( + ArrowCUDA + REQUIRED_VARS ARROW_CUDA_INCLUDE_DIR ARROW_CUDA_LIB_DIR ARROW_CUDA_VERSION_MATCH + VERSION_VAR ARROW_CUDA_VERSION) +set(ARROW_CUDA_FOUND ${ArrowCUDA_FOUND}) + +if(ArrowCUDA_FOUND AND NOT ArrowCUDA_FIND_QUIETLY) + message(STATUS "Found the Arrow CUDA by ${ARROW_CUDA_FIND_APPROACH}") + message(STATUS "Found the Arrow CUDA shared library: ${ARROW_CUDA_SHARED_LIB}") + message(STATUS "Found the Arrow CUDA import library: ${ARROW_CUDA_IMPORT_LIB}") + message(STATUS "Found the Arrow CUDA static library: ${ARROW_CUDA_STATIC_LIB}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindArrowDataset.cmake b/src/arrow/cpp/cmake_modules/FindArrowDataset.cmake new file mode 100644 index 000000000..fe74f247f --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindArrowDataset.cmake @@ -0,0 +1,89 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# - Find Arrow Dataset (arrow/dataset/api.h, libarrow_dataset.a, libarrow_dataset.so) +# +# This module requires Arrow from which it uses +# arrow_find_package() +# +# This module defines +# ARROW_DATASET_FOUND, whether Arrow Dataset has been found +# ARROW_DATASET_IMPORT_LIB, +# path to libarrow_dataset's import library (Windows only) +# ARROW_DATASET_INCLUDE_DIR, directory containing headers +# ARROW_DATASET_LIB_DIR, directory containing Arrow Dataset libraries +# ARROW_DATASET_SHARED_LIB, path to libarrow_dataset's shared library +# ARROW_DATASET_STATIC_LIB, path to libarrow_dataset.a + +if(DEFINED ARROW_DATASET_FOUND) + return() +endif() + +set(find_package_arguments) +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION) + list(APPEND find_package_arguments "${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION}") +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) + list(APPEND find_package_arguments REQUIRED) +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) + list(APPEND find_package_arguments QUIET) +endif() +find_package(Arrow ${find_package_arguments}) +find_package(Parquet ${find_package_arguments}) + +if(ARROW_FOUND AND PARQUET_FOUND) + arrow_find_package(ARROW_DATASET + "${ARROW_HOME}" + arrow_dataset + arrow/dataset/api.h + ArrowDataset + arrow-dataset) + if(NOT ARROW_DATASET_VERSION) + set(ARROW_DATASET_VERSION "${ARROW_VERSION}") + endif() +endif() + +if("${ARROW_DATASET_VERSION}" VERSION_EQUAL "${ARROW_VERSION}") + set(ARROW_DATASET_VERSION_MATCH TRUE) +else() + set(ARROW_DATASET_VERSION_MATCH FALSE) +endif() + +mark_as_advanced(ARROW_DATASET_IMPORT_LIB + ARROW_DATASET_INCLUDE_DIR + ARROW_DATASET_LIBS + ARROW_DATASET_LIB_DIR + ARROW_DATASET_SHARED_IMP_LIB + ARROW_DATASET_SHARED_LIB + ARROW_DATASET_STATIC_LIB + ARROW_DATASET_VERSION + ARROW_DATASET_VERSION_MATCH) + +find_package_handle_standard_args( + ArrowDataset + REQUIRED_VARS ARROW_DATASET_INCLUDE_DIR ARROW_DATASET_LIB_DIR + ARROW_DATASET_VERSION_MATCH + VERSION_VAR ARROW_DATASET_VERSION) +set(ARROW_DATASET_FOUND ${ArrowDataset_FOUND}) + +if(ArrowDataset_FOUND AND NOT ArrowDataset_FIND_QUIETLY) + message(STATUS "Found the Arrow Dataset by ${ARROW_DATASET_FIND_APPROACH}") + message(STATUS "Found the Arrow Dataset shared library: ${ARROW_DATASET_SHARED_LIB}") + message(STATUS "Found the Arrow Dataset import library: ${ARROW_DATASET_IMPORT_LIB}") + message(STATUS "Found the Arrow Dataset static library: ${ARROW_DATASET_STATIC_LIB}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindArrowFlight.cmake b/src/arrow/cpp/cmake_modules/FindArrowFlight.cmake new file mode 100644 index 000000000..805a4ff38 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindArrowFlight.cmake @@ -0,0 +1,89 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# - Find Arrow Flight (arrow/flight/api.h, libarrow_flight.a, libarrow_flight.so) +# +# This module requires Arrow from which it uses +# arrow_find_package() +# +# This module defines +# ARROW_FLIGHT_FOUND, whether Flight has been found +# ARROW_FLIGHT_IMPORT_LIB, +# path to libarrow_flight's import library (Windows only) +# ARROW_FLIGHT_INCLUDE_DIR, directory containing headers +# ARROW_FLIGHT_LIBS, deprecated. Use ARROW_FLIGHT_LIB_DIR instead +# ARROW_FLIGHT_LIB_DIR, directory containing Flight libraries +# ARROW_FLIGHT_SHARED_IMP_LIB, deprecated. Use ARROW_FLIGHT_IMPORT_LIB instead +# ARROW_FLIGHT_SHARED_LIB, path to libarrow_flight's shared library +# ARROW_FLIGHT_STATIC_LIB, path to libarrow_flight.a + +if(DEFINED ARROW_FLIGHT_FOUND) + return() +endif() + +set(find_package_arguments) +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION) + list(APPEND find_package_arguments "${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION}") +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) + list(APPEND find_package_arguments REQUIRED) +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) + list(APPEND find_package_arguments QUIET) +endif() +find_package(Arrow ${find_package_arguments}) + +if(ARROW_FOUND) + arrow_find_package(ARROW_FLIGHT + "${ARROW_HOME}" + arrow_flight + arrow/flight/api.h + ArrowFlight + arrow-flight) + if(NOT ARROW_FLIGHT_VERSION) + set(ARROW_FLIGHT_VERSION "${ARROW_VERSION}") + endif() +endif() + +if("${ARROW_FLIGHT_VERSION}" VERSION_EQUAL "${ARROW_VERSION}") + set(ARROW_FLIGHT_VERSION_MATCH TRUE) +else() + set(ARROW_FLIGHT_VERSION_MATCH FALSE) +endif() + +mark_as_advanced(ARROW_FLIGHT_IMPORT_LIB + ARROW_FLIGHT_INCLUDE_DIR + ARROW_FLIGHT_LIBS + ARROW_FLIGHT_LIB_DIR + ARROW_FLIGHT_SHARED_IMP_LIB + ARROW_FLIGHT_SHARED_LIB + ARROW_FLIGHT_STATIC_LIB + ARROW_FLIGHT_VERSION + ARROW_FLIGHT_VERSION_MATCH) + +find_package_handle_standard_args( + ArrowFlight + REQUIRED_VARS ARROW_FLIGHT_INCLUDE_DIR ARROW_FLIGHT_LIB_DIR ARROW_FLIGHT_VERSION_MATCH + VERSION_VAR ARROW_FLIGHT_VERSION) +set(ARROW_FLIGHT_FOUND ${ArrowFlight_FOUND}) + +if(ArrowFlight_FOUND AND NOT ArrowFlight_FIND_QUIETLY) + message(STATUS "Found the Arrow Flight by ${ARROW_FLIGHT_FIND_APPROACH}") + message(STATUS "Found the Arrow Flight shared library: ${ARROW_FLIGHT_SHARED_LIB}") + message(STATUS "Found the Arrow Flight import library: ${ARROW_FLIGHT_IMPORT_LIB}") + message(STATUS "Found the Arrow Flight static library: ${ARROW_FLIGHT_STATIC_LIB}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindArrowFlightTesting.cmake b/src/arrow/cpp/cmake_modules/FindArrowFlightTesting.cmake new file mode 100644 index 000000000..c0756cf63 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindArrowFlightTesting.cmake @@ -0,0 +1,98 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# - Find Arrow Flight testing library +# (arrow/flight/test_util.h, +# libarrow_flight_testing.a, +# libarrow_flight_testing.so) +# +# This module requires Arrow from which it uses +# arrow_find_package() +# +# This module defines +# ARROW_FLIGHT_TESTING_FOUND, +# whether Arrow Flight testing library has been found +# ARROW_FLIGHT_TESTING_IMPORT_LIB, +# path to libarrow_flight_testing's import library (Windows only) +# ARROW_FLIGHT_TESTING_INCLUDE_DIR, directory containing headers +# ARROW_FLIGHT_TESTING_LIB_DIR, directory containing Arrow testing libraries +# ARROW_FLIGHT_TESTING_SHARED_LIB, +# path to libarrow_flight_testing's shared library +# ARROW_FLIGHT_TESTING_STATIC_LIB, path to libarrow_flight_testing.a + +if(DEFINED ARROW_FLIGHT_TESTING_FOUND) + return() +endif() + +set(find_package_arguments) +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION) + list(APPEND find_package_arguments "${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION}") +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) + list(APPEND find_package_arguments REQUIRED) +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) + list(APPEND find_package_arguments QUIET) +endif() +find_package(ArrowFlight ${find_package_arguments}) +find_package(ArrowTesting ${find_package_arguments}) + +if(ARROW_TESTING_FOUND AND ARROW_FLIGHT_FOUND) + arrow_find_package(ARROW_FLIGHT_TESTING + "${ARROW_HOME}" + arrow_flight_testing + arrow/flight/test_util.h + ArrowFlightTesting + arrow-flight-testing) + if(NOT ARROW_FLIGHT_TESTING_VERSION) + set(ARROW_FLIGHT_TESTING_VERSION "${ARROW_VERSION}") + endif() +endif() + +if("${ARROW_FLIGHT_TESTING_VERSION}" VERSION_EQUAL "${ARROW_VERSION}") + set(ARROW_FLIGHT_TESTING_VERSION_MATCH TRUE) +else() + set(ARROW_FLIGHT_TESTING_VERSION_MATCH FALSE) +endif() + +mark_as_advanced(ARROW_FLIGHT_TESTING_IMPORT_LIB + ARROW_FLIGHT_TESTING_INCLUDE_DIR + ARROW_FLIGHT_TESTING_LIBS + ARROW_FLIGHT_TESTING_LIB_DIR + ARROW_FLIGHT_TESTING_SHARED_IMP_LIB + ARROW_FLIGHT_TESTING_SHARED_LIB + ARROW_FLIGHT_TESTING_STATIC_LIB + ARROW_FLIGHT_TESTING_VERSION + ARROW_FLIGHT_TESTING_VERSION_MATCH) + +find_package_handle_standard_args( + ArrowFlightTesting + REQUIRED_VARS ARROW_FLIGHT_TESTING_INCLUDE_DIR ARROW_FLIGHT_TESTING_LIB_DIR + ARROW_FLIGHT_TESTING_VERSION_MATCH + VERSION_VAR ARROW_FLIGHT_TESTING_VERSION) +set(ARROW_FLIGHT_TESTING_FOUND ${ArrowFlightTesting_FOUND}) + +if(ArrowFlightTesting_FOUND AND NOT ArrowFlightTesting_FIND_QUIETLY) + message(STATUS "Found the Arrow Flight testing by ${ARROW_FLIGHT_TESTING_FIND_APPROACH}" + ) + message(STATUS "Found the Arrow Flight testing shared library: ${ARROW_FLIGHT_TESTING_SHARED_LIB}" + ) + message(STATUS "Found the Arrow Flight testing import library: ${ARROW_FLIGHT_TESTING_IMPORT_LIB}" + ) + message(STATUS "Found the Arrow Flight testing static library: ${ARROW_FLIGHT_TESTING_STATIC_LIB}" + ) +endif() diff --git a/src/arrow/cpp/cmake_modules/FindArrowPython.cmake b/src/arrow/cpp/cmake_modules/FindArrowPython.cmake new file mode 100644 index 000000000..b503e6a9e --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindArrowPython.cmake @@ -0,0 +1,87 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# - Find Arrow Python (arrow/python/api.h, libarrow_python.a, libarrow_python.so) +# +# This module requires Arrow from which it uses +# arrow_find_package() +# +# This module defines +# ARROW_PYTHON_FOUND, whether Arrow Python has been found +# ARROW_PYTHON_IMPORT_LIB, +# path to libarrow_python's import library (Windows only) +# ARROW_PYTHON_INCLUDE_DIR, directory containing headers +# ARROW_PYTHON_LIB_DIR, directory containing Arrow Python libraries +# ARROW_PYTHON_SHARED_LIB, path to libarrow_python's shared library +# ARROW_PYTHON_STATIC_LIB, path to libarrow_python.a + +if(DEFINED ARROW_PYTHON_FOUND) + return() +endif() + +set(find_package_arguments) +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION) + list(APPEND find_package_arguments "${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION}") +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) + list(APPEND find_package_arguments REQUIRED) +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) + list(APPEND find_package_arguments QUIET) +endif() +find_package(Arrow ${find_package_arguments}) + +if(ARROW_FOUND) + arrow_find_package(ARROW_PYTHON + "${ARROW_HOME}" + arrow_python + arrow/python/api.h + ArrowPython + arrow-python) + if(NOT ARROW_PYTHON_VERSION) + set(ARROW_PYTHON_VERSION "${ARROW_VERSION}") + endif() +endif() + +if("${ARROW_PYTHON_VERSION}" VERSION_EQUAL "${ARROW_VERSION}") + set(ARROW_PYTHON_VERSION_MATCH TRUE) +else() + set(ARROW_PYTHON_VERSION_MATCH FALSE) +endif() + +mark_as_advanced(ARROW_PYTHON_IMPORT_LIB + ARROW_PYTHON_INCLUDE_DIR + ARROW_PYTHON_LIBS + ARROW_PYTHON_LIB_DIR + ARROW_PYTHON_SHARED_IMP_LIB + ARROW_PYTHON_SHARED_LIB + ARROW_PYTHON_STATIC_LIB + ARROW_PYTHON_VERSION + ARROW_PYTHON_VERSION_MATCH) + +find_package_handle_standard_args( + ArrowPython + REQUIRED_VARS ARROW_PYTHON_INCLUDE_DIR ARROW_PYTHON_LIB_DIR ARROW_PYTHON_VERSION_MATCH + VERSION_VAR ARROW_PYTHON_VERSION) +set(ARROW_PYTHON_FOUND ${ArrowPython_FOUND}) + +if(ArrowPython_FOUND AND NOT ArrowPython_FIND_QUIETLY) + message(STATUS "Found the Arrow Python by ${ARROW_PYTHON_FIND_APPROACH}") + message(STATUS "Found the Arrow Python shared library: ${ARROW_PYTHON_SHARED_LIB}") + message(STATUS "Found the Arrow Python import library: ${ARROW_PYTHON_IMPORT_LIB}") + message(STATUS "Found the Arrow Python static library: ${ARROW_PYTHON_STATIC_LIB}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindArrowPythonFlight.cmake b/src/arrow/cpp/cmake_modules/FindArrowPythonFlight.cmake new file mode 100644 index 000000000..3a639928c --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindArrowPythonFlight.cmake @@ -0,0 +1,94 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# - Find Arrow Python Flight +# (arrow/python/flight.h, libarrow_python_flight.a, libarrow_python_flight.so) +# +# This module requires Arrow from which it uses +# arrow_find_package() +# +# This module defines +# ARROW_PYTHON_FLIGHT_FOUND, whether Arrow Python Flight has been found +# ARROW_PYTHON_FLIGHT_IMPORT_LIB, +# path to libarrow_python_flight's import library (Windows only) +# ARROW_PYTHON_FLIGHT_INCLUDE_DIR, directory containing headers +# ARROW_PYTHON_FLIGHT_LIB_DIR, +# directory containing Arrow Python Flight libraries +# ARROW_PYTHON_FLIGHT_SHARED_LIB, path to libarrow_python_flight's shared library +# ARROW_PYTHON_FLIGHT_STATIC_LIB, path to libarrow_python_flight.a + +if(DEFINED ARROW_PYTHON_FLIGHT_FOUND) + return() +endif() + +set(find_package_arguments) +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION) + list(APPEND find_package_arguments "${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION}") +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) + list(APPEND find_package_arguments REQUIRED) +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) + list(APPEND find_package_arguments QUIET) +endif() +find_package(ArrowFlight ${find_package_arguments}) +find_package(ArrowPython ${find_package_arguments}) + +if(ARROW_PYTHON_FOUND AND ARROW_FLIGHT_FOUND) + arrow_find_package(ARROW_PYTHON_FLIGHT + "${ARROW_HOME}" + arrow_python_flight + arrow/python/flight.h + ArrowPythonFlight + arrow-python-flight) + if(NOT ARROW_PYTHON_FLIGHT_VERSION) + set(ARROW_PYTHON_FLIGHT_VERSION "${ARROW_VERSION}") + endif() +endif() + +if("${ARROW_PYTHON_FLIGHT_VERSION}" VERSION_EQUAL "${ARROW_VERSION}") + set(ARROW_PYTHON_FLIGHT_VERSION_MATCH TRUE) +else() + set(ARROW_PYTHON_FLIGHT_VERSION_MATCH FALSE) +endif() + +mark_as_advanced(ARROW_PYTHON_FLIGHT_IMPORT_LIB + ARROW_PYTHON_FLIGHT_INCLUDE_DIR + ARROW_PYTHON_FLIGHT_LIBS + ARROW_PYTHON_FLIGHT_LIB_DIR + ARROW_PYTHON_FLIGHT_SHARED_IMP_LIB + ARROW_PYTHON_FLIGHT_SHARED_LIB + ARROW_PYTHON_FLIGHT_STATIC_LIB + ARROW_PYTHON_FLIGHT_VERSION + ARROW_PYTHON_FLIGHT_VERSION_MATCH) + +find_package_handle_standard_args( + ArrowPythonFlight + REQUIRED_VARS ARROW_PYTHON_FLIGHT_INCLUDE_DIR ARROW_PYTHON_FLIGHT_LIB_DIR + ARROW_PYTHON_FLIGHT_VERSION_MATCH + VERSION_VAR ARROW_PYTHON_FLIGHT_VERSION) +set(ARROW_PYTHON_FLIGHT_FOUND ${ArrowPythonFlight_FOUND}) + +if(ArrowPythonFlight_FOUND AND NOT ArrowPythonFlight_FIND_QUIETLY) + message(STATUS "Found the Arrow Python Flight by ${ARROW_PYTHON_FLIGHT_FIND_APPROACH}") + message(STATUS "Found the Arrow Python Flight shared library: ${ARROW_PYTHON_FLIGHT_SHARED_LIB}" + ) + message(STATUS "Found the Arrow Python Flight import library: ${ARROW_PYTHON_FLIGHT_IMPORT_LIB}" + ) + message(STATUS "Found the Arrow Python Flight static library: ${ARROW_PYTHON_FLIGHT_STATIC_LIB}" + ) +endif() diff --git a/src/arrow/cpp/cmake_modules/FindArrowTesting.cmake b/src/arrow/cpp/cmake_modules/FindArrowTesting.cmake new file mode 100644 index 000000000..c405003ad --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindArrowTesting.cmake @@ -0,0 +1,89 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# - Find Arrow testing library +# (arrow/testing/util.h, libarrow_testing.a, libarrow_testing.so) +# +# This module requires Arrow from which it uses +# arrow_find_package() +# +# This module defines +# ARROW_TESTING_FOUND, whether Arrow testing library has been found +# ARROW_TESTING_IMPORT_LIB, +# path to libarrow_testing's import library (Windows only) +# ARROW_TESTING_INCLUDE_DIR, directory containing headers +# ARROW_TESTING_LIB_DIR, directory containing Arrow testing libraries +# ARROW_TESTING_SHARED_LIB, path to libarrow_testing's shared library +# ARROW_TESTING_STATIC_LIB, path to libarrow_testing.a + +if(DEFINED ARROW_TESTING_FOUND) + return() +endif() + +set(find_package_arguments) +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION) + list(APPEND find_package_arguments "${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION}") +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) + list(APPEND find_package_arguments REQUIRED) +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) + list(APPEND find_package_arguments QUIET) +endif() +find_package(Arrow ${find_package_arguments}) + +if(ARROW_FOUND) + arrow_find_package(ARROW_TESTING + "${ARROW_HOME}" + arrow_testing + arrow/testing/util.h + ArrowTesting + arrow-testing) + if(NOT ARROW_TESTING_VERSION) + set(ARROW_TESTING_VERSION "${ARROW_VERSION}") + endif() +endif() + +if("${ARROW_TESTING_VERSION}" VERSION_EQUAL "${ARROW_VERSION}") + set(ARROW_TESTING_VERSION_MATCH TRUE) +else() + set(ARROW_TESTING_VERSION_MATCH FALSE) +endif() + +mark_as_advanced(ARROW_TESTING_IMPORT_LIB + ARROW_TESTING_INCLUDE_DIR + ARROW_TESTING_LIBS + ARROW_TESTING_LIB_DIR + ARROW_TESTING_SHARED_IMP_LIB + ARROW_TESTING_SHARED_LIB + ARROW_TESTING_STATIC_LIB + ARROW_TESTING_VERSION + ARROW_TESTING_VERSION_MATCH) + +find_package_handle_standard_args( + ArrowTesting + REQUIRED_VARS ARROW_TESTING_INCLUDE_DIR ARROW_TESTING_LIB_DIR + ARROW_TESTING_VERSION_MATCH + VERSION_VAR ARROW_TESTING_VERSION) +set(ARROW_TESTING_FOUND ${ArrowTesting_FOUND}) + +if(ArrowTesting_FOUND AND NOT ArrowTesting_FIND_QUIETLY) + message(STATUS "Found the Arrow testing by ${ARROW_TESTING_FIND_APPROACH}") + message(STATUS "Found the Arrow testing shared library: ${ARROW_TESTING_SHARED_LIB}") + message(STATUS "Found the Arrow testing import library: ${ARROW_TESTING_IMPORT_LIB}") + message(STATUS "Found the Arrow testing static library: ${ARROW_TESTING_STATIC_LIB}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindBoostAlt.cmake b/src/arrow/cpp/cmake_modules/FindBoostAlt.cmake new file mode 100644 index 000000000..177193712 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindBoostAlt.cmake @@ -0,0 +1,63 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +if(DEFINED ENV{BOOST_ROOT} OR DEFINED BOOST_ROOT) + # In older versions of CMake (such as 3.2), the system paths for Boost will + # be looked in first even if we set $BOOST_ROOT or pass -DBOOST_ROOT + set(Boost_NO_SYSTEM_PATHS ON) +endif() + +set(BoostAlt_FIND_VERSION_OPTIONS) +if(BoostAlt_FIND_VERSION) + list(APPEND BoostAlt_FIND_VERSION_OPTIONS ${BoostAlt_FIND_VERSION}) +endif() +if(BoostAlt_FIND_REQUIRED) + list(APPEND BoostAlt_FIND_VERSION_OPTIONS REQUIRED) +endif() +if(BoostAlt_FIND_QUIETLY) + list(APPEND BoostAlt_FIND_VERSION_OPTIONS QUIET) +endif() + +if(ARROW_BOOST_USE_SHARED) + # Find shared Boost libraries. + set(Boost_USE_STATIC_LIBS OFF) + set(BUILD_SHARED_LIBS_KEEP ${BUILD_SHARED_LIBS}) + set(BUILD_SHARED_LIBS ON) + + find_package(Boost ${BoostAlt_FIND_VERSION_OPTIONS} COMPONENTS system filesystem) + set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_KEEP}) + unset(BUILD_SHARED_LIBS_KEEP) +else() + # Find static boost headers and libs + # TODO Differentiate here between release and debug builds + set(Boost_USE_STATIC_LIBS ON) + find_package(Boost ${BoostAlt_FIND_VERSION_OPTIONS} COMPONENTS system filesystem) +endif() + +if(Boost_FOUND) + set(BoostAlt_FOUND ON) + if(MSVC_TOOLCHAIN) + # disable autolinking in boost + add_definitions(-DBOOST_ALL_NO_LIB) + if(ARROW_BOOST_USE_SHARED) + # force all boost libraries to dynamic link + add_definitions(-DBOOST_ALL_DYN_LINK) + endif() + endif() +else() + set(BoostAlt_FOUND OFF) +endif() diff --git a/src/arrow/cpp/cmake_modules/FindBrotli.cmake b/src/arrow/cpp/cmake_modules/FindBrotli.cmake new file mode 100644 index 000000000..e2670b51a --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindBrotli.cmake @@ -0,0 +1,130 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Tries to find Brotli headers and libraries. +# +# Usage of this module as follows: +# +# find_package(Brotli) + +if(ARROW_BROTLI_USE_SHARED) + set(BROTLI_COMMON_LIB_NAMES + brotlicommon + ${CMAKE_SHARED_LIBRARY_PREFIX}brotlicommon${CMAKE_SHARED_LIBRARY_SUFFIX}) + + set(BROTLI_ENC_LIB_NAMES + brotlienc ${CMAKE_SHARED_LIBRARY_PREFIX}brotlienc${CMAKE_SHARED_LIBRARY_SUFFIX}) + + set(BROTLI_DEC_LIB_NAMES + brotlidec ${CMAKE_SHARED_LIBRARY_PREFIX}brotlidec${CMAKE_SHARED_LIBRARY_SUFFIX}) +else() + set(BROTLI_COMMON_LIB_NAMES + brotlicommon-static + ${CMAKE_STATIC_LIBRARY_PREFIX}brotlicommon-static${CMAKE_STATIC_LIBRARY_SUFFIX} + ${CMAKE_STATIC_LIBRARY_PREFIX}brotlicommon_static${CMAKE_STATIC_LIBRARY_SUFFIX} + ${CMAKE_STATIC_LIBRARY_PREFIX}brotlicommon${CMAKE_STATIC_LIBRARY_SUFFIX}) + + set(BROTLI_ENC_LIB_NAMES + brotlienc-static + ${CMAKE_STATIC_LIBRARY_PREFIX}brotlienc-static${CMAKE_STATIC_LIBRARY_SUFFIX} + ${CMAKE_STATIC_LIBRARY_PREFIX}brotlienc_static${CMAKE_STATIC_LIBRARY_SUFFIX} + ${CMAKE_STATIC_LIBRARY_PREFIX}brotlienc${CMAKE_STATIC_LIBRARY_SUFFIX}) + + set(BROTLI_DEC_LIB_NAMES + brotlidec-static + ${CMAKE_STATIC_LIBRARY_PREFIX}brotlidec-static${CMAKE_STATIC_LIBRARY_SUFFIX} + ${CMAKE_STATIC_LIBRARY_PREFIX}brotlidec_static${CMAKE_STATIC_LIBRARY_SUFFIX} + ${CMAKE_STATIC_LIBRARY_PREFIX}brotlidec${CMAKE_STATIC_LIBRARY_SUFFIX}) +endif() + +if(BROTLI_ROOT) + find_library(BROTLI_COMMON_LIBRARY + NAMES ${BROTLI_COMMON_LIB_NAMES} + PATHS ${BROTLI_ROOT} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) + find_library(BROTLI_ENC_LIBRARY + NAMES ${BROTLI_ENC_LIB_NAMES} + PATHS ${BROTLI_ROOT} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) + find_library(BROTLI_DEC_LIBRARY + NAMES ${BROTLI_DEC_LIB_NAMES} + PATHS ${BROTLI_ROOT} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) + find_path(BROTLI_INCLUDE_DIR + NAMES brotli/decode.h + PATHS ${BROTLI_ROOT} + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES} + NO_DEFAULT_PATH) +else() + find_package(PkgConfig QUIET) + pkg_check_modules(BROTLI_PC libbrotlicommon libbrotlienc libbrotlidec) + if(BROTLI_PC_FOUND) + set(BROTLI_INCLUDE_DIR "${BROTLI_PC_libbrotlicommon_INCLUDEDIR}") + + # Some systems (e.g. Fedora) don't fill Brotli_LIBRARY_DIRS, so add the other dirs here. + list(APPEND BROTLI_PC_LIBRARY_DIRS "${BROTLI_PC_libbrotlicommon_LIBDIR}") + list(APPEND BROTLI_PC_LIBRARY_DIRS "${BROTLI_PC_libbrotlienc_LIBDIR}") + list(APPEND BROTLI_PC_LIBRARY_DIRS "${BROTLI_PC_libbrotlidec_LIBDIR}") + + find_library(BROTLI_COMMON_LIBRARY + NAMES ${BROTLI_COMMON_LIB_NAMES} + PATHS ${BROTLI_PC_LIBRARY_DIRS} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) + find_library(BROTLI_ENC_LIBRARY + NAMES ${BROTLI_ENC_LIB_NAMES} + PATHS ${BROTLI_PC_LIBRARY_DIRS} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) + find_library(BROTLI_DEC_LIBRARY + NAMES ${BROTLI_DEC_LIB_NAMES} + PATHS ${BROTLI_PC_LIBRARY_DIRS} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) + else() + find_library(BROTLI_COMMON_LIBRARY + NAMES ${BROTLI_COMMON_LIB_NAMES} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES}) + find_library(BROTLI_ENC_LIBRARY + NAMES ${BROTLI_ENC_LIB_NAMES} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES}) + find_library(BROTLI_DEC_LIBRARY + NAMES ${BROTLI_DEC_LIB_NAMES} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES}) + find_path(BROTLI_INCLUDE_DIR + NAMES brotli/decode.h + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) + endif() +endif() + +find_package_handle_standard_args( + Brotli REQUIRED_VARS BROTLI_COMMON_LIBRARY BROTLI_ENC_LIBRARY BROTLI_DEC_LIBRARY + BROTLI_INCLUDE_DIR) +if(Brotli_FOUND OR BROTLI_FOUND) + set(Brotli_FOUND TRUE) + add_library(Brotli::brotlicommon UNKNOWN IMPORTED) + set_target_properties(Brotli::brotlicommon + PROPERTIES IMPORTED_LOCATION "${BROTLI_COMMON_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${BROTLI_INCLUDE_DIR}") + add_library(Brotli::brotlienc UNKNOWN IMPORTED) + set_target_properties(Brotli::brotlienc + PROPERTIES IMPORTED_LOCATION "${BROTLI_ENC_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${BROTLI_INCLUDE_DIR}") + add_library(Brotli::brotlidec UNKNOWN IMPORTED) + set_target_properties(Brotli::brotlidec + PROPERTIES IMPORTED_LOCATION "${BROTLI_DEC_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${BROTLI_INCLUDE_DIR}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindClangTools.cmake b/src/arrow/cpp/cmake_modules/FindClangTools.cmake new file mode 100644 index 000000000..52fc59895 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindClangTools.cmake @@ -0,0 +1,106 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Tries to find the clang-tidy and clang-format modules +# +# Usage of this module as follows: +# +# find_package(ClangTools) +# +# Variables used by this module which can change the default behaviour and need +# to be set before calling find_package: +# +# CLANG_FORMAT_VERSION - +# The version of clang-format to find. If this is not specified, clang-format +# will not be searched for. +# +# ClangTools_PATH - +# When set, this path is inspected in addition to standard library binary locations +# to find clang-tidy and clang-format +# +# This module defines +# CLANG_TIDY_BIN, The path to the clang tidy binary +# CLANG_TIDY_FOUND, Whether clang tidy was found +# CLANG_FORMAT_BIN, The path to the clang format binary +# CLANG_FORMAT_FOUND, Whether clang format was found + +set(CLANG_TOOLS_SEARCH_PATHS + ${ClangTools_PATH} + $ENV{CLANG_TOOLS_PATH} + /usr/local/bin + /usr/bin + "C:/Program Files/LLVM/bin" # Windows, non-conda + "$ENV{CONDA_PREFIX}/Library/bin") # Windows, conda +if(CLANG_TOOLS_BREW_PREFIX) + list(APPEND CLANG_TOOLS_SEARCH_PATHS "${CLANG_TOOLS_BREW}/bin") +endif() + +function(FIND_CLANG_TOOL NAME OUTPUT VERSION_CHECK_PATTERN) + unset(CLANG_TOOL_BIN CACHE) + find_program(CLANG_TOOL_BIN + NAMES ${NAME}-${ARROW_CLANG_TOOLS_VERSION} + ${NAME}-${ARROW_CLANG_TOOLS_VERSION_MAJOR} + PATHS ${CLANG_TOOLS_SEARCH_PATHS} + NO_DEFAULT_PATH) + if(NOT CLANG_TOOL_BIN) + # try searching for non-versioned tool and check the version + find_program(CLANG_TOOL_BIN + NAMES ${NAME} + PATHS ${CLANG_TOOLS_SEARCH_PATHS} + NO_DEFAULT_PATH) + if(CLANG_TOOL_BIN) + unset(CLANG_TOOL_VERSION_MESSAGE) + execute_process(COMMAND ${CLANG_TOOL_BIN} "-version" + OUTPUT_VARIABLE CLANG_TOOL_VERSION_MESSAGE + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT (${CLANG_TOOL_VERSION_MESSAGE} MATCHES ${VERSION_CHECK_PATTERN})) + set(CLANG_TOOL_BIN "CLANG_TOOL_BIN-NOTFOUND") + endif() + endif() + endif() + if(CLANG_TOOL_BIN) + set(${OUTPUT} + ${CLANG_TOOL_BIN} + PARENT_SCOPE) + else() + set(${OUTPUT} + "${OUTPUT}-NOTFOUND" + PARENT_SCOPE) + endif() +endfunction() + +string(REGEX REPLACE "\\." "\\\\." ARROW_CLANG_TOOLS_VERSION_ESCAPED + "${ARROW_CLANG_TOOLS_VERSION}") + +find_clang_tool(clang-tidy CLANG_TIDY_BIN + "LLVM version ${ARROW_CLANG_TOOLS_VERSION_ESCAPED}") +if(CLANG_TIDY_BIN) + set(CLANG_TIDY_FOUND 1) + message(STATUS "clang-tidy found at ${CLANG_TIDY_BIN}") +else() + set(CLANG_TIDY_FOUND 0) + message(STATUS "clang-tidy not found") +endif() + +find_clang_tool(clang-format CLANG_FORMAT_BIN + "^clang-format version ${ARROW_CLANG_TOOLS_VERSION_ESCAPED}") +if(CLANG_FORMAT_BIN) + set(CLANG_FORMAT_FOUND 1) + message(STATUS "clang-format found at ${CLANG_FORMAT_BIN}") +else() + set(CLANG_FORMAT_FOUND 0) + message(STATUS "clang-format not found") +endif() + +find_package_handle_standard_args(ClangTools REQUIRED_VARS CLANG_FORMAT_BIN + CLANG_TIDY_BIN) diff --git a/src/arrow/cpp/cmake_modules/FindGLOG.cmake b/src/arrow/cpp/cmake_modules/FindGLOG.cmake new file mode 100644 index 000000000..d67eb0056 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindGLOG.cmake @@ -0,0 +1,56 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Tries to find GLog headers and libraries. +# +# Usage of this module as follows: +# +# find_package(GLOG) + +find_package(PkgConfig QUIET) +pkg_check_modules(GLOG_PC libglog) +if(GLOG_PC_FOUND) + set(GLOG_INCLUDE_DIR "${GLOG_PC_INCLUDEDIR}") + list(APPEND GLOG_PC_LIBRARY_DIRS "${GLOG_PC_LIBDIR}") + find_library(GLOG_LIB glog + PATHS ${GLOG_PC_LIBRARY_DIRS} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) +elseif(GLOG_ROOT) + find_library(GLOG_LIB + NAMES glog + PATHS ${GLOG_ROOT} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) + find_path(GLOG_INCLUDE_DIR + NAMES glog/logging.h + PATHS ${GLOG_ROOT} + NO_DEFAULT_PATH + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) +else() + find_library(GLOG_LIB + NAMES glog + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES}) + find_path(GLOG_INCLUDE_DIR + NAMES glog/logging.h + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) +endif() + +find_package_handle_standard_args(GLOG REQUIRED_VARS GLOG_INCLUDE_DIR GLOG_LIB) + +if(GLOG_FOUND) + add_library(glog::glog UNKNOWN IMPORTED) + set_target_properties(glog::glog + PROPERTIES IMPORTED_LOCATION "${GLOG_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${GLOG_INCLUDE_DIR}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindGandiva.cmake b/src/arrow/cpp/cmake_modules/FindGandiva.cmake new file mode 100644 index 000000000..c533abed7 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindGandiva.cmake @@ -0,0 +1,94 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# - Find Gandiva (gandiva/arrow.h, libgandiva.a, libgandiva.so) +# +# This module requires Arrow from which it uses +# arrow_find_package() +# +# This module defines +# GANDIVA_FOUND, whether Gandiva has been found +# GANDIVA_IMPORT_LIB, path to libgandiva's import library (Windows only) +# GANDIVA_INCLUDE_DIR, directory containing headers +# GANDIVA_LIBS, deprecated. Use GANDIVA_LIB_DIR instead +# GANDIVA_LIB_DIR, directory containing Gandiva libraries +# GANDIVA_SHARED_IMP_LIB, deprecated. Use GANDIVA_IMPORT_LIB instead +# GANDIVA_SHARED_LIB, path to libgandiva's shared library +# GANDIVA_SO_VERSION, shared object version of found Gandiva such as "100" +# GANDIVA_STATIC_LIB, path to libgandiva.a + +if(DEFINED GANDIVA_FOUND) + return() +endif() + +set(find_package_arguments) +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION) + list(APPEND find_package_arguments "${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION}") +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) + list(APPEND find_package_arguments REQUIRED) +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) + list(APPEND find_package_arguments QUIET) +endif() +find_package(Arrow ${find_package_arguments}) + +if(ARROW_FOUND) + arrow_find_package(GANDIVA + "${ARROW_HOME}" + gandiva + gandiva/arrow.h + Gandiva + gandiva) + if(NOT GANDIVA_VERSION) + set(GANDIVA_VERSION "${ARROW_VERSION}") + endif() + set(GANDIVA_ABI_VERSION "${ARROW_ABI_VERSION}") + set(GANDIVA_SO_VERSION "${ARROW_SO_VERSION}") +endif() + +if("${GANDIVA_VERSION}" VERSION_EQUAL "${ARROW_VERSION}") + set(GANDIVA_VERSION_MATCH TRUE) +else() + set(GANDIVA_VERSION_MATCH FALSE) +endif() + +mark_as_advanced(GANDIVA_ABI_VERSION + GANDIVA_IMPORT_LIB + GANDIVA_INCLUDE_DIR + GANDIVA_LIBS + GANDIVA_LIB_DIR + GANDIVA_SHARED_IMP_LIB + GANDIVA_SHARED_LIB + GANDIVA_SO_VERSION + GANDIVA_STATIC_LIB + GANDIVA_VERSION + GANDIVA_VERSION_MATCH) + +find_package_handle_standard_args( + Gandiva + REQUIRED_VARS GANDIVA_INCLUDE_DIR GANDIVA_LIB_DIR GANDIVA_SO_VERSION + GANDIVA_VERSION_MATCH + VERSION_VAR GANDIVA_VERSION) +set(GANDIVA_FOUND ${Gandiva_FOUND}) + +if(Gandiva_FOUND AND NOT Gandiva_FIND_QUIETLY) + message(STATUS "Found the Gandiva by ${GANDIVA_FIND_APPROACH}") + message(STATUS "Found the Gandiva shared library: ${GANDIVA_SHARED_LIB}") + message(STATUS "Found the Gandiva import library: ${GANDIVA_IMPORT_LIB}") + message(STATUS "Found the Gandiva static library: ${GANDIVA_STATIC_LIB}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindInferTools.cmake b/src/arrow/cpp/cmake_modules/FindInferTools.cmake new file mode 100644 index 000000000..c4b65653a --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindInferTools.cmake @@ -0,0 +1,47 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Tries to find the infer module +# +# Usage of this module as follows: +# +# find_package(InferTools) +# +# Variables used by this module, they can change the default behaviour and need +# to be set before calling find_package: +# +# InferTools_PATH - +# When set, this path is inspected instead of standard library binary locations +# to find infer +# +# This module defines +# INFER_BIN, The path to the infer binary +# INFER_FOUND, Whether infer was found + +find_program(INFER_BIN + NAMES infer + PATHS ${InferTools_PATH} + $ENV{INFER_TOOLS_PATH} + /usr/local/bin + /usr/bin + /usr/local/homebrew/bin + /opt/local/bin + NO_DEFAULT_PATH) + +if("${INFER_BIN}" STREQUAL "INFER_BIN-NOTFOUND") + set(INFER_FOUND 0) + message(STATUS "infer not found") +else() + set(INFER_FOUND 1) + message(STATUS "infer found at ${INFER_BIN}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindLLVMAlt.cmake b/src/arrow/cpp/cmake_modules/FindLLVMAlt.cmake new file mode 100644 index 000000000..380f2d47c --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindLLVMAlt.cmake @@ -0,0 +1,76 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +# Usage of this module as follows: +# +# find_package(LLVMAlt) + +set(LLVM_HINTS ${LLVM_ROOT} ${LLVM_DIR} /usr/lib /usr/share) +if(LLVM_BREW_PREFIX) + list(APPEND LLVM_HINTS ${LLVM_BREW_PREFIX}) +endif() +foreach(ARROW_LLVM_VERSION ${ARROW_LLVM_VERSIONS}) + find_package(LLVM + ${ARROW_LLVM_VERSION} + CONFIG + HINTS + ${LLVM_HINTS}) + if(LLVM_FOUND) + break() + endif() +endforeach() + +if(LLVM_FOUND) + # Find the libraries that correspond to the LLVM components + llvm_map_components_to_libnames(LLVM_LIBS + core + mcjit + native + ipo + bitreader + target + linker + analysis + debuginfodwarf) + + find_program(LLVM_LINK_EXECUTABLE llvm-link HINTS ${LLVM_TOOLS_BINARY_DIR}) + + find_program(CLANG_EXECUTABLE + NAMES clang-${LLVM_PACKAGE_VERSION} + clang-${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR} + clang-${LLVM_VERSION_MAJOR} clang + HINTS ${LLVM_TOOLS_BINARY_DIR}) + + add_library(LLVM::LLVM_INTERFACE INTERFACE IMPORTED) + + set_target_properties(LLVM::LLVM_INTERFACE + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LLVM_INCLUDE_DIRS}" + INTERFACE_COMPILE_FLAGS "${LLVM_DEFINITIONS}" + INTERFACE_LINK_LIBRARIES "${LLVM_LIBS}") +endif() + +mark_as_advanced(CLANG_EXECUTABLE LLVM_LINK_EXECUTABLE) + +find_package_handle_standard_args( + LLVMAlt + REQUIRED_VARS # The first variable is used for display. + LLVM_PACKAGE_VERSION CLANG_EXECUTABLE LLVM_FOUND LLVM_LINK_EXECUTABLE) +if(LLVMAlt_FOUND) + message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + message(STATUS "Found llvm-link ${LLVM_LINK_EXECUTABLE}") + message(STATUS "Found clang ${CLANG_EXECUTABLE}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindLz4.cmake b/src/arrow/cpp/cmake_modules/FindLz4.cmake new file mode 100644 index 000000000..bc8051fe9 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindLz4.cmake @@ -0,0 +1,84 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +if(MSVC_TOOLCHAIN AND NOT DEFINED LZ4_MSVC_LIB_PREFIX) + set(LZ4_MSVC_LIB_PREFIX "lib") +endif() +set(LZ4_LIB_NAME_BASE "${LZ4_MSVC_LIB_PREFIX}lz4") + +if(ARROW_LZ4_USE_SHARED) + set(LZ4_LIB_NAMES) + if(CMAKE_IMPORT_LIBRARY_SUFFIX) + list(APPEND + LZ4_LIB_NAMES + "${CMAKE_IMPORT_LIBRARY_PREFIX}${LZ4_LIB_NAME_BASE}${CMAKE_IMPORT_LIBRARY_SUFFIX}" + ) + endif() + list(APPEND LZ4_LIB_NAMES + "${CMAKE_SHARED_LIBRARY_PREFIX}${LZ4_LIB_NAME_BASE}${CMAKE_SHARED_LIBRARY_SUFFIX}") +else() + if(MSVC AND NOT DEFINED LZ4_MSVC_STATIC_LIB_SUFFIX) + set(LZ4_MSVC_STATIC_LIB_SUFFIX "_static") + endif() + set(LZ4_STATIC_LIB_SUFFIX "${LZ4_MSVC_STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}") + set(LZ4_LIB_NAMES + "${CMAKE_STATIC_LIBRARY_PREFIX}${LZ4_LIB_NAME_BASE}${LZ4_STATIC_LIB_SUFFIX}") +endif() + +if(LZ4_ROOT) + find_library(LZ4_LIB + NAMES ${LZ4_LIB_NAMES} + PATHS ${LZ4_ROOT} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) + find_path(LZ4_INCLUDE_DIR + NAMES lz4.h + PATHS ${LZ4_ROOT} + NO_DEFAULT_PATH + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) + +else() + find_package(PkgConfig QUIET) + pkg_check_modules(LZ4_PC liblz4) + if(LZ4_PC_FOUND) + set(LZ4_INCLUDE_DIR "${LZ4_PC_INCLUDEDIR}") + + list(APPEND LZ4_PC_LIBRARY_DIRS "${LZ4_PC_LIBDIR}") + find_library(LZ4_LIB + NAMES ${LZ4_LIB_NAMES} + PATHS ${LZ4_PC_LIBRARY_DIRS} + NO_DEFAULT_PATH + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES}) + else() + find_library(LZ4_LIB + NAMES ${LZ4_LIB_NAMES} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES}) + find_path(LZ4_INCLUDE_DIR + NAMES lz4.h + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) + endif() +endif() + +find_package_handle_standard_args(Lz4 REQUIRED_VARS LZ4_LIB LZ4_INCLUDE_DIR) + +if(Lz4_FOUND) + set(Lz4_FOUND TRUE) + add_library(LZ4::lz4 UNKNOWN IMPORTED) + set_target_properties(LZ4::lz4 + PROPERTIES IMPORTED_LOCATION "${LZ4_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${LZ4_INCLUDE_DIR}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindNumPy.cmake b/src/arrow/cpp/cmake_modules/FindNumPy.cmake new file mode 100644 index 000000000..c3daba149 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindNumPy.cmake @@ -0,0 +1,96 @@ +# - Find the NumPy libraries +# This module finds if NumPy is installed, and sets the following variables +# indicating where it is. +# +# TODO: Update to provide the libraries and paths for linking npymath lib. +# +# NUMPY_FOUND - was NumPy found +# NUMPY_VERSION - the version of NumPy found as a string +# NUMPY_VERSION_MAJOR - the major version number of NumPy +# NUMPY_VERSION_MINOR - the minor version number of NumPy +# NUMPY_VERSION_PATCH - the patch version number of NumPy +# NUMPY_VERSION_DECIMAL - e.g. version 1.6.1 is 10601 +# NUMPY_INCLUDE_DIRS - path to the NumPy include files + +#============================================================================ +# Copyright 2012 Continuum Analytics, Inc. +# +# MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +#============================================================================ + +# Legacy code for CMake < 3.15.0. The primary point of entry should be +# FindPython3Alt.cmake. + +if(NOT PYTHONINTERP_FOUND) + set(NUMPY_FOUND FALSE) + return() +endif() + +execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" + "import numpy as n; print(n.__version__); print(n.get_include());" + RESULT_VARIABLE _NUMPY_SEARCH_SUCCESS + OUTPUT_VARIABLE _NUMPY_VALUES_OUTPUT + ERROR_VARIABLE _NUMPY_ERROR_VALUE + OUTPUT_STRIP_TRAILING_WHITESPACE) + +if(NOT _NUMPY_SEARCH_SUCCESS MATCHES 0) + if(NumPy_FIND_REQUIRED) + message(FATAL_ERROR + "NumPy import failure:\n${_NUMPY_ERROR_VALUE}") + endif() + set(NUMPY_FOUND FALSE) + return() +endif() + +# Convert the process output into a list +string(REGEX REPLACE ";" "\\\\;" _NUMPY_VALUES ${_NUMPY_VALUES_OUTPUT}) +string(REGEX REPLACE "\n" ";" _NUMPY_VALUES ${_NUMPY_VALUES}) +list(GET _NUMPY_VALUES 0 NUMPY_VERSION) +list(GET _NUMPY_VALUES 1 NUMPY_INCLUDE_DIRS) + +string(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" _VER_CHECK "${NUMPY_VERSION}") +if("${_VER_CHECK}" STREQUAL "") + # The output from Python was unexpected. Raise an error always + # here, because we found NumPy, but it appears to be corrupted somehow. + message(FATAL_ERROR + "Requested version and include path from NumPy, got instead:\n${_NUMPY_VALUES_OUTPUT}\n") + return() +endif() + +# Make sure all directory separators are '/' +string(REGEX REPLACE "\\\\" "/" NUMPY_INCLUDE_DIRS ${NUMPY_INCLUDE_DIRS}) + +# Get the major and minor version numbers +string(REGEX REPLACE "\\." ";" _NUMPY_VERSION_LIST ${NUMPY_VERSION}) +list(GET _NUMPY_VERSION_LIST 0 NUMPY_VERSION_MAJOR) +list(GET _NUMPY_VERSION_LIST 1 NUMPY_VERSION_MINOR) +list(GET _NUMPY_VERSION_LIST 2 NUMPY_VERSION_PATCH) +string(REGEX MATCH "[0-9]*" NUMPY_VERSION_PATCH ${NUMPY_VERSION_PATCH}) +math(EXPR NUMPY_VERSION_DECIMAL + "(${NUMPY_VERSION_MAJOR} * 10000) + (${NUMPY_VERSION_MINOR} * 100) + ${NUMPY_VERSION_PATCH}") + +find_package_message(NUMPY + "Found NumPy: version \"${NUMPY_VERSION}\" ${NUMPY_INCLUDE_DIRS}" + "${NUMPY_INCLUDE_DIRS}${NUMPY_VERSION}") + +set(NUMPY_FOUND TRUE) diff --git a/src/arrow/cpp/cmake_modules/FindORC.cmake b/src/arrow/cpp/cmake_modules/FindORC.cmake new file mode 100644 index 000000000..d45b16078 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindORC.cmake @@ -0,0 +1,55 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# - Find Apache ORC C++ (orc/orc-config.h, liborc.a) +# This module defines +# ORC_INCLUDE_DIR, directory containing headers +# ORC_STATIC_LIB, path to liborc.a +# ORC_FOUND, whether orc has been found + +if(ORC_ROOT) + find_library(ORC_STATIC_LIB + NAMES orc + PATHS ${ORC_ROOT} + NO_DEFAULT_PATH + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES}) + find_path(ORC_INCLUDE_DIR + NAMES orc/orc-config.hh + PATHS ${ORC_ROOT} + NO_DEFAULT_PATH + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) +else() + find_library(ORC_STATIC_LIB + NAMES orc + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES}) + find_path(ORC_INCLUDE_DIR + NAMES orc/orc-config.hh + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) +endif() + +if(ORC_STATIC_LIB AND ORC_INCLUDE_DIR) + set(ORC_FOUND TRUE) + add_library(orc::liborc STATIC IMPORTED) + set_target_properties(orc::liborc + PROPERTIES IMPORTED_LOCATION "${ORC_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${ORC_INCLUDE_DIR}") +else() + if(ORC_FIND_REQUIRED) + message(FATAL_ERROR "ORC library was required in toolchain and unable to locate") + endif() + set(ORC_FOUND FALSE) +endif() diff --git a/src/arrow/cpp/cmake_modules/FindOpenSSLAlt.cmake b/src/arrow/cpp/cmake_modules/FindOpenSSLAlt.cmake new file mode 100644 index 000000000..603e7d066 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindOpenSSLAlt.cmake @@ -0,0 +1,54 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +if(ARROW_OPENSSL_USE_SHARED) + # Find shared OpenSSL libraries. + set(OpenSSL_USE_STATIC_LIBS OFF) + set(OPENSSL_USE_STATIC_LIBS OFF) + find_package(OpenSSL) +else() + # Find static OpenSSL headers and libs + set(OpenSSL_USE_STATIC_LIBS ON) + set(OPENSSL_USE_STATIC_LIBS ON) + find_package(OpenSSL) +endif() + +if(OPENSSL_FOUND) + message(STATUS "OpenSSL found with ${OPENSSL_VERSION} version") + if(OPENSSL_VERSION LESS "1.1.0") + message(SEND_ERROR "The OpenSSL must be greater than or equal to 1.1.0") + endif() +else() + message(SEND_ERROR "Not found the OpenSSL library") +endif() + +if(NOT GANDIVA_OPENSSL_LIBS) + if(WIN32) + if(CMAKE_VERSION VERSION_LESS 3.18) + set(GANDIVA_OPENSSL_LIBS OpenSSL::Crypto OpenSSL::SSL) + else() + set(GANDIVA_OPENSSL_LIBS OpenSSL::Crypto OpenSSL::SSL OpenSSL::applink) + endif() + else() + set(GANDIVA_OPENSSL_LIBS OpenSSL::Crypto OpenSSL::SSL) + endif() +endif() + +if(NOT GANDIVA_OPENSSL_INCLUDE_DIR) + set(GANDIVA_OPENSSL_INCLUDE_DIR ${OPENSSL_INCLUDE_DIR}) + message(STATUS "OpenSSL include dir: ${GANDIVA_OPENSSL_INCLUDE_DIR}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindParquet.cmake b/src/arrow/cpp/cmake_modules/FindParquet.cmake new file mode 100644 index 000000000..e071fc822 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindParquet.cmake @@ -0,0 +1,126 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# - Find Parquet (parquet/api/reader.h, libparquet.a, libparquet.so) +# +# This module requires Arrow from which it uses +# arrow_find_package() +# +# This module defines +# PARQUET_FOUND, whether Parquet has been found +# PARQUET_IMPORT_LIB, path to libparquet's import library (Windows only) +# PARQUET_INCLUDE_DIR, directory containing headers +# PARQUET_LIBS, deprecated. Use PARQUET_LIB_DIR instead +# PARQUET_LIB_DIR, directory containing Parquet libraries +# PARQUET_SHARED_IMP_LIB, deprecated. Use PARQUET_IMPORT_LIB instead +# PARQUET_SHARED_LIB, path to libparquet's shared library +# PARQUET_SO_VERSION, shared object version of found Parquet such as "100" +# PARQUET_STATIC_LIB, path to libparquet.a + +if(DEFINED PARQUET_FOUND) + return() +endif() + +set(find_package_arguments) +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION) + list(APPEND find_package_arguments "${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION}") +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) + list(APPEND find_package_arguments REQUIRED) +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) + list(APPEND find_package_arguments QUIET) +endif() +find_package(Arrow ${find_package_arguments}) + +if(NOT "$ENV{PARQUET_HOME}" STREQUAL "") + file(TO_CMAKE_PATH "$ENV{PARQUET_HOME}" PARQUET_HOME) +endif() + +if((NOT PARQUET_HOME) AND ARROW_HOME) + set(PARQUET_HOME ${ARROW_HOME}) +endif() + +if(ARROW_FOUND) + arrow_find_package(PARQUET + "${PARQUET_HOME}" + parquet + parquet/api/reader.h + Parquet + parquet) + if(PARQUET_HOME) + if(PARQUET_INCLUDE_DIR) + file(READ "${PARQUET_INCLUDE_DIR}/parquet/parquet_version.h" + PARQUET_VERSION_H_CONTENT) + arrow_extract_macro_value(PARQUET_VERSION_MAJOR "PARQUET_VERSION_MAJOR" + "${PARQUET_VERSION_H_CONTENT}") + arrow_extract_macro_value(PARQUET_VERSION_MINOR "PARQUET_VERSION_MINOR" + "${PARQUET_VERSION_H_CONTENT}") + arrow_extract_macro_value(PARQUET_VERSION_PATCH "PARQUET_VERSION_PATCH" + "${PARQUET_VERSION_H_CONTENT}") + if("${PARQUET_VERSION_MAJOR}" STREQUAL "" + OR "${PARQUET_VERSION_MINOR}" STREQUAL "" + OR "${PARQUET_VERSION_PATCH}" STREQUAL "") + set(PARQUET_VERSION "0.0.0") + else() + set(PARQUET_VERSION + "${PARQUET_VERSION_MAJOR}.${PARQUET_VERSION_MINOR}.${PARQUET_VERSION_PATCH}") + endif() + + arrow_extract_macro_value(PARQUET_SO_VERSION_QUOTED "PARQUET_SO_VERSION" + "${PARQUET_VERSION_H_CONTENT}") + string(REGEX REPLACE "^\"(.+)\"$" "\\1" PARQUET_SO_VERSION + "${PARQUET_SO_VERSION_QUOTED}") + arrow_extract_macro_value(PARQUET_FULL_SO_VERSION_QUOTED "PARQUET_FULL_SO_VERSION" + "${PARQUET_VERSION_H_CONTENT}") + string(REGEX REPLACE "^\"(.+)\"$" "\\1" PARQUET_FULL_SO_VERSION + "${PARQUET_FULL_SO_VERSION_QUOTED}") + endif() + else() + if(PARQUET_USE_CMAKE_PACKAGE_CONFIG) + find_package(Parquet CONFIG) + elseif(PARQUET_USE_PKG_CONFIG) + pkg_get_variable(PARQUET_SO_VERSION parquet so_version) + pkg_get_variable(PARQUET_FULL_SO_VERSION parquet full_so_version) + endif() + endif() + set(PARQUET_ABI_VERSION "${PARQUET_SO_VERSION}") +endif() + +mark_as_advanced(PARQUET_ABI_VERSION + PARQUET_IMPORT_LIB + PARQUET_INCLUDE_DIR + PARQUET_LIBS + PARQUET_LIB_DIR + PARQUET_SHARED_IMP_LIB + PARQUET_SHARED_LIB + PARQUET_SO_VERSION + PARQUET_STATIC_LIB + PARQUET_VERSION) + +find_package_handle_standard_args( + Parquet + REQUIRED_VARS PARQUET_INCLUDE_DIR PARQUET_LIB_DIR PARQUET_SO_VERSION + VERSION_VAR PARQUET_VERSION) +set(PARQUET_FOUND ${Parquet_FOUND}) + +if(Parquet_FOUND AND NOT Parquet_FIND_QUIETLY) + message(STATUS "Parquet version: ${PARQUET_VERSION} (${PARQUET_FIND_APPROACH})") + message(STATUS "Found the Parquet shared library: ${PARQUET_SHARED_LIB}") + message(STATUS "Found the Parquet import library: ${PARQUET_IMPORT_LIB}") + message(STATUS "Found the Parquet static library: ${PARQUET_STATIC_LIB}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindPlasma.cmake b/src/arrow/cpp/cmake_modules/FindPlasma.cmake new file mode 100644 index 000000000..2e634844c --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindPlasma.cmake @@ -0,0 +1,102 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# - Find Plasma (plasma/client.h, libplasma.a, libplasma.so) +# +# This module requires Arrow from which it uses +# arrow_find_package() +# +# This module defines +# PLASMA_EXECUTABLE, deprecated. Use PLASMA_STORE_SERVER instead +# PLASMA_FOUND, whether Plasma has been found +# PLASMA_IMPORT_LIB, path to libplasma's import library (Windows only) +# PLASMA_INCLUDE_DIR, directory containing headers +# PLASMA_LIBS, deprecated. Use PLASMA_LIB_DIR instead +# PLASMA_LIB_DIR, directory containing Plasma libraries +# PLASMA_SHARED_IMP_LIB, deprecated. Use PLASMA_IMPORT_LIB instead +# PLASMA_SHARED_LIB, path to libplasma's shared library +# PLASMA_SO_VERSION, shared object version of found Plasma such as "100" +# PLASMA_STATIC_LIB, path to libplasma.a +# PLASMA_STORE_SERVER, path to plasma-store-server + +if(DEFINED PLASMA_FOUND) + return() +endif() + +set(find_package_arguments) +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION) + list(APPEND find_package_arguments "${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION}") +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) + list(APPEND find_package_arguments REQUIRED) +endif() +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) + list(APPEND find_package_arguments QUIET) +endif() +find_package(Arrow ${find_package_arguments}) + +if(ARROW_FOUND) + arrow_find_package(PLASMA + "${ARROW_HOME}" + plasma + plasma/client.h + Plasma + plasma) + if(ARROW_HOME) + set(PLASMA_STORE_SERVER + ${ARROW_HOME}/bin/plasma-store-server${CMAKE_EXECUTABLE_SUFFIX}) + else() + if(PLASMA_USE_CMAKE_PACKAGE_CONFIG) + find_package(Plasma CONFIG) + elseif(PLASMA_USE_PKG_CONFIG) + pkg_get_variable(PLASMA_STORE_SERVER plasma plasma_store_server) + endif() + endif() + set(PLASMA_VERSION "${ARROW_VERSION}") + set(PLASMA_SO_VERSION "${ARROW_SO_VERSION}") + set(PLASMA_ABI_VERSION "${PLASMA_SO_VERSION}") + # For backward compatibility + set(PLASMA_EXECUTABLE "${PLASMA_STORE_SERVER}") + set(PLASMA_LIBS "${PLASMA_LIB_DIR}") +endif() + +mark_as_advanced(PLASMA_ABI_VERSION + PLASMA_EXECUTABLE + PLASMA_IMPORT_LIB + PLASMA_INCLUDE_DIR + PLASMA_LIBS + PLASMA_LIB_DIR + PLASMA_SHARED_IMP_LIB + PLASMA_SHARED_LIB + PLASMA_SO_VERSION + PLASMA_STATIC_LIB + PLASMA_STORE_SERVER + PLASMA_VERSION) + +find_package_handle_standard_args( + Plasma + REQUIRED_VARS PLASMA_INCLUDE_DIR PLASMA_LIB_DIR PLASMA_SO_VERSION PLASMA_STORE_SERVER + VERSION_VAR PLASMA_VERSION) +set(PLASMA_FOUND ${Plasma_FOUND}) + +if(Plasma_FOUND AND NOT Plasma_FIND_QUIETLY) + message(STATUS "Found the Plasma by ${PLASMA_FIND_APPROACH}") + message(STATUS "Found the plasma-store-server: ${PLASMA_STORE_SERVER}") + message(STATUS "Found the Plasma shared library: ${PLASMA_SHARED_LIB}") + message(STATUS "Found the Plasma import library: ${PLASMA_IMPORT_LIB}") + message(STATUS "Found the Plasma static library: ${PLASMA_STATIC_LIB}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindPython3Alt.cmake b/src/arrow/cpp/cmake_modules/FindPython3Alt.cmake new file mode 100644 index 000000000..ab91c7be0 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindPython3Alt.cmake @@ -0,0 +1,96 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# This module finds the libraries corresponding to the Python 3 interpreter +# and the NumPy package, and sets the following variables: +# - PYTHON_EXECUTABLE +# - PYTHON_INCLUDE_DIRS +# - PYTHON_LIBRARIES +# - PYTHON_OTHER_LIBS +# - NUMPY_INCLUDE_DIRS + +# Need CMake 3.15 or later for Python3_FIND_STRATEGY +if(${CMAKE_VERSION} VERSION_LESS "3.15.0") + # Use deprecated Python- and NumPy-finding code + if(Python3Alt_FIND_REQUIRED) + find_package(PythonLibsNew REQUIRED) + find_package(NumPy REQUIRED) + else() + find_package(PythonLibsNew) + find_package(NumPy) + endif() + find_package_handle_standard_args( + Python3Alt REQUIRED_VARS PYTHON_EXECUTABLE PYTHON_INCLUDE_DIRS NUMPY_INCLUDE_DIRS) + return() +endif() + +if(${CMAKE_VERSION} VERSION_LESS "3.18.0" OR ARROW_BUILD_TESTS) + # When building arrow-python-test, we need libpython to be present, so ask for + # the full "Development" component. Also ask for it on CMake < 3.18, + # where "Development.Module" is not available. + if(Python3Alt_FIND_REQUIRED) + find_package(Python3 + COMPONENTS Interpreter Development NumPy + REQUIRED) + else() + find_package(Python3 COMPONENTS Interpreter Development NumPy) + endif() +else() + if(Python3Alt_FIND_REQUIRED) + find_package(Python3 + COMPONENTS Interpreter Development.Module NumPy + REQUIRED) + else() + find_package(Python3 COMPONENTS Interpreter Development.Module NumPy) + endif() +endif() + +if(NOT Python3_FOUND) + return() +endif() + +set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE}) +set(PYTHON_INCLUDE_DIRS ${Python3_INCLUDE_DIRS}) +set(PYTHON_LIBRARIES ${Python3_LIBRARIES}) +set(PYTHON_OTHER_LIBS) + +get_target_property(NUMPY_INCLUDE_DIRS Python3::NumPy INTERFACE_INCLUDE_DIRECTORIES) + +# CMake's python3_add_library() doesn't apply the required extension suffix, +# detect it ourselves. +# (https://gitlab.kitware.com/cmake/cmake/issues/20408) +execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" + "from distutils import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))" + RESULT_VARIABLE _PYTHON_RESULT + OUTPUT_VARIABLE _PYTHON_STDOUT + ERROR_VARIABLE _PYTHON_STDERR) + +if(NOT _PYTHON_RESULT MATCHES 0) + if(Python3Alt_FIND_REQUIRED) + message(FATAL_ERROR "Python 3 config failure:\n${_PYTHON_STDERR}") + endif() +endif() + +string(STRIP ${_PYTHON_STDOUT} _EXT_SUFFIX) + +function(PYTHON_ADD_MODULE name) + python3_add_library(${name} MODULE ${ARGN}) + set_target_properties(${name} PROPERTIES SUFFIX ${_EXT_SUFFIX}) +endfunction() + +find_package_handle_standard_args( + Python3Alt REQUIRED_VARS PYTHON_EXECUTABLE PYTHON_INCLUDE_DIRS NUMPY_INCLUDE_DIRS) diff --git a/src/arrow/cpp/cmake_modules/FindPythonLibsNew.cmake b/src/arrow/cpp/cmake_modules/FindPythonLibsNew.cmake new file mode 100644 index 000000000..581bba9d4 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindPythonLibsNew.cmake @@ -0,0 +1,267 @@ +# - Find python libraries +# This module finds the libraries corresponding to the Python interpreter +# FindPythonInterp provides. +# This code sets the following variables: +# +# PYTHONLIBS_FOUND - have the Python libs been found +# PYTHON_PREFIX - path to the Python installation +# PYTHON_LIBRARIES - path to the python library +# PYTHON_INCLUDE_DIRS - path to where Python.h is found +# PYTHON_SITE_PACKAGES - path to installation site-packages +# PYTHON_IS_DEBUG - whether the Python interpreter is a debug build +# PYTHON_OTHER_LIBS - third-party libraries (as link flags) needed +# for linking with Python +# +# PYTHON_INCLUDE_PATH - path to where Python.h is found (deprecated) +# +# A function PYTHON_ADD_MODULE(<name> src1 src2 ... srcN) is defined +# to build modules for python. +# +# Thanks to talljimbo for the patch adding the 'LDVERSION' config +# variable usage. + +#============================================================================= +# Copyright 2001-2009 Kitware, Inc. +# Copyright 2012-2014 Continuum Analytics, Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the names of Kitware, Inc., the Insight Software Consortium, +# nor the names of their contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +# Legacy code for CMake < 3.15.0. The primary point of entry should be +# FindPython3Alt.cmake. + +# Use the Python interpreter to find the libs. +if(PythonLibsNew_FIND_REQUIRED) + find_package(PythonInterp REQUIRED) +else() + find_package(PythonInterp) +endif() + +if(NOT PYTHONINTERP_FOUND) + set(PYTHONLIBS_FOUND FALSE) + return() +endif() + +# According to http://stackoverflow.com/questions/646518/python-how-to-detect-debug-interpreter +# testing whether sys has the gettotalrefcount function is a reliable, +# cross-platform way to detect a CPython debug interpreter. +# +# The library suffix is from the config var LDVERSION sometimes, otherwise +# VERSION. VERSION will typically be like "2.7" on unix, and "27" on windows. +# +# The config var LIBPL is for Linux, and helps on Debian Jessie where the +# addition of multi-arch support shuffled things around. +execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" + "from distutils import sysconfig as s;import sys;import struct; +print('.'.join(str(v) for v in sys.version_info)); +print(sys.prefix); +print(s.get_python_inc(plat_specific=True)); +print(s.get_python_lib(plat_specific=True)); +print(s.get_config_var('SO')); +print(hasattr(sys, 'gettotalrefcount')+0); +print(struct.calcsize('@P')); +print(s.get_config_var('LDVERSION') or s.get_config_var('VERSION')); +print(s.get_config_var('LIBPL')); +print(s.get_config_var('LIBS') or ''); +" + RESULT_VARIABLE _PYTHON_SUCCESS + OUTPUT_VARIABLE _PYTHON_VALUES + ERROR_VARIABLE _PYTHON_ERROR_VALUE) + +if(NOT _PYTHON_SUCCESS MATCHES 0) + if(PythonLibsNew_FIND_REQUIRED) + message(FATAL_ERROR + "Python config failure:\n${_PYTHON_ERROR_VALUE}") + endif() + set(PYTHONLIBS_FOUND FALSE) + return() +endif() + +# Convert the process output into a list +string(REGEX REPLACE ";" "\\\\;" _PYTHON_VALUES ${_PYTHON_VALUES}) +string(REGEX REPLACE "\n" ";" _PYTHON_VALUES ${_PYTHON_VALUES}) +list(GET _PYTHON_VALUES 0 _PYTHON_VERSION_LIST) +list(GET _PYTHON_VALUES 1 PYTHON_PREFIX) +list(GET _PYTHON_VALUES 2 PYTHON_INCLUDE_DIR) +list(GET _PYTHON_VALUES 3 PYTHON_SITE_PACKAGES) +list(GET _PYTHON_VALUES 4 PYTHON_MODULE_EXTENSION) +list(GET _PYTHON_VALUES 5 PYTHON_IS_DEBUG) +list(GET _PYTHON_VALUES 6 PYTHON_SIZEOF_VOID_P) +list(GET _PYTHON_VALUES 7 PYTHON_LIBRARY_SUFFIX) +list(GET _PYTHON_VALUES 8 PYTHON_LIBRARY_PATH) +list(GET _PYTHON_VALUES 9 PYTHON_OTHER_LIBS) + +# Make sure the Python has the same pointer-size as the chosen compiler +# Skip the check on OS X, it doesn't consistently have CMAKE_SIZEOF_VOID_P defined +if((NOT APPLE) AND (NOT "${PYTHON_SIZEOF_VOID_P}" STREQUAL "${CMAKE_SIZEOF_VOID_P}")) + if(PythonLibsNew_FIND_REQUIRED) + math(EXPR _PYTHON_BITS "${PYTHON_SIZEOF_VOID_P} * 8") + math(EXPR _CMAKE_BITS "${CMAKE_SIZEOF_VOID_P} * 8") + message(FATAL_ERROR + "Python config failure: Python is ${_PYTHON_BITS}-bit, " + "chosen compiler is ${_CMAKE_BITS}-bit") + endif() + set(PYTHONLIBS_FOUND FALSE) + return() +endif() + +# The built-in FindPython didn't always give the version numbers +string(REGEX REPLACE "\\." ";" _PYTHON_VERSION_LIST ${_PYTHON_VERSION_LIST}) +list(GET _PYTHON_VERSION_LIST 0 PYTHON_VERSION_MAJOR) +list(GET _PYTHON_VERSION_LIST 1 PYTHON_VERSION_MINOR) +list(GET _PYTHON_VERSION_LIST 2 PYTHON_VERSION_PATCH) + +# Make sure all directory separators are '/' +string(REGEX REPLACE "\\\\" "/" PYTHON_PREFIX ${PYTHON_PREFIX}) +string(REGEX REPLACE "\\\\" "/" PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIR}) +string(REGEX REPLACE "\\\\" "/" PYTHON_SITE_PACKAGES ${PYTHON_SITE_PACKAGES}) + +if(CMAKE_HOST_WIN32) + # Appease CMP0054 + if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + set(PYTHON_LIBRARY + "${PYTHON_PREFIX}/libs/Python${PYTHON_LIBRARY_SUFFIX}.lib") + else() + find_library(PYTHON_LIBRARY + NAMES "python${PYTHON_LIBRARY_SUFFIX}" + PATHS "${PYTHON_PREFIX}" NO_DEFAULT_PATH + PATH_SUFFIXES "lib" "libs") + endif() +elseif(APPLE) + + set(PYTHON_LIBRARY "${PYTHON_PREFIX}/lib/libpython${PYTHON_LIBRARY_SUFFIX}.dylib") + + if (NOT EXISTS ${PYTHON_LIBRARY}) + # In some cases libpythonX.X.dylib is not part of the PYTHON_PREFIX and we + # need to call `python-config --prefix` to determine the correct location. + find_program(PYTHON_CONFIG python-config + NO_CMAKE_SYSTEM_PATH) + if (PYTHON_CONFIG) + execute_process( + COMMAND "${PYTHON_CONFIG}" "--prefix" + OUTPUT_VARIABLE PYTHON_CONFIG_PREFIX + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(PYTHON_LIBRARY "${PYTHON_CONFIG_PREFIX}/lib/libpython${PYTHON_LIBRARY_SUFFIX}.dylib") + endif() + endif() +else() + if(${PYTHON_SIZEOF_VOID_P} MATCHES 8) + set(_PYTHON_LIBS_SEARCH "${PYTHON_PREFIX}/lib64" "${PYTHON_PREFIX}/lib" "${PYTHON_LIBRARY_PATH}") + else() + set(_PYTHON_LIBS_SEARCH "${PYTHON_PREFIX}/lib" "${PYTHON_LIBRARY_PATH}") + endif() + message(STATUS "Searching for Python libs in ${_PYTHON_LIBS_SEARCH}") + message(STATUS "Looking for python${PYTHON_LIBRARY_SUFFIX}") + # Probably this needs to be more involved. It would be nice if the config + # information the python interpreter itself gave us were more complete. + find_library(PYTHON_LIBRARY + NAMES "python${PYTHON_LIBRARY_SUFFIX}" + PATHS ${_PYTHON_LIBS_SEARCH} + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + message(STATUS "Found Python lib ${PYTHON_LIBRARY}") +endif() + +# For backward compatibility, set PYTHON_INCLUDE_PATH, but make it internal. +SET(PYTHON_INCLUDE_PATH "${PYTHON_INCLUDE_DIR}" CACHE INTERNAL + "Path to where Python.h is found (deprecated)") + +MARK_AS_ADVANCED( + PYTHON_LIBRARY + PYTHON_INCLUDE_DIR +) + +# We use PYTHON_INCLUDE_DIR, PYTHON_LIBRARY and PYTHON_DEBUG_LIBRARY for the +# cache entries because they are meant to specify the location of a single +# library. We now set the variables listed by the documentation for this +# module. +SET(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") +SET(PYTHON_LIBRARIES "${PYTHON_LIBRARY}") +SET(PYTHON_DEBUG_LIBRARIES "${PYTHON_DEBUG_LIBRARY}") + + +# Don't know how to get to this directory, just doing something simple :P +#INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +#FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonLibs DEFAULT_MSG PYTHON_LIBRARIES PYTHON_INCLUDE_DIRS) +find_package_message(PYTHON + "Found PythonLibs: ${PYTHON_LIBRARY}" + "${PYTHON_EXECUTABLE}${PYTHON_VERSION}") + + +# PYTHON_ADD_MODULE(<name> src1 src2 ... srcN) is used to build modules for python. +FUNCTION(PYTHON_ADD_MODULE _NAME ) + GET_PROPERTY(_TARGET_SUPPORTS_SHARED_LIBS + GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS) + OPTION(PYTHON_ENABLE_MODULE_${_NAME} "Add module ${_NAME}" TRUE) + OPTION(PYTHON_MODULE_${_NAME}_BUILD_SHARED + "Add module ${_NAME} shared" ${_TARGET_SUPPORTS_SHARED_LIBS}) + + # Mark these options as advanced + MARK_AS_ADVANCED(PYTHON_ENABLE_MODULE_${_NAME} + PYTHON_MODULE_${_NAME}_BUILD_SHARED) + + IF(PYTHON_ENABLE_MODULE_${_NAME}) + IF(PYTHON_MODULE_${_NAME}_BUILD_SHARED) + SET(PY_MODULE_TYPE MODULE) + ELSE(PYTHON_MODULE_${_NAME}_BUILD_SHARED) + SET(PY_MODULE_TYPE STATIC) + SET_PROPERTY(GLOBAL APPEND PROPERTY PY_STATIC_MODULES_LIST ${_NAME}) + ENDIF(PYTHON_MODULE_${_NAME}_BUILD_SHARED) + + SET_PROPERTY(GLOBAL APPEND PROPERTY PY_MODULES_LIST ${_NAME}) + ADD_LIBRARY(${_NAME} ${PY_MODULE_TYPE} ${ARGN}) + IF(APPLE) + # On OS X, linking against the Python libraries causes + # segfaults, so do this dynamic lookup instead. + SET_TARGET_PROPERTIES(${_NAME} PROPERTIES LINK_FLAGS + "-undefined dynamic_lookup") + ELSEIF(MSVC) + target_link_libraries(${_NAME} ${PYTHON_LIBRARIES}) + ELSE() + # In general, we should not link against libpython as we do not embed the + # Python interpreter. The python binary itself can then define where the + # symbols should loaded from. For being manylinux1 compliant, one is not + # allowed to link to libpython. Partly because not all systems ship it, + # also because the interpreter ABI/API was not stable between patch + # releases for Python < 3.5. + SET_TARGET_PROPERTIES(${_NAME} PROPERTIES LINK_FLAGS + "-Wl,-undefined,dynamic_lookup") + ENDIF() + IF(PYTHON_MODULE_${_NAME}_BUILD_SHARED) + SET_TARGET_PROPERTIES(${_NAME} PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}") + SET_TARGET_PROPERTIES(${_NAME} PROPERTIES SUFFIX "${PYTHON_MODULE_EXTENSION}") + ELSE() + ENDIF() + + ENDIF(PYTHON_ENABLE_MODULE_${_NAME}) +ENDFUNCTION(PYTHON_ADD_MODULE) diff --git a/src/arrow/cpp/cmake_modules/FindRapidJSONAlt.cmake b/src/arrow/cpp/cmake_modules/FindRapidJSONAlt.cmake new file mode 100644 index 000000000..9a449a528 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindRapidJSONAlt.cmake @@ -0,0 +1,72 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +set(find_package_args) +if(RapidJSONAlt_FIND_VERSION) + list(APPEND find_package_args ${RapidJSONAlt_FIND_VERSION}) +endif() +if(RapidJSONAlt_FIND_QUIETLY) + list(APPEND find_package_args QUIET) +endif() +find_package(RapidJSON ${find_package_args}) +if(RapidJSON_FOUND) + set(RapidJSONAlt_FOUND TRUE) + set(RAPIDJSON_INCLUDE_DIR ${RAPIDJSON_INCLUDE_DIRS}) + return() +endif() + +if(RapidJSON_ROOT) + find_path(RAPIDJSON_INCLUDE_DIR + NAMES rapidjson/rapidjson.h + PATHS ${RapidJSON_ROOT} + NO_DEFAULT_PATH + PATH_SUFFIXES "include") +else() + find_path(RAPIDJSON_INCLUDE_DIR + NAMES rapidjson/rapidjson.h + PATH_SUFFIXES "include") +endif() + +if(RAPIDJSON_INCLUDE_DIR) + file(READ "${RAPIDJSON_INCLUDE_DIR}/rapidjson/rapidjson.h" RAPIDJSON_H_CONTENT) + string(REGEX MATCH "#define RAPIDJSON_MAJOR_VERSION ([0-9]+)" + RAPIDJSON_MAJOR_VERSION_DEFINITION "${RAPIDJSON_H_CONTENT}") + string(REGEX REPLACE "^.+ ([0-9]+)$" "\\1" RAPIDJSON_MAJOR_VERSION + "${RAPIDJSON_MAJOR_VERSION_DEFINITION}") + string(REGEX MATCH "#define RAPIDJSON_MINOR_VERSION ([0-9]+)" + RAPIDJSON_MINOR_VERSION_DEFINITION "${RAPIDJSON_H_CONTENT}") + string(REGEX REPLACE "^.+ ([0-9]+)$" "\\1" RAPIDJSON_MINOR_VERSION + "${RAPIDJSON_MINOR_VERSION_DEFINITION}") + string(REGEX MATCH "#define RAPIDJSON_PATCH_VERSION ([0-9]+)" + RAPIDJSON_PATCH_VERSION_DEFINITION "${RAPIDJSON_H_CONTENT}") + string(REGEX REPLACE "^.+ ([0-9]+)$" "\\1" RAPIDJSON_PATCH_VERSION + "${RAPIDJSON_PATCH_VERSION_DEFINITION}") + if("${RAPIDJSON_MAJOR_VERSION}" STREQUAL "" + OR "${RAPIDJSON_MINOR_VERSION}" STREQUAL "" + OR "${RAPIDJSON_PATCH_VERSION}" STREQUAL "") + set(RAPIDJSON_VERSION "0.0.0") + else() + set(RAPIDJSON_VERSION + "${RAPIDJSON_MAJOR_VERSION}.${RAPIDJSON_MINOR_VERSION}.${RAPIDJSON_PATCH_VERSION}" + ) + endif() +endif() + +find_package_handle_standard_args( + RapidJSONAlt + REQUIRED_VARS RAPIDJSON_INCLUDE_DIR + VERSION_VAR RAPIDJSON_VERSION) diff --git a/src/arrow/cpp/cmake_modules/FindSnappy.cmake b/src/arrow/cpp/cmake_modules/FindSnappy.cmake new file mode 100644 index 000000000..747df3185 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindSnappy.cmake @@ -0,0 +1,62 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +if(ARROW_SNAPPY_USE_SHARED) + set(SNAPPY_LIB_NAMES) + if(CMAKE_IMPORT_LIBRARY_SUFFIX) + list(APPEND SNAPPY_LIB_NAMES + "${CMAKE_IMPORT_LIBRARY_PREFIX}snappy${CMAKE_IMPORT_LIBRARY_SUFFIX}") + endif() + list(APPEND SNAPPY_LIB_NAMES + "${CMAKE_SHARED_LIBRARY_PREFIX}snappy${CMAKE_SHARED_LIBRARY_SUFFIX}") +else() + set(SNAPPY_STATIC_LIB_NAME_BASE "snappy") + if(MSVC) + set(SNAPPY_STATIC_LIB_NAME_BASE + "${SNAPPY_STATIC_LIB_NAME_BASE}${SNAPPY_MSVC_STATIC_LIB_SUFFIX}") + endif() + set(SNAPPY_LIB_NAMES + "${CMAKE_STATIC_LIBRARY_PREFIX}${SNAPPY_STATIC_LIB_NAME_BASE}${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) +endif() + +if(Snappy_ROOT) + find_library(Snappy_LIB + NAMES ${SNAPPY_LIB_NAMES} + PATHS ${Snappy_ROOT} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) + find_path(Snappy_INCLUDE_DIR + NAMES snappy.h + PATHS ${Snappy_ROOT} + NO_DEFAULT_PATH + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) +else() + find_library(Snappy_LIB NAMES ${SNAPPY_LIB_NAMES}) + find_path(Snappy_INCLUDE_DIR + NAMES snappy.h + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) +endif() + +find_package_handle_standard_args(Snappy REQUIRED_VARS Snappy_LIB Snappy_INCLUDE_DIR) + +if(Snappy_FOUND) + add_library(Snappy::snappy UNKNOWN IMPORTED) + set_target_properties(Snappy::snappy + PROPERTIES IMPORTED_LOCATION "${Snappy_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${Snappy_INCLUDE_DIR}") +endif() diff --git a/src/arrow/cpp/cmake_modules/FindThrift.cmake b/src/arrow/cpp/cmake_modules/FindThrift.cmake new file mode 100644 index 000000000..750d8ce83 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindThrift.cmake @@ -0,0 +1,144 @@ +# Copyright 2012 Cloudera Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# - Find Thrift (a cross platform RPC lib/tool) +# +# Variables used by this module, they can change the default behaviour and need +# to be set before calling find_package: +# +# Thrift_ROOT - When set, this path is inspected instead of standard library +# locations as the root of the Thrift installation. +# The environment variable THRIFT_HOME overrides this variable. +# +# This module defines +# THRIFT_VERSION, version string of ant if found +# THRIFT_INCLUDE_DIR, where to find THRIFT headers +# THRIFT_LIB, THRIFT library +# THRIFT_FOUND, If false, do not try to use ant + +function(EXTRACT_THRIFT_VERSION) + if(THRIFT_INCLUDE_DIR) + file(READ "${THRIFT_INCLUDE_DIR}/thrift/config.h" THRIFT_CONFIG_H_CONTENT) + string(REGEX MATCH "#define PACKAGE_VERSION \"[0-9.]+\"" THRIFT_VERSION_DEFINITION + "${THRIFT_CONFIG_H_CONTENT}") + string(REGEX MATCH "[0-9.]+" THRIFT_VERSION "${THRIFT_VERSION_DEFINITION}") + set(THRIFT_VERSION + "${THRIFT_VERSION}" + PARENT_SCOPE) + else() + set(THRIFT_VERSION + "" + PARENT_SCOPE) + endif() +endfunction(EXTRACT_THRIFT_VERSION) + +if(MSVC_TOOLCHAIN AND NOT DEFINED THRIFT_MSVC_LIB_SUFFIX) + if(NOT ARROW_THRIFT_USE_SHARED) + if(ARROW_USE_STATIC_CRT) + set(THRIFT_MSVC_LIB_SUFFIX "mt") + else() + set(THRIFT_MSVC_LIB_SUFFIX "md") + endif() + endif() +endif() +set(THRIFT_LIB_NAME_BASE "thrift${THRIFT_MSVC_LIB_SUFFIX}") + +if(ARROW_THRIFT_USE_SHARED) + set(THRIFT_LIB_NAMES thrift) + if(CMAKE_IMPORT_LIBRARY_SUFFIX) + list(APPEND + THRIFT_LIB_NAMES + "${CMAKE_IMPORT_LIBRARY_PREFIX}${THRIFT_LIB_NAME_BASE}${CMAKE_IMPORT_LIBRARY_SUFFIX}" + ) + endif() + list(APPEND + THRIFT_LIB_NAMES + "${CMAKE_SHARED_LIBRARY_PREFIX}${THRIFT_LIB_NAME_BASE}${CMAKE_SHARED_LIBRARY_SUFFIX}" + ) +else() + set(THRIFT_LIB_NAMES + "${CMAKE_STATIC_LIBRARY_PREFIX}${THRIFT_LIB_NAME_BASE}${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) +endif() + +if(Thrift_ROOT) + find_library(THRIFT_LIB + NAMES ${THRIFT_LIB_NAMES} + PATHS ${Thrift_ROOT} + PATH_SUFFIXES "lib/${CMAKE_LIBRARY_ARCHITECTURE}" "lib") + find_path(THRIFT_INCLUDE_DIR thrift/Thrift.h + PATHS ${Thrift_ROOT} + PATH_SUFFIXES "include") + find_program(THRIFT_COMPILER thrift + PATHS ${Thrift_ROOT} + PATH_SUFFIXES "bin") + extract_thrift_version() +else() + # THRIFT-4760: The pkgconfig files are currently only installed when using autotools. + # Starting with 0.13, they are also installed for the CMake-based installations of Thrift. + find_package(PkgConfig QUIET) + pkg_check_modules(THRIFT_PC thrift) + if(THRIFT_PC_FOUND) + set(THRIFT_INCLUDE_DIR "${THRIFT_PC_INCLUDEDIR}") + + list(APPEND THRIFT_PC_LIBRARY_DIRS "${THRIFT_PC_LIBDIR}") + + find_library(THRIFT_LIB + NAMES ${THRIFT_LIB_NAMES} + PATHS ${THRIFT_PC_LIBRARY_DIRS} + NO_DEFAULT_PATH) + find_program(THRIFT_COMPILER thrift + HINTS ${THRIFT_PC_PREFIX} + NO_DEFAULT_PATH + PATH_SUFFIXES "bin") + set(THRIFT_VERSION ${THRIFT_PC_VERSION}) + else() + find_library(THRIFT_LIB + NAMES ${THRIFT_LIB_NAMES} + PATH_SUFFIXES "lib/${CMAKE_LIBRARY_ARCHITECTURE}" "lib") + find_path(THRIFT_INCLUDE_DIR thrift/Thrift.h PATH_SUFFIXES "include") + find_program(THRIFT_COMPILER thrift PATH_SUFFIXES "bin") + extract_thrift_version() + endif() +endif() + +if(THRIFT_COMPILER) + set(Thrift_COMPILER_FOUND TRUE) +else() + set(Thrift_COMPILER_FOUND FALSE) +endif() + +find_package_handle_standard_args( + Thrift + REQUIRED_VARS THRIFT_LIB THRIFT_INCLUDE_DIR + VERSION_VAR THRIFT_VERSION + HANDLE_COMPONENTS) + +if(Thrift_FOUND OR THRIFT_FOUND) + set(Thrift_FOUND TRUE) + if(ARROW_THRIFT_USE_SHARED) + add_library(thrift::thrift SHARED IMPORTED) + else() + add_library(thrift::thrift STATIC IMPORTED) + endif() + set_target_properties(thrift::thrift + PROPERTIES IMPORTED_LOCATION "${THRIFT_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${THRIFT_INCLUDE_DIR}") + if(WIN32 AND NOT MSVC_TOOLCHAIN) + # We don't need this for Visual C++ because Thrift uses + # "#pragma comment(lib, "Ws2_32.lib")" in + # thrift/windows/config.h for Visual C++. + set_target_properties(thrift::thrift PROPERTIES INTERFACE_LINK_LIBRARIES "ws2_32") + endif() +endif() diff --git a/src/arrow/cpp/cmake_modules/Findc-aresAlt.cmake b/src/arrow/cpp/cmake_modules/Findc-aresAlt.cmake new file mode 100644 index 000000000..5213e8d12 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/Findc-aresAlt.cmake @@ -0,0 +1,73 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +set(find_package_args) +if(c-aresAlt_FIND_VERSION) + list(APPEND find_package_args ${c-aresAlt_FIND_VERSION}) +endif() +if(c-aresAlt_FIND_QUIETLY) + list(APPEND find_package_args QUIET) +endif() +find_package(c-ares ${find_package_args}) +if(c-ares_FOUND) + set(c-aresAlt_FOUND TRUE) + return() +endif() + +find_package(PkgConfig QUIET) +pkg_check_modules(c-ares_PC libcares) +if(c-ares_PC_FOUND) + set(c-ares_INCLUDE_DIR "${c-ares_PC_INCLUDEDIR}") + + list(APPEND c-ares_PC_LIBRARY_DIRS "${c-ares_PC_LIBDIR}") + find_library(c-ares_LIB cares + PATHS ${c-ares_PC_LIBRARY_DIRS} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) +elseif(c-ares_ROOT) + find_library(c-ares_LIB + NAMES cares + "${CMAKE_SHARED_LIBRARY_PREFIX}cares${CMAKE_SHARED_LIBRARY_SUFFIX}" + PATHS ${c-ares_ROOT} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) + find_path(c-ares_INCLUDE_DIR + NAMES ares.h + PATHS ${c-ares_ROOT} + NO_DEFAULT_PATH + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) +else() + find_library(c-ares_LIB + NAMES cares + "${CMAKE_SHARED_LIBRARY_PREFIX}cares${CMAKE_SHARED_LIBRARY_SUFFIX}" + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES}) + find_path(c-ares_INCLUDE_DIR + NAMES ares.h + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) +endif() + +find_package_handle_standard_args(c-aresAlt REQUIRED_VARS c-ares_LIB c-ares_INCLUDE_DIR) + +if(c-aresAlt_FOUND) + if(NOT TARGET c-ares::cares) + add_library(c-ares::cares UNKNOWN IMPORTED) + set_target_properties(c-ares::cares + PROPERTIES IMPORTED_LOCATION "${c-ares_LIB}" + INTERFACE_INCLUDE_DIRECTORIES + "${c-ares_INCLUDE_DIR}") + endif() +endif() diff --git a/src/arrow/cpp/cmake_modules/FindgRPCAlt.cmake b/src/arrow/cpp/cmake_modules/FindgRPCAlt.cmake new file mode 100644 index 000000000..18b23f322 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindgRPCAlt.cmake @@ -0,0 +1,76 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set(find_package_args) +if(gRPCAlt_FIND_VERSION) + list(APPEND find_package_args ${gRPCAlt_FIND_VERSION}) +endif() +if(gRPCAlt_FIND_QUIETLY) + list(APPEND find_package_args QUIET) +endif() +find_package(gRPC ${find_package_args}) +if(gRPC_FOUND) + set(gRPCAlt_FOUND TRUE) + return() +endif() + +find_package(PkgConfig QUIET) +pkg_check_modules(GRPCPP_PC grpc++) +if(GRPCPP_PC_FOUND) + set(gRPCAlt_VERSION "${GRPCPP_PC_VERSION}") + set(GRPCPP_INCLUDE_DIRECTORIES ${GRPCPP_PC_INCLUDEDIR}) + if(ARROW_GRPC_USE_SHARED) + set(GRPCPP_LINK_LIBRARIES ${GRPCPP_PC_LINK_LIBRARIES}) + set(GRPCPP_LINK_OPTIONS ${GRPCPP_PC_LDFLAGS_OTHER}) + set(GRPCPP_COMPILE_OPTIONS ${GRPCPP_PC_CFLAGS_OTHER}) + else() + set(GRPCPP_LINK_LIBRARIES) + foreach(GRPCPP_LIBRARY_NAME ${GRPCPP_PC_STATIC_LIBRARIES}) + find_library(GRPCPP_LIBRARY_${GRPCPP_LIBRARY_NAME} + NAMES "${CMAKE_STATIC_LIBRARY_PREFIX}${GRPCPP_LIBRARY_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}" + HINTS ${GRPCPP_PC_STATIC_LIBRARY_DIRS}) + list(APPEND GRPCPP_LINK_LIBRARIES "${GRPCPP_LIBRARY_${GRPCPP_LIBRARY_NAME}}") + endforeach() + set(GRPCPP_LINK_OPTIONS ${GRPCPP_PC_STATIC_LDFLAGS_OTHER}) + set(GRPCPP_COMPILE_OPTIONS ${GRPCPP_PC_STATIC_CFLAGS_OTHER}) + endif() + list(GET GRPCPP_LINK_LIBRARIES 0 GRPCPP_IMPORTED_LOCATION) + list(REMOVE_AT GRPCPP_LINK_LIBRARIES 0) + find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin + HINTS ${GRPCPP_PC_PREFIX} + NO_DEFAULT_PATH + PATH_SUFFIXES "bin") + set(gRPCAlt_FIND_PACKAGE_ARGS gRPCAlt REQUIRED_VARS GRPCPP_IMPORTED_LOCATION + GRPC_CPP_PLUGIN) + if(gRPCAlt_VERSION) + list(APPEND gRPCAlt_FIND_PACKAGE_ARGS VERSION_VAR gRPCAlt_VERSION) + endif() + find_package_handle_standard_args(${gRPCAlt_FIND_PACKAGE_ARGS}) +else() + set(gRPCAlt_FOUND FALSE) +endif() + +if(gRPCAlt_FOUND) + add_library(gRPC::grpc++ UNKNOWN IMPORTED) + set_target_properties(gRPC::grpc++ + PROPERTIES IMPORTED_LOCATION "${GRPCPP_IMPORTED_LOCATION}" + INTERFACE_COMPILE_OPTIONS "${GRPCPP_COMPILE_OPTIONS}" + INTERFACE_INCLUDE_DIRECTORIES + "${GRPCPP_INCLUDE_DIRECTORIES}" + INTERFACE_LINK_LIBRARIES "${GRPCPP_LINK_LIBRARIES}" + INTERFACE_LINK_OPTIONS "${GRPCPP_LINK_OPTIONS}") + + add_executable(gRPC::grpc_cpp_plugin IMPORTED) + set_target_properties(gRPC::grpc_cpp_plugin PROPERTIES IMPORTED_LOCATION + ${GRPC_CPP_PLUGIN}) +endif() diff --git a/src/arrow/cpp/cmake_modules/FindgflagsAlt.cmake b/src/arrow/cpp/cmake_modules/FindgflagsAlt.cmake new file mode 100644 index 000000000..e092ea3e9 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/FindgflagsAlt.cmake @@ -0,0 +1,59 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +set(find_package_args) +if(gflagsAlt_FIND_VERSION) + list(APPEND find_package_args ${gflagsAlt_FIND_VERSION}) +endif() +if(gflagsAlt_FIND_QUIETLY) + list(APPEND find_package_args QUIET) +endif() +find_package(gflags ${find_package_args}) +if(gflags_FOUND) + set(gflagsAlt_FOUND TRUE) + return() +endif() + +# TODO: Support version detection. + +if(gflags_ROOT) + find_library(gflags_LIB + NAMES gflags + PATHS ${gflags_ROOT} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) + find_path(GFLAGS_INCLUDE_DIR + NAMES gflags/gflags.h + PATHS ${gflags_ROOT} + NO_DEFAULT_PATH + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) +else() + find_library(gflags_LIB NAMES gflags) + find_path(GFLAGS_INCLUDE_DIR + NAMES gflags/gflags.h + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) +endif() + +find_package_handle_standard_args(gflagsAlt REQUIRED_VARS gflags_LIB GFLAGS_INCLUDE_DIR) + +if(gflagsAlt_FOUND) + add_library(gflags::gflags UNKNOWN IMPORTED) + set_target_properties(gflags::gflags + PROPERTIES IMPORTED_LOCATION "${gflags_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${GFLAGS_INCLUDE_DIR}") + set(GFLAGS_LIBRARIES gflags::gflags) +endif() diff --git a/src/arrow/cpp/cmake_modules/Findjemalloc.cmake b/src/arrow/cpp/cmake_modules/Findjemalloc.cmake new file mode 100644 index 000000000..84bb81fcb --- /dev/null +++ b/src/arrow/cpp/cmake_modules/Findjemalloc.cmake @@ -0,0 +1,94 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Tries to find jemalloc headers and libraries. +# +# Usage of this module as follows: +# +# find_package(jemalloc) +# +# Variables used by this module, they can change the default behaviour and need +# to be set before calling find_package: +# +# JEMALLOC_HOME - +# When set, this path is inspected instead of standard library locations as +# the root of the jemalloc installation. The environment variable +# JEMALLOC_HOME overrides this veriable. +# +# This module defines +# JEMALLOC_INCLUDE_DIR, directory containing headers +# JEMALLOC_SHARED_LIB, path to libjemalloc.so/dylib +# JEMALLOC_FOUND, whether flatbuffers has been found + +if(NOT "${JEMALLOC_HOME}" STREQUAL "") + file(TO_CMAKE_PATH "${JEMALLOC_HOME}" _native_path) + list(APPEND _jemalloc_roots ${_native_path}) +elseif(JEMALLOC_HOME) + list(APPEND _jemalloc_roots ${JEMALLOC_HOME}) +endif() + +set(LIBJEMALLOC_NAMES jemalloc libjemalloc.so.1 libjemalloc.so.2 libjemalloc.dylib) + +# Try the parameterized roots, if they exist +if(_jemalloc_roots) + find_path(JEMALLOC_INCLUDE_DIR + NAMES jemalloc/jemalloc.h + PATHS ${_jemalloc_roots} + NO_DEFAULT_PATH + PATH_SUFFIXES "include") + find_library(JEMALLOC_SHARED_LIB + NAMES ${LIBJEMALLOC_NAMES} + PATHS ${_jemalloc_roots} + NO_DEFAULT_PATH + PATH_SUFFIXES "lib") + find_library(JEMALLOC_STATIC_LIB + NAMES jemalloc_pic + PATHS ${_jemalloc_roots} + NO_DEFAULT_PATH + PATH_SUFFIXES "lib") +else() + find_path(JEMALLOC_INCLUDE_DIR NAMES jemalloc/jemalloc.h) + message(STATUS ${JEMALLOC_INCLUDE_DIR}) + find_library(JEMALLOC_SHARED_LIB NAMES ${LIBJEMALLOC_NAMES}) + message(STATUS ${JEMALLOC_SHARED_LIB}) + find_library(JEMALLOC_STATIC_LIB NAMES jemalloc_pic) + message(STATUS ${JEMALLOC_STATIC_LIB}) +endif() + +if(JEMALLOC_INCLUDE_DIR AND JEMALLOC_SHARED_LIB) + set(JEMALLOC_FOUND TRUE) +else() + set(JEMALLOC_FOUND FALSE) +endif() + +if(JEMALLOC_FOUND) + if(NOT jemalloc_FIND_QUIETLY) + message(STATUS "Found the jemalloc library: ${JEMALLOC_LIBRARIES}") + endif() +else() + if(NOT jemalloc_FIND_QUIETLY) + set(JEMALLOC_ERR_MSG "Could not find the jemalloc library. Looked in ") + if(_flatbuffers_roots) + set(JEMALLOC_ERR_MSG "${JEMALLOC_ERR_MSG} in ${_jemalloc_roots}.") + else() + set(JEMALLOC_ERR_MSG "${JEMALLOC_ERR_MSG} system search paths.") + endif() + if(jemalloc_FIND_REQUIRED) + message(FATAL_ERROR "${JEMALLOC_ERR_MSG}") + else(jemalloc_FIND_REQUIRED) + message(STATUS "${JEMALLOC_ERR_MSG}") + endif(jemalloc_FIND_REQUIRED) + endif() +endif() + +mark_as_advanced(JEMALLOC_INCLUDE_DIR JEMALLOC_SHARED_LIB) diff --git a/src/arrow/cpp/cmake_modules/Findre2Alt.cmake b/src/arrow/cpp/cmake_modules/Findre2Alt.cmake new file mode 100644 index 000000000..68abf1b75 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/Findre2Alt.cmake @@ -0,0 +1,87 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +set(find_package_args) +if(re2Alt_FIND_VERSION) + list(APPEND find_package_args ${re2Alt_FIND_VERSION}) +endif() +if(re2Alt_FIND_QUIETLY) + list(APPEND find_package_args QUIET) +endif() +find_package(re2 ${find_package_args}) +if(re2_FOUND) + set(re2Alt_FOUND TRUE) + return() +endif() + +find_package(PkgConfig QUIET) +pkg_check_modules(RE2_PC re2) +if(RE2_PC_FOUND) + set(RE2_INCLUDE_DIR "${RE2_PC_INCLUDEDIR}") + + list(APPEND RE2_PC_LIBRARY_DIRS "${RE2_PC_LIBDIR}") + find_library(RE2_LIB re2 + PATHS ${RE2_PC_LIBRARY_DIRS} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) + + # On Fedora, the reported prefix is wrong. As users likely run into this, + # workaround. + # https://bugzilla.redhat.com/show_bug.cgi?id=1652589 + if(UNIX + AND NOT APPLE + AND NOT RE2_LIB) + if(RE2_PC_PREFIX STREQUAL "/usr/local") + find_library(RE2_LIB re2) + endif() + endif() +elseif(RE2_ROOT) + find_library(RE2_LIB + NAMES re2_static + re2 + "${CMAKE_STATIC_LIBRARY_PREFIX}re2${RE2_MSVC_STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}" + "${CMAKE_SHARED_LIBRARY_PREFIX}re2${CMAKE_SHARED_LIBRARY_SUFFIX}" + PATHS ${RE2_ROOT} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) + find_path(RE2_INCLUDE_DIR + NAMES re2/re2.h + PATHS ${RE2_ROOT} + NO_DEFAULT_PATH + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) +else() + find_library(RE2_LIB + NAMES re2_static + re2 + "${CMAKE_STATIC_LIBRARY_PREFIX}re2${RE2_MSVC_STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}" + "${CMAKE_SHARED_LIBRARY_PREFIX}re2${CMAKE_SHARED_LIBRARY_SUFFIX}" + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES}) + find_path(RE2_INCLUDE_DIR + NAMES re2/re2.h + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) +endif() + +find_package_handle_standard_args(re2Alt REQUIRED_VARS RE2_LIB RE2_INCLUDE_DIR) + +if(re2Alt_FOUND) + if(NOT TARGET re2::re2) + add_library(re2::re2 UNKNOWN IMPORTED) + set_target_properties(re2::re2 + PROPERTIES IMPORTED_LOCATION "${RE2_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${RE2_INCLUDE_DIR}") + endif() +endif() diff --git a/src/arrow/cpp/cmake_modules/Findutf8proc.cmake b/src/arrow/cpp/cmake_modules/Findutf8proc.cmake new file mode 100644 index 000000000..4d732f186 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/Findutf8proc.cmake @@ -0,0 +1,101 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +function(extract_utf8proc_version) + if(utf8proc_INCLUDE_DIR) + file(READ "${utf8proc_INCLUDE_DIR}/utf8proc.h" UTF8PROC_H_CONTENT) + + string(REGEX MATCH "#define UTF8PROC_VERSION_MAJOR [0-9]+" + UTF8PROC_MAJOR_VERSION_DEFINITION "${UTF8PROC_H_CONTENT}") + string(REGEX MATCH "#define UTF8PROC_VERSION_MINOR [0-9]+" + UTF8PROC_MINOR_VERSION_DEFINITION "${UTF8PROC_H_CONTENT}") + string(REGEX MATCH "#define UTF8PROC_VERSION_PATCH [0-9]+" + UTF8PROC_PATCH_VERSION_DEFINITION "${UTF8PROC_H_CONTENT}") + + string(REGEX MATCH "[0-9]+$" UTF8PROC_MAJOR_VERSION + "${UTF8PROC_MAJOR_VERSION_DEFINITION}") + string(REGEX MATCH "[0-9]+$" UTF8PROC_MINOR_VERSION + "${UTF8PROC_MINOR_VERSION_DEFINITION}") + string(REGEX MATCH "[0-9]+$" UTF8PROC_PATCH_VERSION + "${UTF8PROC_PATCH_VERSION_DEFINITION}") + set(utf8proc_VERSION + "${UTF8PROC_MAJOR_VERSION}.${UTF8PROC_MINOR_VERSION}.${UTF8PROC_PATCH_VERSION}" + PARENT_SCOPE) + else() + set(utf8proc_VERSION + "" + PARENT_SCOPE) + endif() +endfunction(extract_utf8proc_version) + +if(ARROW_UTF8PROC_USE_SHARED) + set(utf8proc_LIB_NAMES) + if(CMAKE_IMPORT_LIBRARY_SUFFIX) + list(APPEND utf8proc_LIB_NAMES + "${CMAKE_IMPORT_LIBRARY_PREFIX}utf8proc${CMAKE_IMPORT_LIBRARY_SUFFIX}") + endif() + list(APPEND utf8proc_LIB_NAMES + "${CMAKE_SHARED_LIBRARY_PREFIX}utf8proc${CMAKE_SHARED_LIBRARY_SUFFIX}") +else() + if(MSVC AND NOT DEFINED utf8proc_MSVC_STATIC_LIB_SUFFIX) + set(utf8proc_MSVC_STATIC_LIB_SUFFIX "_static") + endif() + set(utf8proc_STATIC_LIB_SUFFIX + "${utf8proc_MSVC_STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}") + set(utf8proc_LIB_NAMES + "${CMAKE_STATIC_LIBRARY_PREFIX}utf8proc${utf8proc_STATIC_LIB_SUFFIX}") +endif() + +if(utf8proc_ROOT) + find_library(utf8proc_LIB + NAMES ${utf8proc_LIB_NAMES} + PATHS ${utf8proc_ROOT} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) + find_path(utf8proc_INCLUDE_DIR + NAMES utf8proc.h + PATHS ${utf8proc_ROOT} + NO_DEFAULT_PATH + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) + extract_utf8proc_version() +else() + find_library(utf8proc_LIB + NAMES ${utf8proc_LIB_NAMES} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES}) + find_path(utf8proc_INCLUDE_DIR + NAMES utf8proc.h + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) + extract_utf8proc_version() +endif() + +find_package_handle_standard_args( + utf8proc + REQUIRED_VARS utf8proc_LIB utf8proc_INCLUDE_DIR + VERSION_VAR utf8proc_VERSION) + +if(utf8proc_FOUND) + set(utf8proc_FOUND TRUE) + add_library(utf8proc::utf8proc UNKNOWN IMPORTED) + set_target_properties(utf8proc::utf8proc + PROPERTIES IMPORTED_LOCATION "${utf8proc_LIB}" + INTERFACE_INCLUDE_DIRECTORIES + "${utf8proc_INCLUDE_DIR}") + if(NOT ARROW_UTF8PROC_USE_SHARED) + set_target_properties(utf8proc::utf8proc PROPERTIES INTERFACE_COMPILER_DEFINITIONS + "UTF8PROC_STATIC") + endif() +endif() diff --git a/src/arrow/cpp/cmake_modules/Findzstd.cmake b/src/arrow/cpp/cmake_modules/Findzstd.cmake new file mode 100644 index 000000000..3fc14ec0d --- /dev/null +++ b/src/arrow/cpp/cmake_modules/Findzstd.cmake @@ -0,0 +1,89 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +if(MSVC AND NOT DEFINED ZSTD_MSVC_LIB_PREFIX) + set(ZSTD_MSVC_LIB_PREFIX "lib") +endif() +set(ZSTD_LIB_NAME_BASE "${ZSTD_MSVC_LIB_PREFIX}zstd") + +if(ARROW_ZSTD_USE_SHARED) + set(ZSTD_LIB_NAMES) + if(CMAKE_IMPORT_LIBRARY_SUFFIX) + list(APPEND + ZSTD_LIB_NAMES + "${CMAKE_IMPORT_LIBRARY_PREFIX}${ZSTD_LIB_NAME_BASE}${CMAKE_IMPORT_LIBRARY_SUFFIX}" + ) + endif() + list(APPEND ZSTD_LIB_NAMES + "${CMAKE_SHARED_LIBRARY_PREFIX}${ZSTD_LIB_NAME_BASE}${CMAKE_SHARED_LIBRARY_SUFFIX}" + ) +else() + if(MSVC AND NOT DEFINED ZSTD_MSVC_STATIC_LIB_SUFFIX) + set(ZSTD_MSVC_STATIC_LIB_SUFFIX "_static") + endif() + set(ZSTD_STATIC_LIB_SUFFIX + "${ZSTD_MSVC_STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}") + set(ZSTD_LIB_NAMES + "${CMAKE_STATIC_LIBRARY_PREFIX}${ZSTD_LIB_NAME_BASE}${ZSTD_STATIC_LIB_SUFFIX}") +endif() + +# First, find via if specified ZSTD_ROOT +if(ZSTD_ROOT) + message(STATUS "Using ZSTD_ROOT: ${ZSTD_ROOT}") + find_library(ZSTD_LIB + NAMES ${ZSTD_LIB_NAMES} + PATHS ${ZSTD_ROOT} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES} + NO_DEFAULT_PATH) + find_path(ZSTD_INCLUDE_DIR + NAMES zstd.h + PATHS ${ZSTD_ROOT} + NO_DEFAULT_PATH + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) + +else() + # Second, find via pkg_check_modules + find_package(PkgConfig QUIET) + pkg_check_modules(ZSTD_PC libzstd) + if(ZSTD_PC_FOUND) + set(ZSTD_INCLUDE_DIR "${ZSTD_PC_INCLUDEDIR}") + + list(APPEND ZSTD_PC_LIBRARY_DIRS "${ZSTD_PC_LIBDIR}") + find_library(ZSTD_LIB + NAMES ${ZSTD_LIB_NAMES} + PATHS ${ZSTD_PC_LIBRARY_DIRS} + NO_DEFAULT_PATH + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES}) + else() + # Third, check all other CMake paths + find_library(ZSTD_LIB + NAMES ${ZSTD_LIB_NAMES} + PATH_SUFFIXES ${ARROW_LIBRARY_PATH_SUFFIXES}) + find_path(ZSTD_INCLUDE_DIR + NAMES zstd.h + PATH_SUFFIXES ${ARROW_INCLUDE_PATH_SUFFIXES}) + endif() +endif() + +find_package_handle_standard_args(zstd REQUIRED_VARS ZSTD_LIB ZSTD_INCLUDE_DIR) + +if(zstd_FOUND) + add_library(zstd::libzstd UNKNOWN IMPORTED) + set_target_properties(zstd::libzstd + PROPERTIES IMPORTED_LOCATION "${ZSTD_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${ZSTD_INCLUDE_DIR}") +endif() diff --git a/src/arrow/cpp/cmake_modules/SetupCxxFlags.cmake b/src/arrow/cpp/cmake_modules/SetupCxxFlags.cmake new file mode 100644 index 000000000..c1a1ba043 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/SetupCxxFlags.cmake @@ -0,0 +1,648 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Check if the target architecture and compiler supports some special +# instruction sets that would boost performance. +include(CheckCXXCompilerFlag) +include(CheckCXXSourceCompiles) +# Get cpu architecture + +message(STATUS "System processor: ${CMAKE_SYSTEM_PROCESSOR}") + +if(NOT DEFINED ARROW_CPU_FLAG) + if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64|arm64") + set(ARROW_CPU_FLAG "armv8") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "armv7") + set(ARROW_CPU_FLAG "armv7") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "powerpc|ppc") + set(ARROW_CPU_FLAG "ppc") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "s390x") + set(ARROW_CPU_FLAG "s390x") + else() + set(ARROW_CPU_FLAG "x86") + endif() +endif() + +# Check architecture specific compiler flags +if(ARROW_CPU_FLAG STREQUAL "x86") + # x86/amd64 compiler flags, msvc/gcc/clang + if(MSVC) + set(ARROW_SSE4_2_FLAG "") + set(ARROW_AVX2_FLAG "/arch:AVX2") + set(ARROW_AVX512_FLAG "/arch:AVX512") + set(CXX_SUPPORTS_SSE4_2 TRUE) + else() + set(ARROW_SSE4_2_FLAG "-msse4.2") + set(ARROW_AVX2_FLAG "-march=haswell") + # skylake-avx512 consists of AVX512F,AVX512BW,AVX512VL,AVX512CD,AVX512DQ + set(ARROW_AVX512_FLAG "-march=skylake-avx512 -mbmi2") + # Append the avx2/avx512 subset option also, fix issue ARROW-9877 for homebrew-cpp + set(ARROW_AVX2_FLAG "${ARROW_AVX2_FLAG} -mavx2") + set(ARROW_AVX512_FLAG + "${ARROW_AVX512_FLAG} -mavx512f -mavx512cd -mavx512vl -mavx512dq -mavx512bw") + check_cxx_compiler_flag(${ARROW_SSE4_2_FLAG} CXX_SUPPORTS_SSE4_2) + endif() + check_cxx_compiler_flag(${ARROW_AVX2_FLAG} CXX_SUPPORTS_AVX2) + if(MINGW) + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65782 + message(STATUS "Disable AVX512 support on MINGW for now") + else() + # Check for AVX512 support in the compiler. + set(OLD_CMAKE_REQURED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${ARROW_AVX512_FLAG}") + check_cxx_source_compiles(" + #ifdef _MSC_VER + #include <intrin.h> + #else + #include <immintrin.h> + #endif + + int main() { + __m512i mask = _mm512_set1_epi32(0x1); + char out[32]; + _mm512_storeu_si512(out, mask); + return 0; + }" + CXX_SUPPORTS_AVX512) + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQURED_FLAGS}) + endif() + # Runtime SIMD level it can get from compiler and ARROW_RUNTIME_SIMD_LEVEL + if(CXX_SUPPORTS_SSE4_2 AND ARROW_RUNTIME_SIMD_LEVEL MATCHES + "^(SSE4_2|AVX2|AVX512|MAX)$") + set(ARROW_HAVE_RUNTIME_SSE4_2 ON) + add_definitions(-DARROW_HAVE_RUNTIME_SSE4_2) + endif() + if(CXX_SUPPORTS_AVX2 AND ARROW_RUNTIME_SIMD_LEVEL MATCHES "^(AVX2|AVX512|MAX)$") + set(ARROW_HAVE_RUNTIME_AVX2 ON) + add_definitions(-DARROW_HAVE_RUNTIME_AVX2 -DARROW_HAVE_RUNTIME_BMI2) + endif() + if(CXX_SUPPORTS_AVX512 AND ARROW_RUNTIME_SIMD_LEVEL MATCHES "^(AVX512|MAX)$") + set(ARROW_HAVE_RUNTIME_AVX512 ON) + add_definitions(-DARROW_HAVE_RUNTIME_AVX512 -DARROW_HAVE_RUNTIME_BMI2) + endif() + if(ARROW_SIMD_LEVEL STREQUAL "DEFAULT") + set(ARROW_SIMD_LEVEL "SSE4_2") + endif() +elseif(ARROW_CPU_FLAG STREQUAL "ppc") + # power compiler flags, gcc/clang only + set(ARROW_ALTIVEC_FLAG "-maltivec") + check_cxx_compiler_flag(${ARROW_ALTIVEC_FLAG} CXX_SUPPORTS_ALTIVEC) + if(ARROW_SIMD_LEVEL STREQUAL "DEFAULT") + set(ARROW_SIMD_LEVEL "NONE") + endif() +elseif(ARROW_CPU_FLAG STREQUAL "armv8") + # Arm64 compiler flags, gcc/clang only + set(ARROW_ARMV8_ARCH_FLAG "-march=${ARROW_ARMV8_ARCH}") + check_cxx_compiler_flag(${ARROW_ARMV8_ARCH_FLAG} CXX_SUPPORTS_ARMV8_ARCH) + if(ARROW_SIMD_LEVEL STREQUAL "DEFAULT") + set(ARROW_SIMD_LEVEL "NEON") + endif() +endif() + +# Support C11 +if(NOT DEFINED CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 11) +endif() + +# This ensures that things like c++11 get passed correctly +if(NOT DEFINED CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 11) +endif() + +# We require a C++11 compliant compiler +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# ARROW-6848: Do not use GNU (or other CXX) extensions +set(CMAKE_CXX_EXTENSIONS OFF) + +# Build with -fPIC so that can static link our libraries into other people's +# shared libraries +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE) + +set(UNKNOWN_COMPILER_MESSAGE + "Unknown compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") + +# compiler flags that are common across debug/release builds +if(WIN32) + # TODO(wesm): Change usages of C runtime functions that MSVC says are + # insecure, like std::getenv + add_definitions(-D_CRT_SECURE_NO_WARNINGS) + + if(MSVC) + if(MSVC_VERSION VERSION_LESS 19) + message(FATAL_ERROR "Only MSVC 2015 (Version 19.0) and later are supported + by Arrow. Found version ${CMAKE_CXX_COMPILER_VERSION}.") + endif() + + # ARROW-1931 See https://github.com/google/googletest/issues/1318 + # + # This is added to CMAKE_CXX_FLAGS instead of CXX_COMMON_FLAGS since only the + # former is passed into the external projects + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING") + + if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + # clang-cl + set(CXX_COMMON_FLAGS "-EHsc") + else() + # Fix annoying D9025 warning + string(REPLACE "/W3" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + + # Set desired warning level (e.g. set /W4 for more warnings) + # + # ARROW-2986: Without /EHsc we get C4530 warning + set(CXX_COMMON_FLAGS "/W3 /EHsc") + endif() + + # Disable C5105 (macro expansion producing 'defined' has undefined + # behavior) warning because there are codes that produce this + # warning in Windows Kits. e.g.: + # + # #define _CRT_INTERNAL_NONSTDC_NAMES \ + # ( \ + # ( defined _CRT_DECLARE_NONSTDC_NAMES && _CRT_DECLARE_NONSTDC_NAMES) || \ + # (!defined _CRT_DECLARE_NONSTDC_NAMES && !__STDC__ ) \ + # ) + # + # See also: + # * C5105: https://docs.microsoft.com/en-US/cpp/error-messages/compiler-warnings/c5105 + # * Related reports: + # * https://developercommunity.visualstudio.com/content/problem/387684/c5105-with-stdioh-and-experimentalpreprocessor.html + # * https://developercommunity.visualstudio.com/content/problem/1249671/stdc17-generates-warning-compiling-windowsh.html + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /wd5105") + + if(ARROW_USE_STATIC_CRT) + foreach(c_flag + CMAKE_CXX_FLAGS + CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_MINSIZEREL + CMAKE_CXX_FLAGS_RELWITHDEBINFO + CMAKE_C_FLAGS + CMAKE_C_FLAGS_RELEASE + CMAKE_C_FLAGS_DEBUG + CMAKE_C_FLAGS_MINSIZEREL + CMAKE_C_FLAGS_RELWITHDEBINFO) + string(REPLACE "/MD" "-MT" ${c_flag} "${${c_flag}}") + endforeach() + endif() + + # Support large object code + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /bigobj") + + # We may use UTF-8 in source code such as + # cpp/src/arrow/compute/kernels/scalar_string_test.cc + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /utf-8") + else() + # MinGW + check_cxx_compiler_flag(-Wa,-mbig-obj CXX_SUPPORTS_BIG_OBJ) + if(CXX_SUPPORTS_BIG_OBJ) + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wa,-mbig-obj") + endif() + endif(MSVC) +else() + # Common flags set below with warning level + set(CXX_COMMON_FLAGS "") +endif() + +# BUILD_WARNING_LEVEL add warning/error compiler flags. The possible values are +# - PRODUCTION: Build with `-Wall` but do not add `-Werror`, so warnings do not +# halt the build. +# - CHECKIN: Build with `-Wall` and `-Wextra`. Also, add `-Werror` in debug mode +# so that any important warnings fail the build. +# - EVERYTHING: Like `CHECKIN`, but possible extra flags depending on the +# compiler, including `-Wextra`, `-Weverything`, `-pedantic`. +# This is the most aggressive warning level. + +# Defaults BUILD_WARNING_LEVEL to `CHECKIN`, unless CMAKE_BUILD_TYPE is +# `RELEASE`, then it will default to `PRODUCTION`. The goal of defaulting to +# `CHECKIN` is to avoid friction with long response time from CI. +if(NOT BUILD_WARNING_LEVEL) + if("${CMAKE_BUILD_TYPE}" STREQUAL "RELEASE") + set(BUILD_WARNING_LEVEL PRODUCTION) + else() + set(BUILD_WARNING_LEVEL CHECKIN) + endif() +endif(NOT BUILD_WARNING_LEVEL) +string(TOUPPER ${BUILD_WARNING_LEVEL} BUILD_WARNING_LEVEL) + +message(STATUS "Arrow build warning level: ${BUILD_WARNING_LEVEL}") + +macro(arrow_add_werror_if_debug) + if("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG") + # Treat all compiler warnings as errors + if(MSVC) + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /WX") + else() + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Werror") + endif() + endif() +endmacro() + +if("${BUILD_WARNING_LEVEL}" STREQUAL "CHECKIN") + # Pre-checkin builds + if(MSVC) + # https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warnings-by-compiler-version + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /W3") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /wd4365") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /wd4267") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /wd4838") + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL + "Clang") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wall") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wextra") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wdocumentation") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-missing-braces") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-unused-parameter") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-constant-logical-operand") + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wall") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-conversion") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-deprecated-declarations") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-sign-conversion") + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") + if(WIN32) + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /Wall") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /Wno-deprecated") + else() + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wall") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-deprecated") + endif() + else() + message(FATAL_ERROR "${UNKNOWN_COMPILER_MESSAGE}") + endif() + arrow_add_werror_if_debug() + +elseif("${BUILD_WARNING_LEVEL}" STREQUAL "EVERYTHING") + # Pedantic builds for fixing warnings + if(MSVC) + string(REPLACE "/W3" "" CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS}") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /Wall") + # https://docs.microsoft.com/en-us/cpp/build/reference/compiler-option-warning-level + # /wdnnnn disables a warning where "nnnn" is a warning number + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL + "Clang") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Weverything") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-c++98-compat") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-c++98-compat-pedantic") + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wall") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wpedantic") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wextra") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-unused-parameter") + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") + if(WIN32) + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /Wall") + else() + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wall") + endif() + else() + message(FATAL_ERROR "${UNKNOWN_COMPILER_MESSAGE}") + endif() + arrow_add_werror_if_debug() + +else() + # Production builds (warning are not treated as errors) + if(MSVC) + # https://docs.microsoft.com/en-us/cpp/build/reference/compiler-option-warning-level + # TODO: Enable /Wall and disable individual warnings until build compiles without errors + # /wdnnnn disables a warning where "nnnn" is a warning number + string(REPLACE "/W3" "" CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS}") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /W3") + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" + OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" + OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wall") + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") + if(WIN32) + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /Wall") + else() + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wall") + endif() + else() + message(FATAL_ERROR "${UNKNOWN_COMPILER_MESSAGE}") + endif() + +endif() + +if(MSVC) + # Disable annoying "performance warning" about int-to-bool conversion + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /wd4800") + + # Disable unchecked iterator warnings, equivalent to /D_SCL_SECURE_NO_WARNINGS + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /wd4996") + + # Disable "switch statement contains 'default' but no 'case' labels" warning + # (required for protobuf, see https://github.com/protocolbuffers/protobuf/issues/6885) + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} /wd4065") + +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + if(CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "7.0" OR CMAKE_CXX_COMPILER_VERSION + VERSION_GREATER "7.0") + # Without this, gcc >= 7 warns related to changes in C++17 + set(CXX_ONLY_FLAGS "${CXX_ONLY_FLAGS} -Wno-noexcept-type") + endif() + + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "5.2") + # Disabling semantic interposition allows faster calling conventions + # when calling global functions internally, and can also help inlining. + # See https://stackoverflow.com/questions/35745543/new-option-in-gcc-5-3-fno-semantic-interposition + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -fno-semantic-interposition") + endif() + + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "4.9") + # Add colors when paired with ninja + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always") + endif() + + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "6.0") + # Work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43407 + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-attributes") + endif() + + if(CMAKE_UNITY_BUILD) + # Work around issue similar to https://bugs.webkit.org/show_bug.cgi?id=176869 + set(CXX_ONLY_FLAGS "${CXX_ONLY_FLAGS} -Wno-subobject-linkage") + endif() + +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL + "Clang") + # Clang options for all builds + + # Using Clang with ccache causes a bunch of spurious warnings that are + # purportedly fixed in the next version of ccache. See the following for details: + # + # http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html + # http://petereisentraut.blogspot.com/2011/09/ccache-and-clang-part-2.html + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Qunused-arguments") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments") + + # Avoid error when an unknown warning flag is passed + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-unknown-warning-option") + # Add colors when paired with ninja + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics") + + # Don't complain about optimization passes that were not possible + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-pass-failed") + + if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + # Depending on the default OSX_DEPLOYMENT_TARGET (< 10.9), libstdc++ may be + # the default standard library which does not support C++11. libc++ is the + # default from 10.9 onward. + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -stdlib=libc++") + endif() +endif() + +# if build warning flags is set, add to CXX_COMMON_FLAGS +if(BUILD_WARNING_FLAGS) + # Use BUILD_WARNING_FLAGS with BUILD_WARNING_LEVEL=everything to disable + # warnings (use with Clang's -Weverything flag to find potential errors) + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} ${BUILD_WARNING_FLAGS}") +endif(BUILD_WARNING_FLAGS) + +# Only enable additional instruction sets if they are supported +if(ARROW_CPU_FLAG STREQUAL "x86") + if(MINGW) + # Enable _xgetbv() intrinsic to query OS support for ZMM register saves + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -mxsave") + endif() + if(ARROW_SIMD_LEVEL STREQUAL "AVX512") + if(NOT CXX_SUPPORTS_AVX512) + message(FATAL_ERROR "AVX512 required but compiler doesn't support it.") + endif() + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} ${ARROW_AVX512_FLAG}") + add_definitions(-DARROW_HAVE_AVX512 -DARROW_HAVE_AVX2 -DARROW_HAVE_BMI2 + -DARROW_HAVE_SSE4_2) + elseif(ARROW_SIMD_LEVEL STREQUAL "AVX2") + if(NOT CXX_SUPPORTS_AVX2) + message(FATAL_ERROR "AVX2 required but compiler doesn't support it.") + endif() + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} ${ARROW_AVX2_FLAG}") + add_definitions(-DARROW_HAVE_AVX2 -DARROW_HAVE_BMI2 -DARROW_HAVE_SSE4_2) + elseif(ARROW_SIMD_LEVEL STREQUAL "SSE4_2") + if(NOT CXX_SUPPORTS_SSE4_2) + message(FATAL_ERROR "SSE4.2 required but compiler doesn't support it.") + endif() + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} ${ARROW_SSE4_2_FLAG}") + add_definitions(-DARROW_HAVE_SSE4_2) + elseif(NOT ARROW_SIMD_LEVEL STREQUAL "NONE") + message(WARNING "ARROW_SIMD_LEVEL=${ARROW_SIMD_LEVEL} not supported by x86.") + endif() +endif() + +if(ARROW_CPU_FLAG STREQUAL "ppc") + if(CXX_SUPPORTS_ALTIVEC AND ARROW_ALTIVEC) + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} ${ARROW_ALTIVEC_FLAG}") + endif() +endif() + +if(ARROW_CPU_FLAG STREQUAL "armv8") + if(ARROW_SIMD_LEVEL STREQUAL "NEON") + set(ARROW_HAVE_NEON ON) + + if(NOT CXX_SUPPORTS_ARMV8_ARCH) + message(FATAL_ERROR "Unsupported arch flag: ${ARROW_ARMV8_ARCH_FLAG}.") + endif() + if(ARROW_ARMV8_ARCH_FLAG MATCHES "native") + message(FATAL_ERROR "native arch not allowed, please specify arch explicitly.") + endif() + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} ${ARROW_ARMV8_ARCH_FLAG}") + + add_definitions(-DARROW_HAVE_NEON) + + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS + "5.4") + message(WARNING "Disable Armv8 CRC and Crypto as compiler doesn't support them well." + ) + else() + if(ARROW_ARMV8_ARCH_FLAG MATCHES "\\+crypto") + add_definitions(-DARROW_HAVE_ARMV8_CRYPTO) + endif() + # armv8.1+ implies crc support + if(ARROW_ARMV8_ARCH_FLAG MATCHES "armv8\\.[1-9]|\\+crc") + add_definitions(-DARROW_HAVE_ARMV8_CRC) + endif() + endif() + elseif(NOT ARROW_SIMD_LEVEL STREQUAL "NONE") + message(WARNING "ARROW_SIMD_LEVEL=${ARROW_SIMD_LEVEL} not supported by Arm.") + endif() +endif() + +# ---------------------------------------------------------------------- +# Setup Gold linker, if available. Code originally from Apache Kudu + +# Interrogates the linker version via the C++ compiler to determine whether +# we're using the gold linker, and if so, extracts its version. +# +# If the gold linker is being used, sets GOLD_VERSION in the parent scope with +# the extracted version. +# +# Any additional arguments are passed verbatim into the C++ compiler invocation. +function(GET_GOLD_VERSION) + # The gold linker is only for ELF binaries, which macOS doesn't use. + execute_process(COMMAND ${CMAKE_CXX_COMPILER} "-Wl,--version" ${ARGN} + ERROR_QUIET + OUTPUT_VARIABLE LINKER_OUTPUT) + # We're expecting LINKER_OUTPUT to look like one of these: + # GNU gold (version 2.24) 1.11 + # GNU gold (GNU Binutils for Ubuntu 2.30) 1.15 + if(LINKER_OUTPUT MATCHES "GNU gold") + string(REGEX MATCH "GNU gold \\([^\\)]*\\) (([0-9]+\\.?)+)" _ "${LINKER_OUTPUT}") + if(NOT CMAKE_MATCH_1) + message(SEND_ERROR "Could not extract GNU gold version. " + "Linker version output: ${LINKER_OUTPUT}") + endif() + set(GOLD_VERSION + "${CMAKE_MATCH_1}" + PARENT_SCOPE) + endif() +endfunction() + +# Is the compiler hard-wired to use the gold linker? +if(NOT WIN32 AND NOT APPLE) + get_gold_version() + if(GOLD_VERSION) + set(MUST_USE_GOLD 1) + elseif(ARROW_USE_LD_GOLD) + # Can the compiler optionally enable the gold linker? + get_gold_version("-fuse-ld=gold") + + # We can't use the gold linker if it's inside devtoolset because the compiler + # won't find it when invoked directly from make/ninja (which is typically + # done outside devtoolset). + execute_process(COMMAND which ld.gold + OUTPUT_VARIABLE GOLD_LOCATION + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + if("${GOLD_LOCATION}" MATCHES "^/opt/rh/devtoolset") + message("Skipping optional gold linker (version ${GOLD_VERSION}) because " + "it's in devtoolset") + set(GOLD_VERSION) + endif() + endif() + + if(GOLD_VERSION) + # Older versions of the gold linker are vulnerable to a bug [1] which + # prevents weak symbols from being overridden properly. This leads to + # omitting of dependencies like tcmalloc (used in Kudu, where this + # workaround was written originally) + # + # How we handle this situation depends on other factors: + # - If gold is optional, we won't use it. + # - If gold is required, we'll either: + # - Raise an error in RELEASE builds (we shouldn't release such a product), or + # - Drop tcmalloc in all other builds. + # + # 1. https://sourceware.org/bugzilla/show_bug.cgi?id=16979. + if("${GOLD_VERSION}" VERSION_LESS "1.12") + set(ARROW_BUGGY_GOLD 1) + endif() + if(MUST_USE_GOLD) + message("Using hard-wired gold linker (version ${GOLD_VERSION})") + if(ARROW_BUGGY_GOLD) + if("${ARROW_LINK}" STREQUAL "d" AND "${CMAKE_BUILD_TYPE}" STREQUAL "RELEASE") + message(SEND_ERROR "Configured to use buggy gold with dynamic linking " + "in a RELEASE build") + endif() + endif() + elseif(NOT ARROW_BUGGY_GOLD) + # The Gold linker must be manually enabled. + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=gold") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold") + message("Using optional gold linker (version ${GOLD_VERSION})") + else() + message("Optional gold linker is buggy, using ld linker instead") + endif() + else() + message("Using ld linker") + endif() +endif() + +# compiler flags for different build types (run 'cmake -DCMAKE_BUILD_TYPE=<type> .') +# For all builds: +# For CMAKE_BUILD_TYPE=Debug +# -ggdb: Enable gdb debugging +# For CMAKE_BUILD_TYPE=FastDebug +# Same as DEBUG, except with some optimizations on. +# For CMAKE_BUILD_TYPE=Release +# -O3: Enable all compiler optimizations +# Debug symbols are stripped for reduced binary size. Add +# -DARROW_CXXFLAGS="-g" to add them +if(NOT MSVC) + if(ARROW_GGDB_DEBUG) + set(ARROW_DEBUG_SYMBOL_TYPE "gdb") + set(C_FLAGS_DEBUG "-g${ARROW_DEBUG_SYMBOL_TYPE} -O0") + set(C_FLAGS_FASTDEBUG "-g${ARROW_DEBUG_SYMBOL_TYPE} -O1") + set(CXX_FLAGS_DEBUG "-g${ARROW_DEBUG_SYMBOL_TYPE} -O0") + set(CXX_FLAGS_FASTDEBUG "-g${ARROW_DEBUG_SYMBOL_TYPE} -O1") + else() + set(C_FLAGS_DEBUG "-g -O0") + set(C_FLAGS_FASTDEBUG "-g -O1") + set(CXX_FLAGS_DEBUG "-g -O0") + set(CXX_FLAGS_FASTDEBUG "-g -O1") + endif() + + set(C_FLAGS_RELEASE "-O3 -DNDEBUG") + set(CXX_FLAGS_RELEASE "-O3 -DNDEBUG") +endif() + +set(C_FLAGS_PROFILE_GEN "${CXX_FLAGS_RELEASE} -fprofile-generate") +set(C_FLAGS_PROFILE_BUILD "${CXX_FLAGS_RELEASE} -fprofile-use") +set(CXX_FLAGS_PROFILE_GEN "${CXX_FLAGS_RELEASE} -fprofile-generate") +set(CXX_FLAGS_PROFILE_BUILD "${CXX_FLAGS_RELEASE} -fprofile-use") + +# Set compile flags based on the build type. +message("Configured for ${CMAKE_BUILD_TYPE} build (set with cmake -DCMAKE_BUILD_TYPE={release,debug,...})" +) +if("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS_DEBUG}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_FLAGS_DEBUG}") +elseif("${CMAKE_BUILD_TYPE}" STREQUAL "RELWITHDEBINFO") + +elseif("${CMAKE_BUILD_TYPE}" STREQUAL "FASTDEBUG") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS_FASTDEBUG}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_FLAGS_FASTDEBUG}") +elseif("${CMAKE_BUILD_TYPE}" STREQUAL "RELEASE") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS_RELEASE}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_FLAGS_RELEASE}") +elseif("${CMAKE_BUILD_TYPE}" STREQUAL "PROFILE_GEN") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS_PROFILE_GEN}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_FLAGS_PROFILE_GEN}") +elseif("${CMAKE_BUILD_TYPE}" STREQUAL "PROFILE_BUILD") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS_PROFILE_BUILD}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_FLAGS_PROFILE_BUILD}") +else() + message(FATAL_ERROR "Unknown build type: ${CMAKE_BUILD_TYPE}") +endif() + +message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}") + +# ---------------------------------------------------------------------- +# MSVC-specific linker options + +if(MSVC) + set(MSVC_LINKER_FLAGS) + if(MSVC_LINK_VERBOSE) + set(MSVC_LINKER_FLAGS "${MSVC_LINKER_FLAGS} /VERBOSE:LIB") + endif() + if(NOT ARROW_USE_STATIC_CRT) + set(MSVC_LINKER_FLAGS "${MSVC_LINKER_FLAGS} /NODEFAULTLIB:LIBCMT") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MSVC_LINKER_FLAGS}") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${MSVC_LINKER_FLAGS}") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${MSVC_LINKER_FLAGS}") + endif() +endif() diff --git a/src/arrow/cpp/cmake_modules/ThirdpartyToolchain.cmake b/src/arrow/cpp/cmake_modules/ThirdpartyToolchain.cmake new file mode 100644 index 000000000..a793f3046 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/ThirdpartyToolchain.cmake @@ -0,0 +1,4063 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +include(ProcessorCount) +processorcount(NPROC) + +add_custom_target(rapidjson) +add_custom_target(toolchain) +add_custom_target(toolchain-benchmarks) +add_custom_target(toolchain-tests) + +# Accumulate all bundled targets and we will splice them together later as +# libarrow_dependencies.a so that third party libraries have something usable +# to create statically-linked builds with some BUNDLED dependencies, including +# allocators like jemalloc and mimalloc +set(ARROW_BUNDLED_STATIC_LIBS) + +# Accumulate all system dependencies to provide suitable static link +# parameters to the third party libraries. +set(ARROW_SYSTEM_DEPENDENCIES) + +# ---------------------------------------------------------------------- +# Toolchain linkage options + +set(ARROW_RE2_LINKAGE + "static" + CACHE STRING "How to link the re2 library. static|shared (default static)") + +if(ARROW_PROTOBUF_USE_SHARED) + set(Protobuf_USE_STATIC_LIBS OFF) +else() + set(Protobuf_USE_STATIC_LIBS ON) +endif() + +# ---------------------------------------------------------------------- +# Resolve the dependencies + +set(ARROW_THIRDPARTY_DEPENDENCIES + AWSSDK + benchmark + Boost + Brotli + BZip2 + c-ares + gflags + GLOG + google_cloud_cpp_storage + gRPC + GTest + LLVM + Lz4 + ORC + re2 + Protobuf + RapidJSON + Snappy + Thrift + utf8proc + xsimd + ZLIB + zstd) + +# TODO(wesm): External GTest shared libraries are not currently +# supported when building with MSVC because of the way that +# conda-forge packages have 4 variants of the libraries packaged +# together +if(MSVC AND "${GTest_SOURCE}" STREQUAL "") + set(GTest_SOURCE "BUNDLED") +endif() + +# For backward compatibility. We use "BOOST_SOURCE" if "Boost_SOURCE" +# isn't specified and "BOOST_SOURCE" is specified. +# We renamed "BOOST" dependency name to "Boost" in 3.0.0 because +# upstreams (CMake and Boost) use "Boost" not "BOOST" as package name. +if("${Boost_SOURCE}" STREQUAL "" AND NOT "${BOOST_SOURCE}" STREQUAL "") + set(Boost_SOURCE ${BOOST_SOURCE}) +endif() + +# For backward compatibility. We use "RE2_SOURCE" if "re2_SOURCE" +# isn't specified and "RE2_SOURCE" is specified. +# We renamed "RE2" dependency name to "re2" in 3.0.0 because +# upstream uses "re2" not "RE2" as package name. +if("${re2_SOURCE}" STREQUAL "" AND NOT "${RE2_SOURCE}" STREQUAL "") + set(re2_SOURCE ${RE2_SOURCE}) +endif() + +message(STATUS "Using ${ARROW_DEPENDENCY_SOURCE} approach to find dependencies") + +if(ARROW_DEPENDENCY_SOURCE STREQUAL "CONDA") + if(MSVC) + set(ARROW_PACKAGE_PREFIX "$ENV{CONDA_PREFIX}/Library") + else() + set(ARROW_PACKAGE_PREFIX $ENV{CONDA_PREFIX}) + endif() + set(ARROW_ACTUAL_DEPENDENCY_SOURCE "SYSTEM") + message(STATUS "Using CONDA_PREFIX for ARROW_PACKAGE_PREFIX: ${ARROW_PACKAGE_PREFIX}") +else() + set(ARROW_ACTUAL_DEPENDENCY_SOURCE "${ARROW_DEPENDENCY_SOURCE}") +endif() + +if(ARROW_PACKAGE_PREFIX) + message(STATUS "Setting (unset) dependency *_ROOT variables: ${ARROW_PACKAGE_PREFIX}") + set(ENV{PKG_CONFIG_PATH} "${ARROW_PACKAGE_PREFIX}/lib/pkgconfig/") + + if(NOT ENV{BOOST_ROOT}) + set(ENV{BOOST_ROOT} ${ARROW_PACKAGE_PREFIX}) + endif() + if(NOT ENV{Boost_ROOT}) + set(ENV{Boost_ROOT} ${ARROW_PACKAGE_PREFIX}) + endif() +endif() + +# For each dependency, set dependency source to global default, if unset +foreach(DEPENDENCY ${ARROW_THIRDPARTY_DEPENDENCIES}) + if("${${DEPENDENCY}_SOURCE}" STREQUAL "") + set(${DEPENDENCY}_SOURCE ${ARROW_ACTUAL_DEPENDENCY_SOURCE}) + # If no ROOT was supplied and we have a global prefix, use it + if(NOT ${DEPENDENCY}_ROOT AND ARROW_PACKAGE_PREFIX) + set(${DEPENDENCY}_ROOT ${ARROW_PACKAGE_PREFIX}) + endif() + endif() +endforeach() + +macro(build_dependency DEPENDENCY_NAME) + if("${DEPENDENCY_NAME}" STREQUAL "AWSSDK") + build_awssdk() + elseif("${DEPENDENCY_NAME}" STREQUAL "benchmark") + build_benchmark() + elseif("${DEPENDENCY_NAME}" STREQUAL "Boost") + build_boost() + elseif("${DEPENDENCY_NAME}" STREQUAL "Brotli") + build_brotli() + elseif("${DEPENDENCY_NAME}" STREQUAL "BZip2") + build_bzip2() + elseif("${DEPENDENCY_NAME}" STREQUAL "c-ares") + build_cares() + elseif("${DEPENDENCY_NAME}" STREQUAL "gflags") + build_gflags() + elseif("${DEPENDENCY_NAME}" STREQUAL "GLOG") + build_glog() + elseif("${DEPENDENCY_NAME}" STREQUAL "google_cloud_cpp_storage") + build_google_cloud_cpp_storage() + elseif("${DEPENDENCY_NAME}" STREQUAL "gRPC") + build_grpc() + elseif("${DEPENDENCY_NAME}" STREQUAL "GTest") + build_gtest() + elseif("${DEPENDENCY_NAME}" STREQUAL "Lz4") + build_lz4() + elseif("${DEPENDENCY_NAME}" STREQUAL "ORC") + build_orc() + elseif("${DEPENDENCY_NAME}" STREQUAL "Protobuf") + build_protobuf() + elseif("${DEPENDENCY_NAME}" STREQUAL "RapidJSON") + build_rapidjson() + elseif("${DEPENDENCY_NAME}" STREQUAL "re2") + build_re2() + elseif("${DEPENDENCY_NAME}" STREQUAL "Snappy") + build_snappy() + elseif("${DEPENDENCY_NAME}" STREQUAL "Thrift") + build_thrift() + elseif("${DEPENDENCY_NAME}" STREQUAL "utf8proc") + build_utf8proc() + elseif("${DEPENDENCY_NAME}" STREQUAL "xsimd") + build_xsimd() + elseif("${DEPENDENCY_NAME}" STREQUAL "ZLIB") + build_zlib() + elseif("${DEPENDENCY_NAME}" STREQUAL "zstd") + build_zstd() + else() + message(FATAL_ERROR "Unknown thirdparty dependency to build: ${DEPENDENCY_NAME}") + endif() +endmacro() + +# Find modules are needed by the consumer in case of a static build, or if the +# linkage is PUBLIC or INTERFACE. +macro(provide_find_module PACKAGE_NAME) + set(module_ "${CMAKE_SOURCE_DIR}/cmake_modules/Find${PACKAGE_NAME}.cmake") + if(EXISTS "${module_}") + message(STATUS "Providing CMake module for ${PACKAGE_NAME}") + install(FILES "${module_}" DESTINATION "${ARROW_CMAKE_INSTALL_DIR}") + endif() + unset(module_) +endmacro() + +macro(resolve_dependency DEPENDENCY_NAME) + set(options) + set(one_value_args HAVE_ALT IS_RUNTIME_DEPENDENCY REQUIRED_VERSION USE_CONFIG) + set(multi_value_args PC_PACKAGE_NAMES) + cmake_parse_arguments(ARG + "${options}" + "${one_value_args}" + "${multi_value_args}" + ${ARGN}) + if(ARG_UNPARSED_ARGUMENTS) + message(SEND_ERROR "Error: unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}") + endif() + if("${ARG_IS_RUNTIME_DEPENDENCY}" STREQUAL "") + set(ARG_IS_RUNTIME_DEPENDENCY TRUE) + endif() + + if(ARG_HAVE_ALT) + set(PACKAGE_NAME "${DEPENDENCY_NAME}Alt") + else() + set(PACKAGE_NAME ${DEPENDENCY_NAME}) + endif() + set(FIND_PACKAGE_ARGUMENTS ${PACKAGE_NAME}) + if(ARG_REQUIRED_VERSION) + list(APPEND FIND_PACKAGE_ARGUMENTS ${ARG_REQUIRED_VERSION}) + endif() + if(ARG_USE_CONFIG) + list(APPEND FIND_PACKAGE_ARGUMENTS CONFIG) + endif() + if(${DEPENDENCY_NAME}_SOURCE STREQUAL "AUTO") + find_package(${FIND_PACKAGE_ARGUMENTS}) + if(${${PACKAGE_NAME}_FOUND}) + set(${DEPENDENCY_NAME}_SOURCE "SYSTEM") + else() + build_dependency(${DEPENDENCY_NAME}) + set(${DEPENDENCY_NAME}_SOURCE "BUNDLED") + endif() + elseif(${DEPENDENCY_NAME}_SOURCE STREQUAL "BUNDLED") + build_dependency(${DEPENDENCY_NAME}) + elseif(${DEPENDENCY_NAME}_SOURCE STREQUAL "SYSTEM") + find_package(${FIND_PACKAGE_ARGUMENTS} REQUIRED) + endif() + if(${DEPENDENCY_NAME}_SOURCE STREQUAL "SYSTEM" AND ARG_IS_RUNTIME_DEPENDENCY) + provide_find_module(${PACKAGE_NAME}) + list(APPEND ARROW_SYSTEM_DEPENDENCIES ${PACKAGE_NAME}) + find_package(PkgConfig QUIET) + foreach(ARG_PC_PACKAGE_NAME ${ARG_PC_PACKAGE_NAMES}) + pkg_check_modules(${ARG_PC_PACKAGE_NAME}_PC + ${ARG_PC_PACKAGE_NAME} + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + QUIET) + if(${${ARG_PC_PACKAGE_NAME}_PC_FOUND}) + string(APPEND ARROW_PC_REQUIRES_PRIVATE " ${ARG_PC_PACKAGE_NAME}") + endif() + endforeach() + endif() +endmacro() + +# ---------------------------------------------------------------------- +# Thirdparty versions, environment variables, source URLs + +set(THIRDPARTY_DIR "${arrow_SOURCE_DIR}/thirdparty") + +# Include vendored Flatbuffers +include_directories(SYSTEM "${THIRDPARTY_DIR}/flatbuffers/include") + +# ---------------------------------------------------------------------- +# Some EP's require other EP's + +if(PARQUET_REQUIRE_ENCRYPTION) + set(ARROW_JSON ON) +endif() + +if(ARROW_THRIFT) + set(ARROW_WITH_ZLIB ON) +endif() + +if(ARROW_HIVESERVER2 OR ARROW_PARQUET) + set(ARROW_WITH_THRIFT ON) + if(ARROW_HIVESERVER2) + set(ARROW_THRIFT_REQUIRED_COMPONENTS COMPILER) + else() + set(ARROW_THRIFT_REQUIRED_COMPONENTS) + endif() +else() + set(ARROW_WITH_THRIFT OFF) +endif() + +if(ARROW_FLIGHT) + set(ARROW_WITH_GRPC ON) + # gRPC requires zlib + set(ARROW_WITH_ZLIB ON) +endif() + +if(ARROW_GCS) + set(ARROW_WITH_GOOGLE_CLOUD_CPP ON) +endif() + +if(ARROW_JSON) + set(ARROW_WITH_RAPIDJSON ON) +endif() + +if(ARROW_ORC + OR ARROW_FLIGHT + OR ARROW_GANDIVA) + set(ARROW_WITH_PROTOBUF ON) +endif() + +if(ARROW_S3) + set(ARROW_WITH_ZLIB ON) +endif() + +if((NOT ARROW_COMPUTE) AND (NOT ARROW_GANDIVA)) + set(ARROW_WITH_UTF8PROC OFF) +endif() + +if((NOT ARROW_COMPUTE) + AND (NOT ARROW_GANDIVA) + AND (NOT ARROW_WITH_GRPC)) + set(ARROW_WITH_RE2 OFF) +endif() + +# ---------------------------------------------------------------------- +# Versions and URLs for toolchain builds, which also can be used to configure +# offline builds +# Note: We should not use the Apache dist server for build dependencies + +macro(set_urls URLS) + set(${URLS} ${ARGN}) + if(CMAKE_VERSION VERSION_LESS 3.7) + # ExternalProject doesn't support backup URLs; + # Feature only available starting in 3.7 + list(GET ${URLS} 0 ${URLS}) + endif() +endmacro() + +# Read toolchain versions from cpp/thirdparty/versions.txt +file(STRINGS "${THIRDPARTY_DIR}/versions.txt" TOOLCHAIN_VERSIONS_TXT) +foreach(_VERSION_ENTRY ${TOOLCHAIN_VERSIONS_TXT}) + # Exclude comments + if(NOT ((_VERSION_ENTRY MATCHES "^[^#][A-Za-z0-9-_]+_VERSION=") + OR (_VERSION_ENTRY MATCHES "^[^#][A-Za-z0-9-_]+_CHECKSUM="))) + continue() + endif() + + string(REGEX MATCH "^[^=]*" _VARIABLE_NAME ${_VERSION_ENTRY}) + string(REPLACE "${_VARIABLE_NAME}=" "" _VARIABLE_VALUE ${_VERSION_ENTRY}) + + # Skip blank or malformed lines + if(_VARIABLE_VALUE STREQUAL "") + continue() + endif() + + # For debugging + message(STATUS "${_VARIABLE_NAME}: ${_VARIABLE_VALUE}") + + set(${_VARIABLE_NAME} ${_VARIABLE_VALUE}) +endforeach() + +if(DEFINED ENV{ARROW_ABSL_URL}) + set(ABSL_SOURCE_URL "$ENV{ARROW_ABSL_URL}") +else() + set_urls(ABSL_SOURCE_URL + "https://github.com/abseil/abseil-cpp/archive/${ARROW_ABSL_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_AWS_C_COMMON_URL}) + set(AWS_C_COMMON_SOURCE_URL "$ENV{ARROW_AWS_C_COMMON_URL}") +else() + set_urls(AWS_C_COMMON_SOURCE_URL + "https://github.com/awslabs/aws-c-common/archive/${ARROW_AWS_C_COMMON_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_AWS_CHECKSUMS_URL}) + set(AWS_CHECKSUMS_SOURCE_URL "$ENV{ARROW_AWS_CHECKSUMS_URL}") +else() + set_urls(AWS_CHECKSUMS_SOURCE_URL + "https://github.com/awslabs/aws-checksums/archive/${ARROW_AWS_CHECKSUMS_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_AWS_C_EVENT_STREAM_URL}) + set(AWS_C_EVENT_STREAM_SOURCE_URL "$ENV{ARROW_AWS_C_EVENT_STREAM_URL}") +else() + set_urls(AWS_C_EVENT_STREAM_SOURCE_URL + "https://github.com/awslabs/aws-c-event-stream/archive/${ARROW_AWS_C_EVENT_STREAM_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_AWSSDK_URL}) + set(AWSSDK_SOURCE_URL "$ENV{ARROW_AWSSDK_URL}") +else() + set_urls(AWSSDK_SOURCE_URL + "https://github.com/aws/aws-sdk-cpp/archive/${ARROW_AWSSDK_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/aws-sdk-cpp-${ARROW_AWSSDK_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_BOOST_URL}) + set(BOOST_SOURCE_URL "$ENV{ARROW_BOOST_URL}") +else() + string(REPLACE "." "_" ARROW_BOOST_BUILD_VERSION_UNDERSCORES + ${ARROW_BOOST_BUILD_VERSION}) + set_urls(BOOST_SOURCE_URL + # These are trimmed boost bundles we maintain. + # See cpp/build-support/trim-boost.sh + # FIXME(ARROW-6407) automate uploading this archive to ensure it reflects + # our currently used packages and doesn't fall out of sync with + # ${ARROW_BOOST_BUILD_VERSION_UNDERSCORES} + "https://github.com/ursa-labs/thirdparty/releases/download/latest/boost_${ARROW_BOOST_BUILD_VERSION_UNDERSCORES}.tar.gz" + "https://boostorg.jfrog.io/artifactory/main/release/${ARROW_BOOST_BUILD_VERSION}/source/boost_${ARROW_BOOST_BUILD_VERSION_UNDERSCORES}.tar.gz" + "https://sourceforge.net/projects/boost/files/boost/${ARROW_BOOST_BUILD_VERSION}/boost_${ARROW_BOOST_BUILD_VERSION_UNDERSCORES}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_BROTLI_URL}) + set(BROTLI_SOURCE_URL "$ENV{ARROW_BROTLI_URL}") +else() + set_urls(BROTLI_SOURCE_URL + "https://github.com/google/brotli/archive/${ARROW_BROTLI_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/brotli-${ARROW_BROTLI_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_BZIP2_URL}) + set(ARROW_BZIP2_SOURCE_URL "$ENV{ARROW_BZIP2_URL}") +else() + set_urls(ARROW_BZIP2_SOURCE_URL + "https://sourceware.org/pub/bzip2/bzip2-${ARROW_BZIP2_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/bzip2-${ARROW_BZIP2_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_CARES_URL}) + set(CARES_SOURCE_URL "$ENV{ARROW_CARES_URL}") +else() + set_urls(CARES_SOURCE_URL + "https://c-ares.haxx.se/download/c-ares-${ARROW_CARES_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/cares-${ARROW_CARES_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_CRC32C_URL}) + set(CRC32C_URL "$ENV{ARROW_CRC32C_URL}") +else() + set_urls(CRC32C_SOURCE_URL + "https://github.com/google/crc32c/archive/${ARROW_CRC32C_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_GBENCHMARK_URL}) + set(GBENCHMARK_SOURCE_URL "$ENV{ARROW_GBENCHMARK_URL}") +else() + set_urls(GBENCHMARK_SOURCE_URL + "https://github.com/google/benchmark/archive/${ARROW_GBENCHMARK_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/gbenchmark-${ARROW_GBENCHMARK_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_GFLAGS_URL}) + set(GFLAGS_SOURCE_URL "$ENV{ARROW_GFLAGS_URL}") +else() + set_urls(GFLAGS_SOURCE_URL + "https://github.com/gflags/gflags/archive/${ARROW_GFLAGS_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/gflags-${ARROW_GFLAGS_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_GLOG_URL}) + set(GLOG_SOURCE_URL "$ENV{ARROW_GLOG_URL}") +else() + set_urls(GLOG_SOURCE_URL + "https://github.com/google/glog/archive/${ARROW_GLOG_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/glog-${ARROW_GLOG_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_GOOGLE_CLOUD_CPP_URL}) + set(google_cloud_cpp_storage_SOURCE_URL "$ENV{ARROW_GOOGLE_CLOUD_CPP_URL}") +else() + set_urls(google_cloud_cpp_storage_SOURCE_URL + "https://github.com/googleapis/google-cloud-cpp/archive/${ARROW_GOOGLE_CLOUD_CPP_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_GRPC_URL}) + set(GRPC_SOURCE_URL "$ENV{ARROW_GRPC_URL}") +else() + set_urls(GRPC_SOURCE_URL + "https://github.com/grpc/grpc/archive/${ARROW_GRPC_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/grpc-${ARROW_GRPC_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_GTEST_URL}) + set(GTEST_SOURCE_URL "$ENV{ARROW_GTEST_URL}") +else() + set_urls(GTEST_SOURCE_URL + "https://github.com/google/googletest/archive/release-${ARROW_GTEST_BUILD_VERSION}.tar.gz" + "https://chromium.googlesource.com/external/github.com/google/googletest/+archive/release-${ARROW_GTEST_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/gtest-${ARROW_GTEST_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_JEMALLOC_URL}) + set(JEMALLOC_SOURCE_URL "$ENV{ARROW_JEMALLOC_URL}") +else() + set_urls(JEMALLOC_SOURCE_URL + "https://github.com/jemalloc/jemalloc/releases/download/${ARROW_JEMALLOC_BUILD_VERSION}/jemalloc-${ARROW_JEMALLOC_BUILD_VERSION}.tar.bz2" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/jemalloc-${ARROW_JEMALLOC_BUILD_VERSION}.tar.bz2" + ) +endif() + +if(DEFINED ENV{ARROW_MIMALLOC_URL}) + set(MIMALLOC_SOURCE_URL "$ENV{ARROW_MIMALLOC_URL}") +else() + set_urls(MIMALLOC_SOURCE_URL + "https://github.com/microsoft/mimalloc/archive/${ARROW_MIMALLOC_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/mimalloc-${ARROW_MIMALLOC_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_NLOHMANN_JSON_URL}) + set(NLOHMANN_JSON_SOURCE_URL "$ENV{ARROW_NLOHMANN_JSON_URL}") +else() + set_urls(NLOHMANN_JSON_SOURCE_URL + "https://github.com/nlohmann/json/archive/${ARROW_NLOHMANN_JSON_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_LZ4_URL}) + set(LZ4_SOURCE_URL "$ENV{ARROW_LZ4_URL}") +else() + set_urls(LZ4_SOURCE_URL + "https://github.com/lz4/lz4/archive/${ARROW_LZ4_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/lz4-${ARROW_LZ4_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_ORC_URL}) + set(ORC_SOURCE_URL "$ENV{ARROW_ORC_URL}") +else() + set_urls(ORC_SOURCE_URL + "https://github.com/apache/orc/archive/rel/release-${ARROW_ORC_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/orc-${ARROW_ORC_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_PROTOBUF_URL}) + set(PROTOBUF_SOURCE_URL "$ENV{ARROW_PROTOBUF_URL}") +else() + string(SUBSTRING ${ARROW_PROTOBUF_BUILD_VERSION} 1 -1 + ARROW_PROTOBUF_STRIPPED_BUILD_VERSION) + # strip the leading `v` + set_urls(PROTOBUF_SOURCE_URL + "https://github.com/protocolbuffers/protobuf/releases/download/${ARROW_PROTOBUF_BUILD_VERSION}/protobuf-all-${ARROW_PROTOBUF_STRIPPED_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/protobuf-${ARROW_PROTOBUF_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_RE2_URL}) + set(RE2_SOURCE_URL "$ENV{ARROW_RE2_URL}") +else() + set_urls(RE2_SOURCE_URL + "https://github.com/google/re2/archive/${ARROW_RE2_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/re2-${ARROW_RE2_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_RAPIDJSON_URL}) + set(RAPIDJSON_SOURCE_URL "$ENV{ARROW_RAPIDJSON_URL}") +else() + set_urls(RAPIDJSON_SOURCE_URL + "https://github.com/miloyip/rapidjson/archive/${ARROW_RAPIDJSON_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/rapidjson-${ARROW_RAPIDJSON_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_SNAPPY_URL}) + set(SNAPPY_SOURCE_URL "$ENV{ARROW_SNAPPY_URL}") +else() + set_urls(SNAPPY_SOURCE_URL + "https://github.com/google/snappy/archive/${ARROW_SNAPPY_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/snappy-${ARROW_SNAPPY_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_THRIFT_URL}) + set(THRIFT_SOURCE_URL "$ENV{ARROW_THRIFT_URL}") +else() + set_urls(THRIFT_SOURCE_URL + "https://www.apache.org/dyn/closer.cgi?action=download&filename=/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz" + "https://downloads.apache.org/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz" + "https://github.com/apache/thrift/archive/v${ARROW_THRIFT_BUILD_VERSION}.tar.gz" + "https://apache.claz.org/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz" + "https://apache.cs.utah.edu/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz" + "https://apache.mirrors.lucidnetworks.net/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz" + "https://apache.osuosl.org/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz" + "https://ftp.wayne.edu/apache/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz" + "https://mirror.olnevhost.net/pub/apache/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz" + "https://mirrors.gigenet.com/apache/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz" + "https://mirrors.koehn.com/apache/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz" + "https://mirrors.ocf.berkeley.edu/apache/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz" + "https://mirrors.sonic.net/apache/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz" + "https://us.mirrors.quenda.co/apache/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_UTF8PROC_URL}) + set(ARROW_UTF8PROC_SOURCE_URL "$ENV{ARROW_UTF8PROC_URL}") +else() + set_urls(ARROW_UTF8PROC_SOURCE_URL + "https://github.com/JuliaStrings/utf8proc/archive/${ARROW_UTF8PROC_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_XSIMD_URL}) + set(XSIMD_SOURCE_URL "$ENV{ARROW_XSIMD_URL}") +else() + set_urls(XSIMD_SOURCE_URL + "https://github.com/xtensor-stack/xsimd/archive/${ARROW_XSIMD_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_ZLIB_URL}) + set(ZLIB_SOURCE_URL "$ENV{ARROW_ZLIB_URL}") +else() + set_urls(ZLIB_SOURCE_URL + "https://zlib.net/fossils/zlib-${ARROW_ZLIB_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/zlib-${ARROW_ZLIB_BUILD_VERSION}.tar.gz" + ) +endif() + +if(DEFINED ENV{ARROW_ZSTD_URL}) + set(ZSTD_SOURCE_URL "$ENV{ARROW_ZSTD_URL}") +else() + set_urls(ZSTD_SOURCE_URL + "https://github.com/facebook/zstd/archive/${ARROW_ZSTD_BUILD_VERSION}.tar.gz" + "https://github.com/ursa-labs/thirdparty/releases/download/latest/zstd-${ARROW_ZSTD_BUILD_VERSION}.tar.gz" + ) +endif() + +# ---------------------------------------------------------------------- +# ExternalProject options + +set(EP_CXX_FLAGS + "${CMAKE_CXX_COMPILER_ARG1} ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${UPPERCASE_BUILD_TYPE}}" +) +set(EP_C_FLAGS + "${CMAKE_C_COMPILER_ARG1} ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${UPPERCASE_BUILD_TYPE}}") + +if(NOT MSVC_TOOLCHAIN) + # Set -fPIC on all external projects + set(EP_CXX_FLAGS "${EP_CXX_FLAGS} -fPIC") + set(EP_C_FLAGS "${EP_C_FLAGS} -fPIC") +endif() + +# CC/CXX environment variables are captured on the first invocation of the +# builder (e.g make or ninja) instead of when CMake is invoked into to build +# directory. This leads to issues if the variables are exported in a subshell +# and the invocation of make/ninja is in distinct subshell without the same +# environment (CC/CXX). +set(EP_COMMON_TOOLCHAIN -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}) + +if(CMAKE_AR) + set(EP_COMMON_TOOLCHAIN ${EP_COMMON_TOOLCHAIN} -DCMAKE_AR=${CMAKE_AR}) +endif() + +if(CMAKE_RANLIB) + set(EP_COMMON_TOOLCHAIN ${EP_COMMON_TOOLCHAIN} -DCMAKE_RANLIB=${CMAKE_RANLIB}) +endif() + +# External projects are still able to override the following declarations. +# cmake command line will favor the last defined variable when a duplicate is +# encountered. This requires that `EP_COMMON_CMAKE_ARGS` is always the first +# argument. +set(EP_COMMON_CMAKE_ARGS + ${EP_COMMON_TOOLCHAIN} + ${EP_COMMON_CMAKE_ARGS} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_C_FLAGS=${EP_C_FLAGS} + -DCMAKE_C_FLAGS_${UPPERCASE_BUILD_TYPE}=${EP_C_FLAGS} + -DCMAKE_CXX_FLAGS=${EP_CXX_FLAGS} + -DCMAKE_CXX_FLAGS_${UPPERCASE_BUILD_TYPE}=${EP_CXX_FLAGS} + -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} + -DCMAKE_EXPORT_NO_PACKAGE_REGISTRY=${CMAKE_EXPORT_NO_PACKAGE_REGISTRY} + -DCMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=${CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY}) + +if(NOT ARROW_VERBOSE_THIRDPARTY_BUILD) + set(EP_LOG_OPTIONS + LOG_CONFIGURE + 1 + LOG_BUILD + 1 + LOG_INSTALL + 1 + LOG_DOWNLOAD + 1 + LOG_OUTPUT_ON_FAILURE + 1) + set(Boost_DEBUG FALSE) +else() + set(EP_LOG_OPTIONS) + set(Boost_DEBUG TRUE) +endif() + +# Ensure that a default make is set +if("${MAKE}" STREQUAL "") + if(NOT MSVC) + find_program(MAKE make) + endif() +endif() + +# Using make -j in sub-make is fragile +# see discussion https://github.com/apache/arrow/pull/2779 +if(${CMAKE_GENERATOR} MATCHES "Makefiles") + set(MAKE_BUILD_ARGS "") +else() + # limit the maximum number of jobs for ninja + set(MAKE_BUILD_ARGS "-j${NPROC}") +endif() + +# ---------------------------------------------------------------------- +# Find pthreads + +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads REQUIRED) + +# ---------------------------------------------------------------------- +# Add Boost dependencies (code adapted from Apache Kudu) + +macro(build_boost) + set(BOOST_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/boost_ep-prefix/src/boost_ep") + + # This is needed by the thrift_ep build + set(BOOST_ROOT ${BOOST_PREFIX}) + + if(ARROW_BOOST_REQUIRE_LIBRARY) + set(BOOST_LIB_DIR "${BOOST_PREFIX}/stage/lib") + set(BOOST_BUILD_LINK "static") + if("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG") + set(BOOST_BUILD_VARIANT "debug") + else() + set(BOOST_BUILD_VARIANT "release") + endif() + if(MSVC) + set(BOOST_CONFIGURE_COMMAND ".\\\\bootstrap.bat") + else() + set(BOOST_CONFIGURE_COMMAND "./bootstrap.sh") + endif() + + set(BOOST_BUILD_WITH_LIBRARIES "filesystem" "system") + string(REPLACE ";" "," BOOST_CONFIGURE_LIBRARIES "${BOOST_BUILD_WITH_LIBRARIES}") + list(APPEND BOOST_CONFIGURE_COMMAND "--prefix=${BOOST_PREFIX}" + "--with-libraries=${BOOST_CONFIGURE_LIBRARIES}") + set(BOOST_BUILD_COMMAND "./b2" "-j${NPROC}" "link=${BOOST_BUILD_LINK}" + "variant=${BOOST_BUILD_VARIANT}") + if(MSVC) + string(REGEX REPLACE "([0-9])$" ".\\1" BOOST_TOOLSET_MSVC_VERSION + ${MSVC_TOOLSET_VERSION}) + list(APPEND BOOST_BUILD_COMMAND "toolset=msvc-${BOOST_TOOLSET_MSVC_VERSION}") + set(BOOST_BUILD_WITH_LIBRARIES_MSVC) + foreach(_BOOST_LIB ${BOOST_BUILD_WITH_LIBRARIES}) + list(APPEND BOOST_BUILD_WITH_LIBRARIES_MSVC "--with-${_BOOST_LIB}") + endforeach() + list(APPEND BOOST_BUILD_COMMAND ${BOOST_BUILD_WITH_LIBRARIES_MSVC}) + else() + list(APPEND BOOST_BUILD_COMMAND "cxxflags=-fPIC") + endif() + + if(MSVC) + string(REGEX + REPLACE "^([0-9]+)\\.([0-9]+)\\.[0-9]+$" "\\1_\\2" + ARROW_BOOST_BUILD_VERSION_NO_MICRO_UNDERSCORE + ${ARROW_BOOST_BUILD_VERSION}) + set(BOOST_LIBRARY_SUFFIX "-vc${MSVC_TOOLSET_VERSION}-mt") + if(BOOST_BUILD_VARIANT STREQUAL "debug") + set(BOOST_LIBRARY_SUFFIX "${BOOST_LIBRARY_SUFFIX}-gd") + endif() + set(BOOST_LIBRARY_SUFFIX + "${BOOST_LIBRARY_SUFFIX}-x64-${ARROW_BOOST_BUILD_VERSION_NO_MICRO_UNDERSCORE}") + else() + set(BOOST_LIBRARY_SUFFIX "") + endif() + set(BOOST_STATIC_SYSTEM_LIBRARY + "${BOOST_LIB_DIR}/libboost_system${BOOST_LIBRARY_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + set(BOOST_STATIC_FILESYSTEM_LIBRARY + "${BOOST_LIB_DIR}/libboost_filesystem${BOOST_LIBRARY_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + set(BOOST_SYSTEM_LIBRARY boost_system_static) + set(BOOST_FILESYSTEM_LIBRARY boost_filesystem_static) + set(BOOST_BUILD_PRODUCTS ${BOOST_STATIC_SYSTEM_LIBRARY} + ${BOOST_STATIC_FILESYSTEM_LIBRARY}) + + add_thirdparty_lib(boost_system STATIC_LIB "${BOOST_STATIC_SYSTEM_LIBRARY}") + + add_thirdparty_lib(boost_filesystem STATIC_LIB "${BOOST_STATIC_FILESYSTEM_LIBRARY}") + + externalproject_add(boost_ep + URL ${BOOST_SOURCE_URL} + URL_HASH "SHA256=${ARROW_BOOST_BUILD_SHA256_CHECKSUM}" + BUILD_BYPRODUCTS ${BOOST_BUILD_PRODUCTS} + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND ${BOOST_CONFIGURE_COMMAND} + BUILD_COMMAND ${BOOST_BUILD_COMMAND} + INSTALL_COMMAND "" ${EP_LOG_OPTIONS}) + add_dependencies(boost_system_static boost_ep) + add_dependencies(boost_filesystem_static boost_ep) + else() + externalproject_add(boost_ep + ${EP_LOG_OPTIONS} + BUILD_COMMAND "" + CONFIGURE_COMMAND "" + INSTALL_COMMAND "" + URL ${BOOST_SOURCE_URL} + URL_HASH "SHA256=${ARROW_BOOST_BUILD_SHA256_CHECKSUM}") + endif() + set(Boost_INCLUDE_DIR "${BOOST_PREFIX}") + set(Boost_INCLUDE_DIRS "${Boost_INCLUDE_DIR}") + add_dependencies(toolchain boost_ep) + set(BOOST_VENDORED TRUE) +endmacro() + +if(ARROW_FLIGHT AND ARROW_BUILD_TESTS) + set(ARROW_BOOST_REQUIRED_VERSION "1.64") +else() + set(ARROW_BOOST_REQUIRED_VERSION "1.58") +endif() + +set(Boost_USE_MULTITHREADED ON) +if(MSVC AND ARROW_USE_STATIC_CRT) + set(Boost_USE_STATIC_RUNTIME ON) +endif() +set(Boost_ADDITIONAL_VERSIONS + "1.75.0" + "1.75" + "1.74.0" + "1.74" + "1.73.0" + "1.73" + "1.72.0" + "1.72" + "1.71.0" + "1.71" + "1.70.0" + "1.70" + "1.69.0" + "1.69" + "1.68.0" + "1.68" + "1.67.0" + "1.67" + "1.66.0" + "1.66" + "1.65.0" + "1.65" + "1.64.0" + "1.64" + "1.63.0" + "1.63" + "1.62.0" + "1.61" + "1.61.0" + "1.62" + "1.60.0" + "1.60") + +# Thrift needs Boost if we're building the bundled version with version < 0.13, +# so we first need to determine whether we're building it +if(ARROW_WITH_THRIFT AND Thrift_SOURCE STREQUAL "AUTO") + find_package(Thrift 0.11.0 MODULE COMPONENTS ${ARROW_THRIFT_REQUIRED_COMPONENTS}) + if(Thrift_FOUND) + find_package(PkgConfig QUIET) + pkg_check_modules(THRIFT_PC + thrift + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + QUIET) + if(THRIFT_PC_FOUND) + string(APPEND ARROW_PC_REQUIRES_PRIVATE " thrift") + endif() + else() + set(Thrift_SOURCE "BUNDLED") + endif() +endif() + +# Thrift < 0.13 has a compile-time header dependency on boost +if(Thrift_SOURCE STREQUAL "BUNDLED" AND ARROW_THRIFT_BUILD_VERSION VERSION_LESS "0.13") + set(THRIFT_REQUIRES_BOOST TRUE) +elseif(THRIFT_VERSION VERSION_LESS "0.13") + set(THRIFT_REQUIRES_BOOST TRUE) +else() + set(THRIFT_REQUIRES_BOOST FALSE) +endif() + +# Compilers that don't support int128_t have a compile-time +# (header-only) dependency on Boost for int128_t. +if(ARROW_USE_UBSAN) + # NOTE: Avoid native int128_t on clang with UBSan as it produces linker errors + # (such as "undefined reference to '__muloti4'") + set(ARROW_USE_NATIVE_INT128 FALSE) +else() + include(CheckCXXSymbolExists) + check_cxx_symbol_exists("__SIZEOF_INT128__" "" ARROW_USE_NATIVE_INT128) +endif() + +# - Gandiva has a compile-time (header-only) dependency on Boost, not runtime. +# - Tests need Boost at runtime. +# - S3FS and Flight benchmarks need Boost at runtime. +if(ARROW_BUILD_INTEGRATION + OR ARROW_BUILD_TESTS + OR (ARROW_FLIGHT AND ARROW_BUILD_BENCHMARKS) + OR (ARROW_S3 AND ARROW_BUILD_BENCHMARKS)) + set(ARROW_BOOST_REQUIRED TRUE) + set(ARROW_BOOST_REQUIRE_LIBRARY TRUE) +elseif(ARROW_GANDIVA + OR (ARROW_WITH_THRIFT AND THRIFT_REQUIRES_BOOST) + OR (NOT ARROW_USE_NATIVE_INT128)) + set(ARROW_BOOST_REQUIRED TRUE) + set(ARROW_BOOST_REQUIRE_LIBRARY FALSE) +else() + set(ARROW_BOOST_REQUIRED FALSE) +endif() + +if(ARROW_BOOST_REQUIRED) + resolve_dependency(Boost + HAVE_ALT + TRUE + REQUIRED_VERSION + ${ARROW_BOOST_REQUIRED_VERSION} + IS_RUNTIME_DEPENDENCY + # libarrow.so doesn't depend on libboost*. + FALSE) + + if(TARGET Boost::system) + set(BOOST_SYSTEM_LIBRARY Boost::system) + set(BOOST_FILESYSTEM_LIBRARY Boost::filesystem) + elseif(BoostAlt_FOUND) + set(BOOST_SYSTEM_LIBRARY ${Boost_SYSTEM_LIBRARY}) + set(BOOST_FILESYSTEM_LIBRARY ${Boost_FILESYSTEM_LIBRARY}) + else() + set(BOOST_SYSTEM_LIBRARY boost_system_static) + set(BOOST_FILESYSTEM_LIBRARY boost_filesystem_static) + endif() + set(ARROW_BOOST_LIBS ${BOOST_SYSTEM_LIBRARY} ${BOOST_FILESYSTEM_LIBRARY}) + + message(STATUS "Boost include dir: ${Boost_INCLUDE_DIR}") + message(STATUS "Boost libraries: ${ARROW_BOOST_LIBS}") + + include_directories(SYSTEM ${Boost_INCLUDE_DIR}) +endif() + +# ---------------------------------------------------------------------- +# Snappy + +macro(build_snappy) + message(STATUS "Building snappy from source") + set(SNAPPY_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/snappy_ep/src/snappy_ep-install") + set(SNAPPY_STATIC_LIB_NAME snappy) + set(SNAPPY_STATIC_LIB + "${SNAPPY_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}${SNAPPY_STATIC_LIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + + set(SNAPPY_CMAKE_ARGS + ${EP_COMMON_CMAKE_ARGS} -DCMAKE_INSTALL_LIBDIR=lib -DSNAPPY_BUILD_TESTS=OFF + "-DCMAKE_INSTALL_PREFIX=${SNAPPY_PREFIX}") + + externalproject_add(snappy_ep + ${EP_LOG_OPTIONS} + BUILD_IN_SOURCE 1 + INSTALL_DIR ${SNAPPY_PREFIX} + URL ${SNAPPY_SOURCE_URL} + URL_HASH "SHA256=${ARROW_SNAPPY_BUILD_SHA256_CHECKSUM}" + CMAKE_ARGS ${SNAPPY_CMAKE_ARGS} + BUILD_BYPRODUCTS "${SNAPPY_STATIC_LIB}") + + file(MAKE_DIRECTORY "${SNAPPY_PREFIX}/include") + + add_library(Snappy::snappy STATIC IMPORTED) + set_target_properties(Snappy::snappy + PROPERTIES IMPORTED_LOCATION "${SNAPPY_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES + "${SNAPPY_PREFIX}/include") + add_dependencies(toolchain snappy_ep) + add_dependencies(Snappy::snappy snappy_ep) + + list(APPEND ARROW_BUNDLED_STATIC_LIBS Snappy::snappy) +endmacro() + +if(ARROW_WITH_SNAPPY) + resolve_dependency(Snappy PC_PACKAGE_NAMES snappy) + if(${Snappy_SOURCE} STREQUAL "SYSTEM" AND NOT snappy_PC_FOUND) + get_target_property(SNAPPY_LIB Snappy::snappy IMPORTED_LOCATION) + string(APPEND ARROW_PC_LIBS_PRIVATE " ${SNAPPY_LIB}") + endif() + # TODO: Don't use global includes but rather target_include_directories + get_target_property(SNAPPY_INCLUDE_DIRS Snappy::snappy INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM ${SNAPPY_INCLUDE_DIRS}) +endif() + +# ---------------------------------------------------------------------- +# Brotli + +macro(build_brotli) + message(STATUS "Building brotli from source") + set(BROTLI_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/brotli_ep/src/brotli_ep-install") + set(BROTLI_INCLUDE_DIR "${BROTLI_PREFIX}/include") + set(BROTLI_LIB_DIR lib) + set(BROTLI_STATIC_LIBRARY_ENC + "${BROTLI_PREFIX}/${BROTLI_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}brotlienc-static${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + set(BROTLI_STATIC_LIBRARY_DEC + "${BROTLI_PREFIX}/${BROTLI_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}brotlidec-static${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + set(BROTLI_STATIC_LIBRARY_COMMON + "${BROTLI_PREFIX}/${BROTLI_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}brotlicommon-static${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + set(BROTLI_CMAKE_ARGS ${EP_COMMON_CMAKE_ARGS} "-DCMAKE_INSTALL_PREFIX=${BROTLI_PREFIX}" + -DCMAKE_INSTALL_LIBDIR=${BROTLI_LIB_DIR}) + + externalproject_add(brotli_ep + URL ${BROTLI_SOURCE_URL} + URL_HASH "SHA256=${ARROW_BROTLI_BUILD_SHA256_CHECKSUM}" + BUILD_BYPRODUCTS "${BROTLI_STATIC_LIBRARY_ENC}" + "${BROTLI_STATIC_LIBRARY_DEC}" + "${BROTLI_STATIC_LIBRARY_COMMON}" + ${BROTLI_BUILD_BYPRODUCTS} + ${EP_LOG_OPTIONS} + CMAKE_ARGS ${BROTLI_CMAKE_ARGS} + STEP_TARGETS headers_copy) + + add_dependencies(toolchain brotli_ep) + file(MAKE_DIRECTORY "${BROTLI_INCLUDE_DIR}") + + add_library(Brotli::brotlicommon STATIC IMPORTED) + set_target_properties(Brotli::brotlicommon + PROPERTIES IMPORTED_LOCATION "${BROTLI_STATIC_LIBRARY_COMMON}" + INTERFACE_INCLUDE_DIRECTORIES "${BROTLI_INCLUDE_DIR}") + add_dependencies(Brotli::brotlicommon brotli_ep) + + add_library(Brotli::brotlienc STATIC IMPORTED) + set_target_properties(Brotli::brotlienc + PROPERTIES IMPORTED_LOCATION "${BROTLI_STATIC_LIBRARY_ENC}" + INTERFACE_INCLUDE_DIRECTORIES "${BROTLI_INCLUDE_DIR}") + add_dependencies(Brotli::brotlienc brotli_ep) + + add_library(Brotli::brotlidec STATIC IMPORTED) + set_target_properties(Brotli::brotlidec + PROPERTIES IMPORTED_LOCATION "${BROTLI_STATIC_LIBRARY_DEC}" + INTERFACE_INCLUDE_DIRECTORIES "${BROTLI_INCLUDE_DIR}") + add_dependencies(Brotli::brotlidec brotli_ep) + + list(APPEND + ARROW_BUNDLED_STATIC_LIBS + Brotli::brotlicommon + Brotli::brotlienc + Brotli::brotlidec) +endmacro() + +if(ARROW_WITH_BROTLI) + resolve_dependency(Brotli PC_PACKAGE_NAMES libbrotlidec libbrotlienc) + # TODO: Don't use global includes but rather target_include_directories + get_target_property(BROTLI_INCLUDE_DIR Brotli::brotlicommon + INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM ${BROTLI_INCLUDE_DIR}) +endif() + +if(PARQUET_REQUIRE_ENCRYPTION AND NOT ARROW_PARQUET) + set(PARQUET_REQUIRE_ENCRYPTION OFF) +endif() +set(ARROW_OPENSSL_REQUIRED_VERSION "1.0.2") +if(BREW_BIN AND NOT OPENSSL_ROOT_DIR) + execute_process(COMMAND ${BREW_BIN} --prefix "openssl@1.1" + OUTPUT_VARIABLE OPENSSL11_BREW_PREFIX + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(OPENSSL11_BREW_PREFIX) + set(OPENSSL_ROOT_DIR ${OPENSSL11_BREW_PREFIX}) + else() + execute_process(COMMAND ${BREW_BIN} --prefix "openssl" + OUTPUT_VARIABLE OPENSSL_BREW_PREFIX + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(OPENSSL_BREW_PREFIX) + set(OPENSSL_ROOT_DIR ${OPENSSL_BREW_PREFIX}) + endif() + endif() +endif() + +set(ARROW_USE_OPENSSL OFF) +if(PARQUET_REQUIRE_ENCRYPTION + OR ARROW_FLIGHT + OR ARROW_S3) + # OpenSSL is required + if(ARROW_OPENSSL_USE_SHARED) + # Find shared OpenSSL libraries. + set(OpenSSL_USE_STATIC_LIBS OFF) + # Seems that different envs capitalize this differently? + set(OPENSSL_USE_STATIC_LIBS OFF) + set(BUILD_SHARED_LIBS_KEEP ${BUILD_SHARED_LIBS}) + set(BUILD_SHARED_LIBS ON) + + find_package(OpenSSL ${ARROW_OPENSSL_REQUIRED_VERSION} REQUIRED) + set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_KEEP}) + unset(BUILD_SHARED_LIBS_KEEP) + else() + # Find static OpenSSL headers and libs + set(OpenSSL_USE_STATIC_LIBS ON) + set(OPENSSL_USE_STATIC_LIBS ON) + find_package(OpenSSL ${ARROW_OPENSSL_REQUIRED_VERSION} REQUIRED) + endif() + set(ARROW_USE_OPENSSL ON) +endif() + +if(ARROW_USE_OPENSSL) + message(STATUS "Found OpenSSL Crypto Library: ${OPENSSL_CRYPTO_LIBRARY}") + message(STATUS "Building with OpenSSL (Version: ${OPENSSL_VERSION}) support") + + list(APPEND ARROW_SYSTEM_DEPENDENCIES "OpenSSL") + + include_directories(SYSTEM ${OPENSSL_INCLUDE_DIR}) +else() + message(STATUS "Building without OpenSSL support. Minimum OpenSSL version ${ARROW_OPENSSL_REQUIRED_VERSION} required." + ) +endif() + +# ---------------------------------------------------------------------- +# GLOG + +macro(build_glog) + message(STATUS "Building glog from source") + set(GLOG_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/glog_ep-prefix/src/glog_ep") + set(GLOG_INCLUDE_DIR "${GLOG_BUILD_DIR}/include") + if(${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG") + set(GLOG_LIB_SUFFIX "d") + else() + set(GLOG_LIB_SUFFIX "") + endif() + set(GLOG_STATIC_LIB + "${GLOG_BUILD_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}glog${GLOG_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + set(GLOG_CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") + set(GLOG_CMAKE_C_FLAGS "${EP_C_FLAGS} -fPIC") + if(CMAKE_THREAD_LIBS_INIT) + set(GLOG_CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_THREAD_LIBS_INIT}") + set(GLOG_CMAKE_C_FLAGS "${EP_C_FLAGS} ${CMAKE_THREAD_LIBS_INIT}") + endif() + + if(APPLE) + # If we don't set this flag, the binary built with 10.13 cannot be used in 10.12. + set(GLOG_CMAKE_CXX_FLAGS "${GLOG_CMAKE_CXX_FLAGS} -mmacosx-version-min=10.9") + endif() + + set(GLOG_CMAKE_ARGS + ${EP_COMMON_CMAKE_ARGS} + "-DCMAKE_INSTALL_PREFIX=${GLOG_BUILD_DIR}" + -DBUILD_SHARED_LIBS=OFF + -DBUILD_TESTING=OFF + -DWITH_GFLAGS=OFF + -DCMAKE_CXX_FLAGS_${UPPERCASE_BUILD_TYPE}=${GLOG_CMAKE_CXX_FLAGS} + -DCMAKE_C_FLAGS_${UPPERCASE_BUILD_TYPE}=${GLOG_CMAKE_C_FLAGS} + -DCMAKE_CXX_FLAGS=${GLOG_CMAKE_CXX_FLAGS}) + externalproject_add(glog_ep + URL ${GLOG_SOURCE_URL} + URL_HASH "SHA256=${ARROW_GLOG_BUILD_SHA256_CHECKSUM}" + BUILD_IN_SOURCE 1 + BUILD_BYPRODUCTS "${GLOG_STATIC_LIB}" + CMAKE_ARGS ${GLOG_CMAKE_ARGS} ${EP_LOG_OPTIONS}) + + add_dependencies(toolchain glog_ep) + file(MAKE_DIRECTORY "${GLOG_INCLUDE_DIR}") + + add_library(glog::glog STATIC IMPORTED) + set_target_properties(glog::glog + PROPERTIES IMPORTED_LOCATION "${GLOG_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${GLOG_INCLUDE_DIR}") + add_dependencies(glog::glog glog_ep) + + list(APPEND ARROW_BUNDLED_STATIC_LIBS glog::glog) +endmacro() + +if(ARROW_USE_GLOG) + resolve_dependency(GLOG PC_PACKAGE_NAMES libglog) + # TODO: Don't use global includes but rather target_include_directories + get_target_property(GLOG_INCLUDE_DIR glog::glog INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM ${GLOG_INCLUDE_DIR}) +endif() + +# ---------------------------------------------------------------------- +# gflags + +if(ARROW_BUILD_TESTS + OR ARROW_BUILD_BENCHMARKS + OR ARROW_BUILD_INTEGRATION + OR ARROW_PLASMA + OR ARROW_USE_GLOG + OR ARROW_WITH_GRPC) + set(ARROW_NEED_GFLAGS 1) +else() + set(ARROW_NEED_GFLAGS 0) +endif() + +macro(build_gflags) + message(STATUS "Building gflags from source") + + set(GFLAGS_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/gflags_ep-prefix/src/gflags_ep") + set(GFLAGS_INCLUDE_DIR "${GFLAGS_PREFIX}/include") + if(${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG") + set(GFLAGS_LIB_SUFFIX "_debug") + else() + set(GFLAGS_LIB_SUFFIX "") + endif() + if(MSVC) + set(GFLAGS_STATIC_LIB "${GFLAGS_PREFIX}/lib/gflags_static${GFLAGS_LIB_SUFFIX}.lib") + else() + set(GFLAGS_STATIC_LIB "${GFLAGS_PREFIX}/lib/libgflags${GFLAGS_LIB_SUFFIX}.a") + endif() + set(GFLAGS_CMAKE_ARGS + ${EP_COMMON_CMAKE_ARGS} + "-DCMAKE_INSTALL_PREFIX=${GFLAGS_PREFIX}" + -DBUILD_SHARED_LIBS=OFF + -DBUILD_STATIC_LIBS=ON + -DBUILD_PACKAGING=OFF + -DBUILD_TESTING=OFF + -DBUILD_CONFIG_TESTS=OFF + -DINSTALL_HEADERS=ON) + + file(MAKE_DIRECTORY "${GFLAGS_INCLUDE_DIR}") + externalproject_add(gflags_ep + URL ${GFLAGS_SOURCE_URL} ${EP_LOG_OPTIONS} + URL_HASH "SHA256=${ARROW_GFLAGS_BUILD_SHA256_CHECKSUM}" + BUILD_IN_SOURCE 1 + BUILD_BYPRODUCTS "${GFLAGS_STATIC_LIB}" + CMAKE_ARGS ${GFLAGS_CMAKE_ARGS}) + + add_dependencies(toolchain gflags_ep) + + add_thirdparty_lib(gflags STATIC_LIB ${GFLAGS_STATIC_LIB}) + set(GFLAGS_LIBRARY gflags_static) + set_target_properties(${GFLAGS_LIBRARY} + PROPERTIES INTERFACE_COMPILE_DEFINITIONS "GFLAGS_IS_A_DLL=0" + INTERFACE_INCLUDE_DIRECTORIES "${GFLAGS_INCLUDE_DIR}") + if(MSVC) + set_target_properties(${GFLAGS_LIBRARY} PROPERTIES INTERFACE_LINK_LIBRARIES + "shlwapi.lib") + endif() + set(GFLAGS_LIBRARIES ${GFLAGS_LIBRARY}) + + set(GFLAGS_VENDORED TRUE) + + list(APPEND ARROW_BUNDLED_STATIC_LIBS gflags_static) +endmacro() + +if(ARROW_NEED_GFLAGS) + set(ARROW_GFLAGS_REQUIRED_VERSION "2.1.0") + resolve_dependency(gflags + HAVE_ALT + TRUE + REQUIRED_VERSION + ${ARROW_GFLAGS_REQUIRED_VERSION} + IS_RUNTIME_DEPENDENCY + FALSE) + # TODO: Don't use global includes but rather target_include_directories + include_directories(SYSTEM ${GFLAGS_INCLUDE_DIR}) + + if(NOT TARGET ${GFLAGS_LIBRARIES}) + if(TARGET gflags-shared) + set(GFLAGS_LIBRARIES gflags-shared) + elseif(TARGET gflags_shared) + set(GFLAGS_LIBRARIES gflags_shared) + endif() + endif() +endif() + +# ---------------------------------------------------------------------- +# Thrift + +macro(build_thrift) + if(CMAKE_VERSION VERSION_LESS 3.10) + message(FATAL_ERROR "Building thrift using ExternalProject requires at least CMake 3.10" + ) + endif() + message("Building Apache Thrift from source") + set(THRIFT_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/thrift_ep-install") + set(THRIFT_INCLUDE_DIR "${THRIFT_PREFIX}/include") + set(THRIFT_CMAKE_ARGS + ${EP_COMMON_CMAKE_ARGS} + "-DCMAKE_INSTALL_PREFIX=${THRIFT_PREFIX}" + "-DCMAKE_INSTALL_RPATH=${THRIFT_PREFIX}/lib" + -DBUILD_COMPILER=OFF + -DBUILD_SHARED_LIBS=OFF + -DBUILD_TESTING=OFF + -DBUILD_EXAMPLES=OFF + -DBUILD_TUTORIALS=OFF + -DWITH_QT4=OFF + -DWITH_C_GLIB=OFF + -DWITH_JAVA=OFF + -DWITH_PYTHON=OFF + -DWITH_HASKELL=OFF + -DWITH_CPP=ON + -DWITH_STATIC_LIB=ON + -DWITH_LIBEVENT=OFF + # Work around https://gitlab.kitware.com/cmake/cmake/issues/18865 + -DBoost_NO_BOOST_CMAKE=ON) + + # Thrift also uses boost. Forward important boost settings if there were ones passed. + if(DEFINED BOOST_ROOT) + list(APPEND THRIFT_CMAKE_ARGS "-DBOOST_ROOT=${BOOST_ROOT}") + endif() + if(DEFINED Boost_NAMESPACE) + list(APPEND THRIFT_CMAKE_ARGS "-DBoost_NAMESPACE=${Boost_NAMESPACE}") + endif() + + set(THRIFT_STATIC_LIB_NAME "${CMAKE_STATIC_LIBRARY_PREFIX}thrift") + if(MSVC) + if(ARROW_USE_STATIC_CRT) + set(THRIFT_STATIC_LIB_NAME "${THRIFT_STATIC_LIB_NAME}mt") + list(APPEND THRIFT_CMAKE_ARGS "-DWITH_MT=ON") + else() + set(THRIFT_STATIC_LIB_NAME "${THRIFT_STATIC_LIB_NAME}md") + list(APPEND THRIFT_CMAKE_ARGS "-DWITH_MT=OFF") + endif() + endif() + if(${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG") + set(THRIFT_STATIC_LIB_NAME "${THRIFT_STATIC_LIB_NAME}d") + endif() + set(THRIFT_STATIC_LIB + "${THRIFT_PREFIX}/lib/${THRIFT_STATIC_LIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}") + + if(BOOST_VENDORED) + set(THRIFT_DEPENDENCIES ${THRIFT_DEPENDENCIES} boost_ep) + endif() + + externalproject_add(thrift_ep + URL ${THRIFT_SOURCE_URL} + URL_HASH "SHA256=${ARROW_THRIFT_BUILD_SHA256_CHECKSUM}" + BUILD_BYPRODUCTS "${THRIFT_STATIC_LIB}" + CMAKE_ARGS ${THRIFT_CMAKE_ARGS} + DEPENDS ${THRIFT_DEPENDENCIES} ${EP_LOG_OPTIONS}) + + add_library(thrift::thrift STATIC IMPORTED) + # The include directory must exist before it is referenced by a target. + file(MAKE_DIRECTORY "${THRIFT_INCLUDE_DIR}") + set_target_properties(thrift::thrift + PROPERTIES IMPORTED_LOCATION "${THRIFT_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${THRIFT_INCLUDE_DIR}") + add_dependencies(toolchain thrift_ep) + add_dependencies(thrift::thrift thrift_ep) + set(THRIFT_VERSION ${ARROW_THRIFT_BUILD_VERSION}) + + list(APPEND ARROW_BUNDLED_STATIC_LIBS thrift::thrift) +endmacro() + +if(ARROW_WITH_THRIFT) + # We already may have looked for Thrift earlier, when considering whether + # to build Boost, so don't look again if already found. + if(NOT Thrift_FOUND) + # Thrift c++ code generated by 0.13 requires 0.11 or greater + resolve_dependency(Thrift + REQUIRED_VERSION + 0.11.0 + PC_PACKAGE_NAMES + thrift) + endif() + # TODO: Don't use global includes but rather target_include_directories + include_directories(SYSTEM ${THRIFT_INCLUDE_DIR}) + + string(REPLACE "." ";" VERSION_LIST ${THRIFT_VERSION}) + list(GET VERSION_LIST 0 THRIFT_VERSION_MAJOR) + list(GET VERSION_LIST 1 THRIFT_VERSION_MINOR) + list(GET VERSION_LIST 2 THRIFT_VERSION_PATCH) +endif() + +# ---------------------------------------------------------------------- +# Protocol Buffers (required for ORC and Flight and Gandiva libraries) + +macro(build_protobuf) + message("Building Protocol Buffers from source") + set(PROTOBUF_VENDORED TRUE) + set(PROTOBUF_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/protobuf_ep-install") + set(PROTOBUF_INCLUDE_DIR "${PROTOBUF_PREFIX}/include") + # Newer protobuf releases always have a lib prefix independent from CMAKE_STATIC_LIBRARY_PREFIX + set(PROTOBUF_STATIC_LIB + "${PROTOBUF_PREFIX}/lib/libprotobuf${CMAKE_STATIC_LIBRARY_SUFFIX}") + set(PROTOC_STATIC_LIB "${PROTOBUF_PREFIX}/lib/libprotoc${CMAKE_STATIC_LIBRARY_SUFFIX}") + set(Protobuf_PROTOC_LIBRARY "${PROTOC_STATIC_LIB}") + set(PROTOBUF_COMPILER "${PROTOBUF_PREFIX}/bin/protoc") + + if(CMAKE_VERSION VERSION_LESS 3.7) + set(PROTOBUF_CONFIGURE_ARGS + "AR=${CMAKE_AR}" + "RANLIB=${CMAKE_RANLIB}" + "CC=${CMAKE_C_COMPILER}" + "CXX=${CMAKE_CXX_COMPILER}" + "--disable-shared" + "--prefix=${PROTOBUF_PREFIX}" + "CFLAGS=${EP_C_FLAGS}" + "CXXFLAGS=${EP_CXX_FLAGS}") + set(PROTOBUF_BUILD_COMMAND ${MAKE} ${MAKE_BUILD_ARGS}) + if(CMAKE_OSX_SYSROOT) + list(APPEND PROTOBUF_CONFIGURE_ARGS "SDKROOT=${CMAKE_OSX_SYSROOT}") + list(APPEND PROTOBUF_BUILD_COMMAND "SDKROOT=${CMAKE_OSX_SYSROOT}") + endif() + set(PROTOBUF_EXTERNAL_PROJECT_ADD_ARGS + CONFIGURE_COMMAND + "./configure" + ${PROTOBUF_CONFIGURE_ARGS} + BUILD_COMMAND + ${PROTOBUF_BUILD_COMMAND}) + else() + # Strip lto flags (which may be added by dh_auto_configure) + # See https://github.com/protocolbuffers/protobuf/issues/7092 + set(PROTOBUF_C_FLAGS ${EP_C_FLAGS}) + set(PROTOBUF_CXX_FLAGS ${EP_CXX_FLAGS}) + string(REPLACE "-flto=auto" "" PROTOBUF_C_FLAGS "${PROTOBUF_C_FLAGS}") + string(REPLACE "-ffat-lto-objects" "" PROTOBUF_C_FLAGS "${PROTOBUF_C_FLAGS}") + string(REPLACE "-flto=auto" "" PROTOBUF_CXX_FLAGS "${PROTOBUF_CXX_FLAGS}") + string(REPLACE "-ffat-lto-objects" "" PROTOBUF_CXX_FLAGS "${PROTOBUF_CXX_FLAGS}") + set(PROTOBUF_CMAKE_ARGS + ${EP_COMMON_CMAKE_ARGS} + -DBUILD_SHARED_LIBS=OFF + -DCMAKE_INSTALL_LIBDIR=lib + "-DCMAKE_INSTALL_PREFIX=${PROTOBUF_PREFIX}" + -Dprotobuf_BUILD_TESTS=OFF + -Dprotobuf_DEBUG_POSTFIX= + "-DCMAKE_C_FLAGS=${PROTOBUF_C_FLAGS}" + "-DCMAKE_CXX_FLAGS=${PROTOBUF_CXX_FLAGS}" + "-DCMAKE_C_FLAGS_${UPPERCASE_BUILD_TYPE}=${PROTOBUF_C_FLAGS}" + "-DCMAKE_CXX_FLAGS_${UPPERCASE_BUILD_TYPE}=${PROTOBUF_CXX_FLAGS}") + if(MSVC AND NOT ARROW_USE_STATIC_CRT) + list(APPEND PROTOBUF_CMAKE_ARGS "-Dprotobuf_MSVC_STATIC_RUNTIME=OFF") + endif() + if(ZLIB_ROOT) + list(APPEND PROTOBUF_CMAKE_ARGS "-DZLIB_ROOT=${ZLIB_ROOT}") + endif() + set(PROTOBUF_EXTERNAL_PROJECT_ADD_ARGS CMAKE_ARGS ${PROTOBUF_CMAKE_ARGS} + SOURCE_SUBDIR "cmake") + endif() + + externalproject_add(protobuf_ep + ${PROTOBUF_EXTERNAL_PROJECT_ADD_ARGS} + BUILD_BYPRODUCTS "${PROTOBUF_STATIC_LIB}" "${PROTOBUF_COMPILER}" + ${EP_LOG_OPTIONS} + BUILD_IN_SOURCE 1 + URL ${PROTOBUF_SOURCE_URL} + URL_HASH "SHA256=${ARROW_PROTOBUF_BUILD_SHA256_CHECKSUM}") + + file(MAKE_DIRECTORY "${PROTOBUF_INCLUDE_DIR}") + + add_library(arrow::protobuf::libprotobuf STATIC IMPORTED) + set_target_properties(arrow::protobuf::libprotobuf + PROPERTIES IMPORTED_LOCATION "${PROTOBUF_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES + "${PROTOBUF_INCLUDE_DIR}") + add_library(arrow::protobuf::libprotoc STATIC IMPORTED) + set_target_properties(arrow::protobuf::libprotoc + PROPERTIES IMPORTED_LOCATION "${PROTOC_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES + "${PROTOBUF_INCLUDE_DIR}") + add_executable(arrow::protobuf::protoc IMPORTED) + set_target_properties(arrow::protobuf::protoc PROPERTIES IMPORTED_LOCATION + "${PROTOBUF_COMPILER}") + + add_dependencies(toolchain protobuf_ep) + add_dependencies(arrow::protobuf::libprotobuf protobuf_ep) + + list(APPEND ARROW_BUNDLED_STATIC_LIBS arrow::protobuf::libprotobuf) +endmacro() + +if(ARROW_WITH_PROTOBUF) + if(ARROW_WITH_GRPC) + # FlightSQL uses proto3 optionals, which require 3.15 or later. + set(ARROW_PROTOBUF_REQUIRED_VERSION "3.15.0") + elseif(ARROW_GANDIVA_JAVA) + # google::protobuf::MessageLite::ByteSize() is deprecated since + # Protobuf 3.4.0. + set(ARROW_PROTOBUF_REQUIRED_VERSION "3.4.0") + else() + set(ARROW_PROTOBUF_REQUIRED_VERSION "2.6.1") + endif() + resolve_dependency(Protobuf + REQUIRED_VERSION + ${ARROW_PROTOBUF_REQUIRED_VERSION} + PC_PACKAGE_NAMES + protobuf) + + if(ARROW_PROTOBUF_USE_SHARED AND MSVC_TOOLCHAIN) + add_definitions(-DPROTOBUF_USE_DLLS) + endif() + + # TODO: Don't use global includes but rather target_include_directories + include_directories(SYSTEM ${PROTOBUF_INCLUDE_DIR}) + + if(TARGET arrow::protobuf::libprotobuf) + set(ARROW_PROTOBUF_LIBPROTOBUF arrow::protobuf::libprotobuf) + else() + # CMake 3.8 or older don't define the targets + if(NOT TARGET protobuf::libprotobuf) + add_library(protobuf::libprotobuf UNKNOWN IMPORTED) + set_target_properties(protobuf::libprotobuf + PROPERTIES IMPORTED_LOCATION "${PROTOBUF_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${PROTOBUF_INCLUDE_DIR}") + endif() + set(ARROW_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) + endif() + if(TARGET arrow::protobuf::libprotoc) + set(ARROW_PROTOBUF_LIBPROTOC arrow::protobuf::libprotoc) + else() + # CMake 3.8 or older don't define the targets + if(NOT TARGET protobuf::libprotoc) + if(PROTOBUF_PROTOC_LIBRARY AND NOT Protobuf_PROTOC_LIBRARY) + # Old CMake versions have a different casing. + set(Protobuf_PROTOC_LIBRARY ${PROTOBUF_PROTOC_LIBRARY}) + endif() + if(NOT Protobuf_PROTOC_LIBRARY) + message(FATAL_ERROR "libprotoc was set to ${Protobuf_PROTOC_LIBRARY}") + endif() + add_library(protobuf::libprotoc UNKNOWN IMPORTED) + set_target_properties(protobuf::libprotoc + PROPERTIES IMPORTED_LOCATION "${Protobuf_PROTOC_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${PROTOBUF_INCLUDE_DIR}") + endif() + set(ARROW_PROTOBUF_LIBPROTOC protobuf::libprotoc) + endif() + if(TARGET arrow::protobuf::protoc) + set(ARROW_PROTOBUF_PROTOC arrow::protobuf::protoc) + else() + if(NOT TARGET protobuf::protoc) + add_executable(protobuf::protoc IMPORTED) + set_target_properties(protobuf::protoc PROPERTIES IMPORTED_LOCATION + "${PROTOBUF_PROTOC_EXECUTABLE}") + endif() + set(ARROW_PROTOBUF_PROTOC protobuf::protoc) + endif() + + # Log protobuf paths as we often see issues with mixed sources for + # the libraries and protoc. + get_target_property(PROTOBUF_PROTOC_EXECUTABLE ${ARROW_PROTOBUF_PROTOC} + IMPORTED_LOCATION) + message(STATUS "Found protoc: ${PROTOBUF_PROTOC_EXECUTABLE}") + # Protobuf_PROTOC_LIBRARY is set by all versions of FindProtobuf.cmake + message(STATUS "Found libprotoc: ${Protobuf_PROTOC_LIBRARY}") + get_target_property(PROTOBUF_LIBRARY ${ARROW_PROTOBUF_LIBPROTOBUF} IMPORTED_LOCATION) + message(STATUS "Found libprotobuf: ${PROTOBUF_LIBRARY}") + message(STATUS "Found protobuf headers: ${PROTOBUF_INCLUDE_DIR}") +endif() + +# ---------------------------------------------------------------------- +# jemalloc - Unix-only high-performance allocator + +if(ARROW_JEMALLOC) + message(STATUS "Building (vendored) jemalloc from source") + # We only use a vendored jemalloc as we want to control its version. + # Also our build of jemalloc is specially prefixed so that it will not + # conflict with the default allocator as well as other jemalloc + # installations. + # find_package(jemalloc) + + set(ARROW_JEMALLOC_USE_SHARED OFF) + set(JEMALLOC_PREFIX + "${CMAKE_CURRENT_BINARY_DIR}/jemalloc_ep-prefix/src/jemalloc_ep/dist/") + set(JEMALLOC_LIB_DIR "${JEMALLOC_PREFIX}/lib") + set(JEMALLOC_STATIC_LIB + "${JEMALLOC_LIB_DIR}/libjemalloc_pic${CMAKE_STATIC_LIBRARY_SUFFIX}") + set(JEMALLOC_CONFIGURE_COMMAND ./configure "AR=${CMAKE_AR}" "CC=${CMAKE_C_COMPILER}") + if(CMAKE_OSX_SYSROOT) + list(APPEND JEMALLOC_CONFIGURE_COMMAND "SDKROOT=${CMAKE_OSX_SYSROOT}") + endif() + if(DEFINED ARROW_JEMALLOC_LG_PAGE) + # Used for arm64 manylinux wheels in order to make the wheel work on both + # 4k and 64k page arm64 systems. + list(APPEND JEMALLOC_CONFIGURE_COMMAND "--with-lg-page=${ARROW_JEMALLOC_LG_PAGE}") + endif() + list(APPEND + JEMALLOC_CONFIGURE_COMMAND + "--prefix=${JEMALLOC_PREFIX}" + "--libdir=${JEMALLOC_LIB_DIR}" + "--with-jemalloc-prefix=je_arrow_" + "--with-private-namespace=je_arrow_private_" + "--without-export" + "--disable-shared" + # Don't override operator new() + "--disable-cxx" + "--disable-libdl" + # See https://github.com/jemalloc/jemalloc/issues/1237 + "--disable-initial-exec-tls" + ${EP_LOG_OPTIONS}) + set(JEMALLOC_BUILD_COMMAND ${MAKE} ${MAKE_BUILD_ARGS}) + if(CMAKE_OSX_SYSROOT) + list(APPEND JEMALLOC_BUILD_COMMAND "SDKROOT=${CMAKE_OSX_SYSROOT}") + endif() + externalproject_add(jemalloc_ep + URL ${JEMALLOC_SOURCE_URL} + URL_HASH "SHA256=${ARROW_JEMALLOC_BUILD_SHA256_CHECKSUM}" + PATCH_COMMAND touch doc/jemalloc.3 doc/jemalloc.html + # The prefix "je_arrow_" must be kept in sync with the value in memory_pool.cc + CONFIGURE_COMMAND ${JEMALLOC_CONFIGURE_COMMAND} + BUILD_IN_SOURCE 1 + BUILD_COMMAND ${JEMALLOC_BUILD_COMMAND} + BUILD_BYPRODUCTS "${JEMALLOC_STATIC_LIB}" + INSTALL_COMMAND ${MAKE} -j1 install) + + # Don't use the include directory directly so that we can point to a path + # that is unique to our codebase. + include_directories(SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/jemalloc_ep-prefix/src/") + # The include directory must exist before it is referenced by a target. + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/jemalloc_ep-prefix/src/") + add_library(jemalloc::jemalloc STATIC IMPORTED) + set_target_properties(jemalloc::jemalloc + PROPERTIES INTERFACE_LINK_LIBRARIES Threads::Threads + IMPORTED_LOCATION "${JEMALLOC_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES + "${CMAKE_CURRENT_BINARY_DIR}/jemalloc_ep-prefix/src") + add_dependencies(jemalloc::jemalloc jemalloc_ep) + + list(APPEND ARROW_BUNDLED_STATIC_LIBS jemalloc::jemalloc) +endif() + +# ---------------------------------------------------------------------- +# mimalloc - Cross-platform high-performance allocator, from Microsoft + +if(ARROW_MIMALLOC) + message(STATUS "Building (vendored) mimalloc from source") + # We only use a vendored mimalloc as we want to control its build options. + + set(MIMALLOC_LIB_BASE_NAME "mimalloc") + if(WIN32) + set(MIMALLOC_LIB_BASE_NAME "${MIMALLOC_LIB_BASE_NAME}-static") + endif() + if(${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG") + set(MIMALLOC_LIB_BASE_NAME "${MIMALLOC_LIB_BASE_NAME}-${LOWERCASE_BUILD_TYPE}") + endif() + + set(MIMALLOC_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/mimalloc_ep/src/mimalloc_ep") + set(MIMALLOC_INCLUDE_DIR "${MIMALLOC_PREFIX}/include/mimalloc-1.7") + set(MIMALLOC_STATIC_LIB + "${MIMALLOC_PREFIX}/lib/mimalloc-1.7/${CMAKE_STATIC_LIBRARY_PREFIX}${MIMALLOC_LIB_BASE_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + + set(MIMALLOC_CMAKE_ARGS + ${EP_COMMON_CMAKE_ARGS} + "-DCMAKE_INSTALL_PREFIX=${MIMALLOC_PREFIX}" + -DMI_OVERRIDE=OFF + -DMI_LOCAL_DYNAMIC_TLS=ON + -DMI_BUILD_OBJECT=OFF + -DMI_BUILD_SHARED=OFF + -DMI_BUILD_TESTS=OFF) + + externalproject_add(mimalloc_ep + URL ${MIMALLOC_SOURCE_URL} + URL_HASH "SHA256=${ARROW_MIMALLOC_BUILD_SHA256_CHECKSUM}" + CMAKE_ARGS ${MIMALLOC_CMAKE_ARGS} + BUILD_BYPRODUCTS "${MIMALLOC_STATIC_LIB}") + + include_directories(SYSTEM ${MIMALLOC_INCLUDE_DIR}) + file(MAKE_DIRECTORY ${MIMALLOC_INCLUDE_DIR}) + + add_library(mimalloc::mimalloc STATIC IMPORTED) + set_target_properties(mimalloc::mimalloc + PROPERTIES INTERFACE_LINK_LIBRARIES Threads::Threads + IMPORTED_LOCATION "${MIMALLOC_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES + "${MIMALLOC_INCLUDE_DIR}") + add_dependencies(mimalloc::mimalloc mimalloc_ep) + add_dependencies(toolchain mimalloc_ep) + + list(APPEND ARROW_BUNDLED_STATIC_LIBS mimalloc::mimalloc) +endif() + +# ---------------------------------------------------------------------- +# Google gtest + +macro(build_gtest) + message(STATUS "Building gtest from source") + set(GTEST_VENDORED TRUE) + set(GTEST_CMAKE_CXX_FLAGS ${EP_CXX_FLAGS}) + + if(CMAKE_BUILD_TYPE MATCHES DEBUG) + set(CMAKE_GTEST_DEBUG_EXTENSION "d") + else() + set(CMAKE_GTEST_DEBUG_EXTENSION "") + endif() + + if(APPLE) + set(GTEST_CMAKE_CXX_FLAGS ${GTEST_CMAKE_CXX_FLAGS} -DGTEST_USE_OWN_TR1_TUPLE=1 + -Wno-unused-value -Wno-ignored-attributes) + endif() + + if(MSVC) + set(GTEST_CMAKE_CXX_FLAGS "${GTEST_CMAKE_CXX_FLAGS} -DGTEST_CREATE_SHARED_LIBRARY=1") + endif() + + set(GTEST_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/googletest_ep-prefix") + set(GTEST_INCLUDE_DIR "${GTEST_PREFIX}/include") + + set(_GTEST_LIBRARY_DIR "${GTEST_PREFIX}/lib") + + if(MSVC) + set(_GTEST_IMPORTED_TYPE IMPORTED_IMPLIB) + set(_GTEST_LIBRARY_SUFFIX + "${CMAKE_GTEST_DEBUG_EXTENSION}${CMAKE_IMPORT_LIBRARY_SUFFIX}") + else() + set(_GTEST_IMPORTED_TYPE IMPORTED_LOCATION) + set(_GTEST_LIBRARY_SUFFIX + "${CMAKE_GTEST_DEBUG_EXTENSION}${CMAKE_SHARED_LIBRARY_SUFFIX}") + + endif() + + set(GTEST_SHARED_LIB + "${_GTEST_LIBRARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}gtest${_GTEST_LIBRARY_SUFFIX}") + set(GMOCK_SHARED_LIB + "${_GTEST_LIBRARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}gmock${_GTEST_LIBRARY_SUFFIX}") + set(GTEST_MAIN_SHARED_LIB + "${_GTEST_LIBRARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}gtest_main${_GTEST_LIBRARY_SUFFIX}" + ) + set(GTEST_INSTALL_NAME_DIR "$<INSTALL_PREFIX$<ANGLE-R>/lib") + # Fix syntax highlighting mess introduced by unclosed bracket above + set(dummy ">") + + set(GTEST_CMAKE_ARGS + ${EP_COMMON_TOOLCHAIN} + -DBUILD_SHARED_LIBS=ON + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_CXX_FLAGS=${GTEST_CMAKE_CXX_FLAGS} + -DCMAKE_CXX_FLAGS_${UPPERCASE_BUILD_TYPE}=${GTEST_CMAKE_CXX_FLAGS} + -DCMAKE_INSTALL_LIBDIR=lib + -DCMAKE_INSTALL_NAME_DIR=${GTEST_INSTALL_NAME_DIR} + -DCMAKE_INSTALL_PREFIX=${GTEST_PREFIX} + -DCMAKE_MACOSX_RPATH=OFF) + set(GMOCK_INCLUDE_DIR "${GTEST_PREFIX}/include") + + add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=1) + + if(MSVC AND NOT ARROW_USE_STATIC_CRT) + set(GTEST_CMAKE_ARGS ${GTEST_CMAKE_ARGS} -Dgtest_force_shared_crt=ON) + endif() + + externalproject_add(googletest_ep + URL ${GTEST_SOURCE_URL} + URL_HASH "SHA256=${ARROW_GTEST_BUILD_SHA256_CHECKSUM}" + BUILD_BYPRODUCTS ${GTEST_SHARED_LIB} ${GTEST_MAIN_SHARED_LIB} + ${GMOCK_SHARED_LIB} + CMAKE_ARGS ${GTEST_CMAKE_ARGS} ${EP_LOG_OPTIONS}) + if(WIN32) + # Copy the built shared libraries to the same directory as our + # test programs because Windows doesn't provided rpath (run-time + # search path) feature. We need to put these shared libraries to + # the same directory as our test programs or add + # _GTEST_LIBRARY_DIR to PATH when we run our test programs. We + # choose the former because the latter may be forgotten. + set(_GTEST_RUNTIME_DIR "${GTEST_PREFIX}/bin") + set(_GTEST_RUNTIME_SUFFIX + "${CMAKE_GTEST_DEBUG_EXTENSION}${CMAKE_SHARED_LIBRARY_SUFFIX}") + set(_GTEST_RUNTIME_LIB + "${_GTEST_RUNTIME_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}gtest${_GTEST_RUNTIME_SUFFIX}" + ) + set(_GMOCK_RUNTIME_LIB + "${_GTEST_RUNTIME_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}gmock${_GTEST_RUNTIME_SUFFIX}" + ) + set(_GTEST_MAIN_RUNTIME_LIB + "${_GTEST_RUNTIME_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}gtest_main${_GTEST_RUNTIME_SUFFIX}" + ) + if(CMAKE_VERSION VERSION_LESS 3.9) + message(FATAL_ERROR "Building GoogleTest from source on Windows requires at least CMake 3.9" + ) + endif() + get_property(_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if(_GENERATOR_IS_MULTI_CONFIG) + set(_GTEST_RUNTIME_OUTPUT_DIR "${BUILD_OUTPUT_ROOT_DIRECTORY}/${CMAKE_BUILD_TYPE}") + else() + set(_GTEST_RUNTIME_OUTPUT_DIR ${BUILD_OUTPUT_ROOT_DIRECTORY}) + endif() + externalproject_add_step(googletest_ep copy + COMMAND ${CMAKE_COMMAND} -E make_directory + ${_GTEST_RUNTIME_OUTPUT_DIR} + COMMAND ${CMAKE_COMMAND} -E copy ${_GTEST_RUNTIME_LIB} + ${_GTEST_RUNTIME_OUTPUT_DIR} + COMMAND ${CMAKE_COMMAND} -E copy ${_GMOCK_RUNTIME_LIB} + ${_GTEST_RUNTIME_OUTPUT_DIR} + COMMAND ${CMAKE_COMMAND} -E copy ${_GTEST_MAIN_RUNTIME_LIB} + ${_GTEST_RUNTIME_OUTPUT_DIR} + DEPENDEES install) + endif() + + # The include directory must exist before it is referenced by a target. + file(MAKE_DIRECTORY "${GTEST_INCLUDE_DIR}") + + add_library(GTest::gtest SHARED IMPORTED) + set_target_properties(GTest::gtest + PROPERTIES ${_GTEST_IMPORTED_TYPE} "${GTEST_SHARED_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIR}") + + add_library(GTest::gtest_main SHARED IMPORTED) + set_target_properties(GTest::gtest_main + PROPERTIES ${_GTEST_IMPORTED_TYPE} "${GTEST_MAIN_SHARED_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIR}") + + add_library(GTest::gmock SHARED IMPORTED) + set_target_properties(GTest::gmock + PROPERTIES ${_GTEST_IMPORTED_TYPE} "${GMOCK_SHARED_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIR}") + add_dependencies(toolchain-tests googletest_ep) + add_dependencies(GTest::gtest googletest_ep) + add_dependencies(GTest::gtest_main googletest_ep) + add_dependencies(GTest::gmock googletest_ep) +endmacro() + +if(ARROW_TESTING) + resolve_dependency(GTest + REQUIRED_VERSION + 1.10.0 + USE_CONFIG + TRUE) + + if(NOT GTEST_VENDORED) + # TODO(wesm): This logic does not work correctly with the MSVC static libraries + # built for the shared crt + + # set(CMAKE_REQUIRED_LIBRARIES GTest::GTest GTest::Main GTest::GMock) + # CHECK_CXX_SOURCE_COMPILES(" + # #include <gmock/gmock.h> + # #include <gtest/gtest.h> + + # class A { + # public: + # int run() const { return 1; } + # }; + + # class B : public A { + # public: + # MOCK_CONST_METHOD0(run, int()); + # }; + + # TEST(Base, Test) { + # B b; + # }" GTEST_COMPILES_WITHOUT_MACRO) + # if (NOT GTEST_COMPILES_WITHOUT_MACRO) + # message(STATUS "Setting GTEST_LINKED_AS_SHARED_LIBRARY=1 on GTest::GTest") + # add_compile_definitions("GTEST_LINKED_AS_SHARED_LIBRARY=1") + # endif() + # set(CMAKE_REQUIRED_LIBRARIES) + endif() + + get_target_property(GTEST_INCLUDE_DIR GTest::gtest INTERFACE_INCLUDE_DIRECTORIES) + # TODO: Don't use global includes but rather target_include_directories + include_directories(SYSTEM ${GTEST_INCLUDE_DIR}) +endif() + +macro(build_benchmark) + message(STATUS "Building benchmark from source") + if(CMAKE_VERSION VERSION_LESS 3.6) + message(FATAL_ERROR "Building gbenchmark from source requires at least CMake 3.6") + endif() + + if(NOT MSVC) + set(GBENCHMARK_CMAKE_CXX_FLAGS "${EP_CXX_FLAGS} -std=c++11") + endif() + + if(APPLE AND (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID + STREQUAL "Clang")) + set(GBENCHMARK_CMAKE_CXX_FLAGS "${GBENCHMARK_CMAKE_CXX_FLAGS} -stdlib=libc++") + endif() + + set(GBENCHMARK_PREFIX + "${CMAKE_CURRENT_BINARY_DIR}/gbenchmark_ep/src/gbenchmark_ep-install") + set(GBENCHMARK_INCLUDE_DIR "${GBENCHMARK_PREFIX}/include") + set(GBENCHMARK_STATIC_LIB + "${GBENCHMARK_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}benchmark${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + set(GBENCHMARK_MAIN_STATIC_LIB + "${GBENCHMARK_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}benchmark_main${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + set(GBENCHMARK_CMAKE_ARGS + ${EP_COMMON_CMAKE_ARGS} + "-DCMAKE_INSTALL_PREFIX=${GBENCHMARK_PREFIX}" + -DCMAKE_INSTALL_LIBDIR=lib + -DBENCHMARK_ENABLE_TESTING=OFF + -DCMAKE_CXX_FLAGS=${GBENCHMARK_CMAKE_CXX_FLAGS}) + if(APPLE) + set(GBENCHMARK_CMAKE_ARGS ${GBENCHMARK_CMAKE_ARGS} "-DBENCHMARK_USE_LIBCXX=ON") + endif() + + externalproject_add(gbenchmark_ep + URL ${GBENCHMARK_SOURCE_URL} + URL_HASH "SHA256=${ARROW_GBENCHMARK_BUILD_SHA256_CHECKSUM}" + BUILD_BYPRODUCTS "${GBENCHMARK_STATIC_LIB}" + "${GBENCHMARK_MAIN_STATIC_LIB}" + CMAKE_ARGS ${GBENCHMARK_CMAKE_ARGS} ${EP_LOG_OPTIONS}) + + # The include directory must exist before it is referenced by a target. + file(MAKE_DIRECTORY "${GBENCHMARK_INCLUDE_DIR}") + + add_library(benchmark::benchmark STATIC IMPORTED) + set_target_properties(benchmark::benchmark + PROPERTIES IMPORTED_LOCATION "${GBENCHMARK_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES + "${GBENCHMARK_INCLUDE_DIR}") + + add_library(benchmark::benchmark_main STATIC IMPORTED) + set_target_properties(benchmark::benchmark_main + PROPERTIES IMPORTED_LOCATION "${GBENCHMARK_MAIN_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES + "${GBENCHMARK_INCLUDE_DIR}") + + add_dependencies(toolchain-benchmarks gbenchmark_ep) + add_dependencies(benchmark::benchmark gbenchmark_ep) + add_dependencies(benchmark::benchmark_main gbenchmark_ep) +endmacro() + +if(ARROW_BUILD_BENCHMARKS) + # ArgsProduct() is available since 1.5.2 + set(BENCHMARK_REQUIRED_VERSION 1.5.2) + resolve_dependency(benchmark + REQUIRED_VERSION + ${BENCHMARK_REQUIRED_VERSION} + IS_RUNTIME_DEPENDENCY + FALSE) + # TODO: Don't use global includes but rather target_include_directories + get_target_property(BENCHMARK_INCLUDE_DIR benchmark::benchmark + INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM ${BENCHMARK_INCLUDE_DIR}) +endif() + +macro(build_rapidjson) + message(STATUS "Building RapidJSON from source") + set(RAPIDJSON_PREFIX + "${CMAKE_CURRENT_BINARY_DIR}/rapidjson_ep/src/rapidjson_ep-install") + set(RAPIDJSON_CMAKE_ARGS + ${EP_COMMON_CMAKE_ARGS} + -DRAPIDJSON_BUILD_DOC=OFF + -DRAPIDJSON_BUILD_EXAMPLES=OFF + -DRAPIDJSON_BUILD_TESTS=OFF + "-DCMAKE_INSTALL_PREFIX=${RAPIDJSON_PREFIX}") + + externalproject_add(rapidjson_ep + ${EP_LOG_OPTIONS} + PREFIX "${CMAKE_BINARY_DIR}" + URL ${RAPIDJSON_SOURCE_URL} + URL_HASH "SHA256=${ARROW_RAPIDJSON_BUILD_SHA256_CHECKSUM}" + CMAKE_ARGS ${RAPIDJSON_CMAKE_ARGS}) + + set(RAPIDJSON_INCLUDE_DIR "${RAPIDJSON_PREFIX}/include") + + add_dependencies(toolchain rapidjson_ep) + add_dependencies(toolchain-tests rapidjson_ep) + add_dependencies(rapidjson rapidjson_ep) + + set(RAPIDJSON_VENDORED TRUE) +endmacro() + +if(ARROW_WITH_RAPIDJSON) + set(ARROW_RAPIDJSON_REQUIRED_VERSION "1.1.0") + resolve_dependency(RapidJSON + HAVE_ALT + TRUE + REQUIRED_VERSION + ${ARROW_RAPIDJSON_REQUIRED_VERSION} + IS_RUNTIME_DEPENDENCY + FALSE) + + if(RapidJSON_INCLUDE_DIR) + set(RAPIDJSON_INCLUDE_DIR "${RapidJSON_INCLUDE_DIR}") + endif() + + # TODO: Don't use global includes but rather target_include_directories + include_directories(SYSTEM ${RAPIDJSON_INCLUDE_DIR}) +endif() + +macro(build_xsimd) + message(STATUS "Building xsimd from source") + set(XSIMD_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/xsimd_ep/src/xsimd_ep-install") + set(XSIMD_CMAKE_ARGS ${EP_COMMON_CMAKE_ARGS} "-DCMAKE_INSTALL_PREFIX=${XSIMD_PREFIX}") + + externalproject_add(xsimd_ep + ${EP_LOG_OPTIONS} + PREFIX "${CMAKE_BINARY_DIR}" + URL ${XSIMD_SOURCE_URL} + URL_HASH "SHA256=${ARROW_XSIMD_BUILD_SHA256_CHECKSUM}" + CMAKE_ARGS ${XSIMD_CMAKE_ARGS}) + + set(XSIMD_INCLUDE_DIR "${XSIMD_PREFIX}/include") + + add_dependencies(toolchain xsimd_ep) + add_dependencies(toolchain-tests xsimd_ep) + + set(XSIMD_VENDORED TRUE) +endmacro() + +if((NOT ARROW_SIMD_LEVEL STREQUAL "NONE") OR (NOT ARROW_RUNTIME_SIMD_LEVEL STREQUAL "NONE" + )) + set(xsimd_SOURCE "BUNDLED") + resolve_dependency(xsimd) + # TODO: Don't use global includes but rather target_include_directories + include_directories(SYSTEM ${XSIMD_INCLUDE_DIR}) +endif() + +macro(build_zlib) + message(STATUS "Building ZLIB from source") + set(ZLIB_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/zlib_ep/src/zlib_ep-install") + if(MSVC) + if(${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG") + set(ZLIB_STATIC_LIB_NAME zlibstaticd.lib) + else() + set(ZLIB_STATIC_LIB_NAME zlibstatic.lib) + endif() + else() + set(ZLIB_STATIC_LIB_NAME libz.a) + endif() + set(ZLIB_STATIC_LIB "${ZLIB_PREFIX}/lib/${ZLIB_STATIC_LIB_NAME}") + set(ZLIB_CMAKE_ARGS ${EP_COMMON_CMAKE_ARGS} "-DCMAKE_INSTALL_PREFIX=${ZLIB_PREFIX}" + -DBUILD_SHARED_LIBS=OFF) + + externalproject_add(zlib_ep + URL ${ZLIB_SOURCE_URL} ${EP_LOG_OPTIONS} + URL_HASH "SHA256=${ARROW_ZLIB_BUILD_SHA256_CHECKSUM}" + BUILD_BYPRODUCTS "${ZLIB_STATIC_LIB}" + CMAKE_ARGS ${ZLIB_CMAKE_ARGS}) + + file(MAKE_DIRECTORY "${ZLIB_PREFIX}/include") + + add_library(ZLIB::ZLIB STATIC IMPORTED) + set(ZLIB_LIBRARIES ${ZLIB_STATIC_LIB}) + set(ZLIB_INCLUDE_DIRS "${ZLIB_PREFIX}/include") + set_target_properties(ZLIB::ZLIB + PROPERTIES IMPORTED_LOCATION ${ZLIB_LIBRARIES} + INTERFACE_INCLUDE_DIRECTORIES ${ZLIB_INCLUDE_DIRS}) + + add_dependencies(toolchain zlib_ep) + add_dependencies(ZLIB::ZLIB zlib_ep) + + list(APPEND ARROW_BUNDLED_STATIC_LIBS ZLIB::ZLIB) +endmacro() + +if(ARROW_WITH_ZLIB) + resolve_dependency(ZLIB PC_PACKAGE_NAMES zlib) + + # TODO: Don't use global includes but rather target_include_directories + get_target_property(ZLIB_INCLUDE_DIR ZLIB::ZLIB INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM ${ZLIB_INCLUDE_DIR}) +endif() + +macro(build_lz4) + message(STATUS "Building lz4 from source") + set(LZ4_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/lz4_ep-prefix/src/lz4_ep") + set(LZ4_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/lz4_ep-prefix") + + if(MSVC) + if(ARROW_USE_STATIC_CRT) + if(${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG") + set(LZ4_RUNTIME_LIBRARY_LINKAGE "/p:RuntimeLibrary=MultiThreadedDebug") + else() + set(LZ4_RUNTIME_LIBRARY_LINKAGE "/p:RuntimeLibrary=MultiThreaded") + endif() + endif() + set(LZ4_STATIC_LIB + "${LZ4_BUILD_DIR}/build/VS2010/bin/x64_${CMAKE_BUILD_TYPE}/liblz4_static.lib") + set(LZ4_BUILD_COMMAND + BUILD_COMMAND msbuild.exe /m /p:Configuration=${CMAKE_BUILD_TYPE} /p:Platform=x64 + /p:PlatformToolset=v140 ${LZ4_RUNTIME_LIBRARY_LINKAGE} /t:Build + ${LZ4_BUILD_DIR}/build/VS2010/lz4.sln) + else() + set(LZ4_STATIC_LIB "${LZ4_BUILD_DIR}/lib/liblz4.a") + # Must explicitly invoke sh on MinGW + set(LZ4_BUILD_COMMAND + BUILD_COMMAND sh "${CMAKE_SOURCE_DIR}/build-support/build-lz4-lib.sh" + "AR=${CMAKE_AR}" "OS=${CMAKE_SYSTEM_NAME}") + endif() + + # We need to copy the header in lib to directory outside of the build + externalproject_add(lz4_ep + URL ${LZ4_SOURCE_URL} ${EP_LOG_OPTIONS} + URL_HASH "SHA256=${ARROW_LZ4_BUILD_SHA256_CHECKSUM}" + UPDATE_COMMAND ${CMAKE_COMMAND} -E copy_directory + "${LZ4_BUILD_DIR}/lib" "${LZ4_PREFIX}/include" + ${LZ4_PATCH_COMMAND} + CONFIGURE_COMMAND "" + INSTALL_COMMAND "" + BINARY_DIR ${LZ4_BUILD_DIR} + BUILD_BYPRODUCTS ${LZ4_STATIC_LIB} ${LZ4_BUILD_COMMAND}) + + file(MAKE_DIRECTORY "${LZ4_PREFIX}/include") + add_library(LZ4::lz4 STATIC IMPORTED) + set_target_properties(LZ4::lz4 + PROPERTIES IMPORTED_LOCATION "${LZ4_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${LZ4_PREFIX}/include") + add_dependencies(toolchain lz4_ep) + add_dependencies(LZ4::lz4 lz4_ep) + + list(APPEND ARROW_BUNDLED_STATIC_LIBS LZ4::lz4) +endmacro() + +if(ARROW_WITH_LZ4) + resolve_dependency(Lz4 PC_PACKAGE_NAMES liblz4) + + # TODO: Don't use global includes but rather target_include_directories + get_target_property(LZ4_INCLUDE_DIR LZ4::lz4 INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM ${LZ4_INCLUDE_DIR}) +endif() + +macro(build_zstd) + message(STATUS "Building zstd from source") + set(ZSTD_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/zstd_ep-install") + + set(ZSTD_CMAKE_ARGS + ${EP_COMMON_TOOLCHAIN} + "-DCMAKE_INSTALL_PREFIX=${ZSTD_PREFIX}" + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR} + -DZSTD_BUILD_PROGRAMS=off + -DZSTD_BUILD_SHARED=off + -DZSTD_BUILD_STATIC=on + -DZSTD_MULTITHREAD_SUPPORT=off) + + if(MSVC) + set(ZSTD_STATIC_LIB "${ZSTD_PREFIX}/${CMAKE_INSTALL_LIBDIR}/zstd_static.lib") + if(ARROW_USE_STATIC_CRT) + set(ZSTD_CMAKE_ARGS ${ZSTD_CMAKE_ARGS} "-DZSTD_USE_STATIC_RUNTIME=on") + endif() + else() + set(ZSTD_STATIC_LIB "${ZSTD_PREFIX}/${CMAKE_INSTALL_LIBDIR}/libzstd.a") + # Only pass our C flags on Unix as on MSVC it leads to a + # "incompatible command-line options" error + set(ZSTD_CMAKE_ARGS + ${ZSTD_CMAKE_ARGS} + -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} + -DCMAKE_C_FLAGS=${EP_C_FLAGS} + -DCMAKE_CXX_FLAGS=${EP_CXX_FLAGS}) + endif() + + if(CMAKE_VERSION VERSION_LESS 3.7) + message(FATAL_ERROR "Building zstd using ExternalProject requires at least CMake 3.7") + endif() + + externalproject_add(zstd_ep + ${EP_LOG_OPTIONS} + CMAKE_ARGS ${ZSTD_CMAKE_ARGS} + SOURCE_SUBDIR "build/cmake" + INSTALL_DIR ${ZSTD_PREFIX} + URL ${ZSTD_SOURCE_URL} + URL_HASH "SHA256=${ARROW_ZSTD_BUILD_SHA256_CHECKSUM}" + BUILD_BYPRODUCTS "${ZSTD_STATIC_LIB}") + + file(MAKE_DIRECTORY "${ZSTD_PREFIX}/include") + + add_library(zstd::libzstd STATIC IMPORTED) + set_target_properties(zstd::libzstd + PROPERTIES IMPORTED_LOCATION "${ZSTD_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${ZSTD_PREFIX}/include") + + add_dependencies(toolchain zstd_ep) + add_dependencies(zstd::libzstd zstd_ep) + + list(APPEND ARROW_BUNDLED_STATIC_LIBS zstd::libzstd) +endmacro() + +if(ARROW_WITH_ZSTD) + # ARROW-13384: ZSTD_minCLevel was added in v1.4.0, required by ARROW-13091 + resolve_dependency(zstd + PC_PACKAGE_NAMES + libzstd + REQUIRED_VERSION + 1.4.0) + + if(TARGET zstd::libzstd) + set(ARROW_ZSTD_LIBZSTD zstd::libzstd) + else() + # "SYSTEM" source will prioritize cmake config, which exports + # zstd::libzstd_{static,shared} + if(ARROW_ZSTD_USE_SHARED) + if(TARGET zstd::libzstd_shared) + set(ARROW_ZSTD_LIBZSTD zstd::libzstd_shared) + endif() + else() + if(TARGET zstd::libzstd_static) + set(ARROW_ZSTD_LIBZSTD zstd::libzstd_static) + endif() + endif() + endif() + + # TODO: Don't use global includes but rather target_include_directories + get_target_property(ZSTD_INCLUDE_DIR ${ARROW_ZSTD_LIBZSTD} + INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM ${ZSTD_INCLUDE_DIR}) +endif() + +# ---------------------------------------------------------------------- +# RE2 (required for Gandiva) + +macro(build_re2) + message(STATUS "Building RE2 from source") + set(RE2_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/re2_ep-install") + set(RE2_STATIC_LIB + "${RE2_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}re2${CMAKE_STATIC_LIBRARY_SUFFIX}") + + set(RE2_CMAKE_ARGS ${EP_COMMON_CMAKE_ARGS} "-DCMAKE_INSTALL_PREFIX=${RE2_PREFIX}" + -DCMAKE_INSTALL_LIBDIR=lib) + + externalproject_add(re2_ep + ${EP_LOG_OPTIONS} + INSTALL_DIR ${RE2_PREFIX} + URL ${RE2_SOURCE_URL} + URL_HASH "SHA256=${ARROW_RE2_BUILD_SHA256_CHECKSUM}" + CMAKE_ARGS ${RE2_CMAKE_ARGS} + BUILD_BYPRODUCTS "${RE2_STATIC_LIB}") + + file(MAKE_DIRECTORY "${RE2_PREFIX}/include") + add_library(re2::re2 STATIC IMPORTED) + set_target_properties(re2::re2 + PROPERTIES IMPORTED_LOCATION "${RE2_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${RE2_PREFIX}/include") + + add_dependencies(toolchain re2_ep) + add_dependencies(re2::re2 re2_ep) + set(RE2_VENDORED TRUE) + # Set values so that FindRE2 finds this too + set(RE2_LIB ${RE2_STATIC_LIB}) + set(RE2_INCLUDE_DIR "${RE2_PREFIX}/include") + + list(APPEND ARROW_BUNDLED_STATIC_LIBS re2::re2) +endmacro() + +if(ARROW_WITH_RE2) + # Don't specify "PC_PACKAGE_NAMES re2" here because re2.pc may + # include -std=c++11. It's not compatible with C source and C++ + # source not uses C++ 11. + resolve_dependency(re2 HAVE_ALT TRUE) + if(${re2_SOURCE} STREQUAL "SYSTEM") + get_target_property(RE2_LIB re2::re2 IMPORTED_LOCATION) + string(APPEND ARROW_PC_LIBS_PRIVATE " ${RE2_LIB}") + endif() + add_definitions(-DARROW_WITH_RE2) + + # TODO: Don't use global includes but rather target_include_directories + get_target_property(RE2_INCLUDE_DIR re2::re2 INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM ${RE2_INCLUDE_DIR}) +endif() + +macro(build_bzip2) + message(STATUS "Building BZip2 from source") + set(BZIP2_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/bzip2_ep-install") + set(BZIP2_STATIC_LIB + "${BZIP2_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}bz2${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + + set(BZIP2_EXTRA_ARGS "CC=${CMAKE_C_COMPILER}" "CFLAGS=${EP_C_FLAGS}") + + if(CMAKE_OSX_SYSROOT) + list(APPEND BZIP2_EXTRA_ARGS "SDKROOT=${CMAKE_OSX_SYSROOT}") + endif() + + if(CMAKE_AR) + list(APPEND BZIP2_EXTRA_ARGS AR=${CMAKE_AR}) + endif() + + if(CMAKE_RANLIB) + list(APPEND BZIP2_EXTRA_ARGS RANLIB=${CMAKE_RANLIB}) + endif() + + externalproject_add(bzip2_ep + ${EP_LOG_OPTIONS} + CONFIGURE_COMMAND "" + BUILD_IN_SOURCE 1 + BUILD_COMMAND ${MAKE} libbz2.a ${MAKE_BUILD_ARGS} + ${BZIP2_EXTRA_ARGS} + INSTALL_COMMAND ${MAKE} install PREFIX=${BZIP2_PREFIX} + ${BZIP2_EXTRA_ARGS} + INSTALL_DIR ${BZIP2_PREFIX} + URL ${ARROW_BZIP2_SOURCE_URL} + URL_HASH "SHA256=${ARROW_BZIP2_BUILD_SHA256_CHECKSUM}" + BUILD_BYPRODUCTS "${BZIP2_STATIC_LIB}") + + file(MAKE_DIRECTORY "${BZIP2_PREFIX}/include") + add_library(BZip2::BZip2 STATIC IMPORTED) + set_target_properties(BZip2::BZip2 + PROPERTIES IMPORTED_LOCATION "${BZIP2_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES + "${BZIP2_PREFIX}/include") + set(BZIP2_INCLUDE_DIR "${BZIP2_PREFIX}/include") + + add_dependencies(toolchain bzip2_ep) + add_dependencies(BZip2::BZip2 bzip2_ep) + + list(APPEND ARROW_BUNDLED_STATIC_LIBS BZip2::BZip2) +endmacro() + +if(ARROW_WITH_BZ2) + resolve_dependency(BZip2) + if(${BZip2_SOURCE} STREQUAL "SYSTEM") + string(APPEND ARROW_PC_LIBS_PRIVATE " ${BZIP2_LIBRARIES}") + endif() + + if(NOT TARGET BZip2::BZip2) + add_library(BZip2::BZip2 UNKNOWN IMPORTED) + set_target_properties(BZip2::BZip2 + PROPERTIES IMPORTED_LOCATION "${BZIP2_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${BZIP2_INCLUDE_DIR}") + endif() + include_directories(SYSTEM "${BZIP2_INCLUDE_DIR}") +endif() + +macro(build_utf8proc) + message(STATUS "Building utf8proc from source") + set(UTF8PROC_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/utf8proc_ep-install") + if(MSVC) + set(UTF8PROC_STATIC_LIB "${UTF8PROC_PREFIX}/lib/utf8proc_static.lib") + else() + set(UTF8PROC_STATIC_LIB + "${UTF8PROC_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}utf8proc${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + endif() + + set(UTF8PROC_CMAKE_ARGS + ${EP_COMMON_TOOLCHAIN} + "-DCMAKE_INSTALL_PREFIX=${UTF8PROC_PREFIX}" + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_INSTALL_LIBDIR=lib + -DBUILD_SHARED_LIBS=OFF) + + externalproject_add(utf8proc_ep + ${EP_LOG_OPTIONS} + CMAKE_ARGS ${UTF8PROC_CMAKE_ARGS} + INSTALL_DIR ${UTF8PROC_PREFIX} + URL ${ARROW_UTF8PROC_SOURCE_URL} + URL_HASH "SHA256=${ARROW_UTF8PROC_BUILD_SHA256_CHECKSUM}" + BUILD_BYPRODUCTS "${UTF8PROC_STATIC_LIB}") + + file(MAKE_DIRECTORY "${UTF8PROC_PREFIX}/include") + add_library(utf8proc::utf8proc STATIC IMPORTED) + set_target_properties(utf8proc::utf8proc + PROPERTIES IMPORTED_LOCATION "${UTF8PROC_STATIC_LIB}" + INTERFACE_COMPILER_DEFINITIONS "UTF8PROC_STATIC" + INTERFACE_INCLUDE_DIRECTORIES + "${UTF8PROC_PREFIX}/include") + + add_dependencies(toolchain utf8proc_ep) + add_dependencies(utf8proc::utf8proc utf8proc_ep) + + list(APPEND ARROW_BUNDLED_STATIC_LIBS utf8proc::utf8proc) +endmacro() + +if(ARROW_WITH_UTF8PROC) + resolve_dependency(utf8proc + REQUIRED_VERSION + "2.2.0" + PC_PACKAGE_NAMES + libutf8proc) + + add_definitions(-DARROW_WITH_UTF8PROC) + + # TODO: Don't use global definitions but rather + # target_compile_definitions or target_link_libraries + get_target_property(UTF8PROC_COMPILER_DEFINITIONS utf8proc::utf8proc + INTERFACE_COMPILER_DEFINITIONS) + if(UTF8PROC_COMPILER_DEFINITIONS) + add_definitions(-D${UTF8PROC_COMPILER_DEFINITIONS}) + endif() + + # TODO: Don't use global includes but rather + # target_include_directories or target_link_libraries + get_target_property(UTF8PROC_INCLUDE_DIR utf8proc::utf8proc + INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM ${UTF8PROC_INCLUDE_DIR}) +endif() + +macro(build_cares) + message(STATUS "Building c-ares from source") + set(CARES_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/cares_ep-install") + set(CARES_INCLUDE_DIR "${CARES_PREFIX}/include") + + # If you set -DCARES_SHARED=ON then the build system names the library + # libcares_static.a + set(CARES_STATIC_LIB + "${CARES_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}cares${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + + set(CARES_CMAKE_ARGS + "${EP_COMMON_CMAKE_ARGS}" + -DCARES_STATIC=ON + -DCARES_SHARED=OFF + -DCMAKE_INSTALL_LIBDIR=lib + "-DCMAKE_INSTALL_PREFIX=${CARES_PREFIX}") + + externalproject_add(cares_ep + ${EP_LOG_OPTIONS} + URL ${CARES_SOURCE_URL} + URL_HASH "SHA256=${ARROW_CARES_BUILD_SHA256_CHECKSUM}" + CMAKE_ARGS ${CARES_CMAKE_ARGS} + BUILD_BYPRODUCTS "${CARES_STATIC_LIB}") + + file(MAKE_DIRECTORY ${CARES_INCLUDE_DIR}) + + add_dependencies(toolchain cares_ep) + add_library(c-ares::cares STATIC IMPORTED) + set_target_properties(c-ares::cares + PROPERTIES IMPORTED_LOCATION "${CARES_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${CARES_INCLUDE_DIR}") + add_dependencies(c-ares::cares cares_ep) + + if(APPLE) + # libresolv must be linked from c-ares version 1.16.1 + find_library(LIBRESOLV_LIBRARY NAMES resolv libresolv REQUIRED) + set_target_properties(c-ares::cares PROPERTIES INTERFACE_LINK_LIBRARIES + "${LIBRESOLV_LIBRARY}") + endif() + + set(CARES_VENDORED TRUE) + + list(APPEND ARROW_BUNDLED_STATIC_LIBS c-ares::cares) +endmacro() + +# ---------------------------------------------------------------------- +# Dependencies for Arrow Flight RPC + +macro(build_absl_once) + if(NOT TARGET absl_ep) + message(STATUS "Building Abseil-cpp from source") + set(ABSL_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/absl_ep-install") + set(ABSL_INCLUDE_DIR "${ABSL_PREFIX}/include") + set(ABSL_CMAKE_ARGS + "${EP_COMMON_CMAKE_ARGS}" -DABSL_RUN_TESTS=OFF -DCMAKE_INSTALL_LIBDIR=lib + "-DCMAKE_INSTALL_PREFIX=${ABSL_PREFIX}") + set(ABSL_BUILD_BYPRODUCTS) + set(ABSL_LIBRARIES) + + # Abseil produces the following libraries, each is fairly small, but there + # are (as you can see), many of them. We need to add the libraries first, + # and then describe how they depend on each other. The list can be + # refreshed using: + # ls -1 $PREFIX/lib/libabsl_*.a | sed -e 's/.*libabsl_//' -e 's/.a$//' + set(_ABSL_LIBS + bad_any_cast_impl + bad_optional_access + bad_variant_access + base + city + civil_time + cord + debugging_internal + demangle_internal + examine_stack + exponential_biased + failure_signal_handler + flags + flags_commandlineflag + flags_commandlineflag_internal + flags_config + flags_internal + flags_marshalling + flags_parse + flags_private_handle_accessor + flags_program_name + flags_reflection + flags_usage + flags_usage_internal + graphcycles_internal + hash + hashtablez_sampler + int128 + leak_check + leak_check_disable + log_severity + malloc_internal + periodic_sampler + random_distributions + random_internal_distribution_test_util + random_internal_platform + random_internal_pool_urbg + random_internal_randen + random_internal_randen_hwaes + random_internal_randen_hwaes_impl + random_internal_randen_slow + random_internal_seed_material + random_seed_gen_exception + random_seed_sequences + raw_hash_set + raw_logging_internal + scoped_set_env + spinlock_wait + stacktrace + status + statusor + strerror + str_format_internal + strings + strings_internal + symbolize + synchronization + throw_delegate + time + time_zone + wyhash) + # Abseil creates a number of header-only targets, which are needed to resolve dependencies. + # The list can be refreshed using: + # comm -13 <(ls -l $PREFIX/lib/libabsl_*.a | sed -e 's/.*libabsl_//' -e 's/.a$//' | sort -u) \ + # <(ls -1 $PREFIX/lib/pkgconfig/absl_*.pc | sed -e 's/.*absl_//' -e 's/.pc$//' | sort -u) + set(_ABSL_INTERFACE_LIBS + algorithm + algorithm_container + any + atomic_hook + bad_any_cast + base_internal + bind_front + bits + btree + cleanup + cleanup_internal + compare + compressed_tuple + config + container_common + container_memory + core_headers + counting_allocator + debugging + dynamic_annotations + endian + errno_saver + fast_type_id + fixed_array + flags_path_util + flat_hash_map + flat_hash_set + function_ref + hash_function_defaults + hash_policy_traits + hashtable_debug + hashtable_debug_hooks + have_sse + inlined_vector + inlined_vector_internal + kernel_timeout_internal + layout + memory + meta + node_hash_map + node_hash_policy + node_hash_set + numeric + numeric_representation + optional + pretty_function + random_bit_gen_ref + random_internal_distribution_caller + random_internal_fastmath + random_internal_fast_uniform_bits + random_internal_generate_real + random_internal_iostream_state_saver + random_internal_mock_helpers + random_internal_nonsecure_base + random_internal_pcg_engine + random_internal_randen_engine + random_internal_salted_seed_seq + random_internal_traits + random_internal_uniform_helper + random_internal_wide_multiply + random_random + raw_hash_map + span + str_format + type_traits + utility + variant) + + foreach(_ABSL_LIB ${_ABSL_LIBS}) + set(_ABSL_STATIC_LIBRARY + "${ABSL_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}absl_${_ABSL_LIB}${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + add_library(absl::${_ABSL_LIB} STATIC IMPORTED) + set_target_properties(absl::${_ABSL_LIB} + PROPERTIES IMPORTED_LOCATION ${_ABSL_STATIC_LIBRARY} + INTERFACE_INCLUDE_DIRECTORIES + "${ABSL_INCLUDE_DIR}") + list(APPEND ABSL_BUILD_BYPRODUCTS ${_ABSL_STATIC_LIBRARY}) + endforeach() + foreach(_ABSL_LIB ${_ABSL_INTERFACE_LIBS}) + add_library(absl::${_ABSL_LIB} INTERFACE IMPORTED) + set_target_properties(absl::${_ABSL_LIB} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${ABSL_INCLUDE_DIR}") + endforeach() + + # Extracted the dependency information using the Abseil pkg-config files: + # grep Requires $PREFIX/pkgconfig/absl_*.pc | \ + # sed -e 's;.*/absl_;set_property(TARGET absl::;' \ + # -e 's/.pc:Requires:/ PROPERTY INTERFACE_LINK_LIBRARIES /' \ + # -e 's/ = 20210324,//g' \ + # -e 's/ = 20210324//g' \ + # -e 's/absl_/absl::/g' \ + # -e 's/$/)/' | \ + # grep -v 'INTERFACE_LINK_LIBRARIES[ ]*)' + set_property(TARGET absl::algorithm_container + PROPERTY INTERFACE_LINK_LIBRARIES absl::algorithm absl::core_headers + absl::meta) + set_property(TARGET absl::algorithm PROPERTY INTERFACE_LINK_LIBRARIES absl::config) + set_property(TARGET absl::any + PROPERTY INTERFACE_LINK_LIBRARIES + absl::bad_any_cast + absl::config + absl::core_headers + absl::fast_type_id + absl::type_traits + absl::utility) + set_property(TARGET absl::atomic_hook PROPERTY INTERFACE_LINK_LIBRARIES absl::config + absl::core_headers) + set_property(TARGET absl::bad_any_cast_impl + PROPERTY INTERFACE_LINK_LIBRARIES absl::config + absl::raw_logging_internal) + set_property(TARGET absl::bad_any_cast PROPERTY INTERFACE_LINK_LIBRARIES + absl::bad_any_cast_impl absl::config) + set_property(TARGET absl::bad_optional_access + PROPERTY INTERFACE_LINK_LIBRARIES absl::config + absl::raw_logging_internal) + set_property(TARGET absl::bad_variant_access + PROPERTY INTERFACE_LINK_LIBRARIES absl::config + absl::raw_logging_internal) + set_property(TARGET absl::base_internal PROPERTY INTERFACE_LINK_LIBRARIES + absl::config absl::type_traits) + set_property(TARGET absl::base + PROPERTY INTERFACE_LINK_LIBRARIES + absl::atomic_hook + absl::base_internal + absl::config + absl::core_headers + absl::dynamic_annotations + absl::log_severity + absl::raw_logging_internal + absl::spinlock_wait + absl::type_traits) + set_property(TARGET absl::bind_front + PROPERTY INTERFACE_LINK_LIBRARIES absl::base_internal + absl::compressed_tuple) + set_property(TARGET absl::bits PROPERTY INTERFACE_LINK_LIBRARIES absl::core_headers) + set_property(TARGET absl::btree + PROPERTY INTERFACE_LINK_LIBRARIES + absl::container_common + absl::compare + absl::compressed_tuple + absl::container_memory + absl::cord + absl::core_headers + absl::layout + absl::memory + absl::strings + absl::throw_delegate + absl::type_traits + absl::utility) + set_property(TARGET absl::city PROPERTY INTERFACE_LINK_LIBRARIES absl::config + absl::core_headers absl::endian) + set_property(TARGET absl::cleanup_internal + PROPERTY INTERFACE_LINK_LIBRARIES absl::base_internal absl::core_headers + absl::utility) + set_property(TARGET absl::cleanup + PROPERTY INTERFACE_LINK_LIBRARIES absl::cleanup_internal absl::config + absl::core_headers) + set_property(TARGET absl::compare PROPERTY INTERFACE_LINK_LIBRARIES + absl::core_headers absl::type_traits) + set_property(TARGET absl::compressed_tuple PROPERTY INTERFACE_LINK_LIBRARIES + absl::utility) + set_property(TARGET absl::container_common PROPERTY INTERFACE_LINK_LIBRARIES + absl::type_traits) + set_property(TARGET absl::container_memory + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::memory + absl::type_traits + absl::utility) + set_property(TARGET absl::cord + PROPERTY INTERFACE_LINK_LIBRARIES + absl::base + absl::base_internal + absl::compressed_tuple + absl::config + absl::core_headers + absl::endian + absl::fixed_array + absl::function_ref + absl::inlined_vector + absl::optional + absl::raw_logging_internal + absl::strings + absl::strings_internal + absl::throw_delegate + absl::type_traits) + set_property(TARGET absl::core_headers PROPERTY INTERFACE_LINK_LIBRARIES absl::config) + set_property(TARGET absl::counting_allocator PROPERTY INTERFACE_LINK_LIBRARIES + absl::config) + set_property(TARGET absl::debugging_internal + PROPERTY INTERFACE_LINK_LIBRARIES + absl::core_headers + absl::config + absl::dynamic_annotations + absl::errno_saver + absl::raw_logging_internal) + set_property(TARGET absl::debugging PROPERTY INTERFACE_LINK_LIBRARIES + absl::stacktrace absl::leak_check) + set_property(TARGET absl::demangle_internal PROPERTY INTERFACE_LINK_LIBRARIES + absl::base absl::core_headers) + set_property(TARGET absl::dynamic_annotations PROPERTY INTERFACE_LINK_LIBRARIES + absl::config) + set_property(TARGET absl::endian PROPERTY INTERFACE_LINK_LIBRARIES absl::base + absl::config absl::core_headers) + set_property(TARGET absl::errno_saver PROPERTY INTERFACE_LINK_LIBRARIES absl::config) + set_property(TARGET absl::examine_stack + PROPERTY INTERFACE_LINK_LIBRARIES + absl::stacktrace + absl::symbolize + absl::config + absl::core_headers + absl::raw_logging_internal) + set_property(TARGET absl::exponential_biased PROPERTY INTERFACE_LINK_LIBRARIES + absl::config absl::core_headers) + set_property(TARGET absl::failure_signal_handler + PROPERTY INTERFACE_LINK_LIBRARIES + absl::examine_stack + absl::stacktrace + absl::base + absl::config + absl::core_headers + absl::errno_saver + absl::raw_logging_internal) + set_property(TARGET absl::fast_type_id PROPERTY INTERFACE_LINK_LIBRARIES absl::config) + set_property(TARGET absl::fixed_array + PROPERTY INTERFACE_LINK_LIBRARIES + absl::compressed_tuple + absl::algorithm + absl::config + absl::core_headers + absl::dynamic_annotations + absl::throw_delegate + absl::memory) + set_property(TARGET absl::flags_commandlineflag_internal + PROPERTY INTERFACE_LINK_LIBRARIES absl::config absl::fast_type_id) + set_property(TARGET absl::flags_commandlineflag + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::fast_type_id + absl::flags_commandlineflag_internal + absl::optional + absl::strings) + set_property(TARGET absl::flags_config + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::flags_path_util + absl::flags_program_name + absl::core_headers + absl::strings + absl::synchronization) + set_property(TARGET absl::flags_internal + PROPERTY INTERFACE_LINK_LIBRARIES + absl::base + absl::config + absl::flags_commandlineflag + absl::flags_commandlineflag_internal + absl::flags_config + absl::flags_marshalling + absl::synchronization + absl::meta + absl::utility) + set_property(TARGET absl::flags_marshalling + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::core_headers + absl::log_severity + absl::strings + absl::str_format) + set_property(TARGET absl::flags_parse + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::core_headers + absl::flags_config + absl::flags + absl::flags_commandlineflag + absl::flags_commandlineflag_internal + absl::flags_internal + absl::flags_private_handle_accessor + absl::flags_program_name + absl::flags_reflection + absl::flags_usage + absl::strings + absl::synchronization) + set_property(TARGET absl::flags_path_util PROPERTY INTERFACE_LINK_LIBRARIES + absl::config absl::strings) + set_property(TARGET absl::flags + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::flags_commandlineflag + absl::flags_config + absl::flags_internal + absl::flags_reflection + absl::base + absl::core_headers + absl::strings) + set_property(TARGET absl::flags_private_handle_accessor + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::flags_commandlineflag + absl::flags_commandlineflag_internal + absl::strings) + set_property(TARGET absl::flags_program_name + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::core_headers + absl::flags_path_util + absl::strings + absl::synchronization) + set_property(TARGET absl::flags_reflection + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::flags_commandlineflag + absl::flags_private_handle_accessor + absl::flags_config + absl::strings + absl::synchronization + absl::flat_hash_map) + set_property(TARGET absl::flags_usage_internal + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::flags_config + absl::flags + absl::flags_commandlineflag + absl::flags_internal + absl::flags_path_util + absl::flags_private_handle_accessor + absl::flags_program_name + absl::flags_reflection + absl::strings + absl::synchronization) + set_property(TARGET absl::flags_usage + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::core_headers + absl::flags_usage_internal + absl::strings + absl::synchronization) + set_property(TARGET absl::flat_hash_map + PROPERTY INTERFACE_LINK_LIBRARIES + absl::container_memory + absl::hash_function_defaults + absl::raw_hash_map + absl::algorithm_container + absl::memory) + set_property(TARGET absl::flat_hash_set + PROPERTY INTERFACE_LINK_LIBRARIES + absl::container_memory + absl::hash_function_defaults + absl::raw_hash_set + absl::algorithm_container + absl::core_headers + absl::memory) + set_property(TARGET absl::function_ref PROPERTY INTERFACE_LINK_LIBRARIES + absl::base_internal absl::meta) + set_property(TARGET absl::graphcycles_internal + PROPERTY INTERFACE_LINK_LIBRARIES + absl::base + absl::base_internal + absl::config + absl::core_headers + absl::malloc_internal + absl::raw_logging_internal) + set_property(TARGET absl::hash_function_defaults + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::cord + absl::hash + absl::strings) + set_property(TARGET absl::hash + PROPERTY INTERFACE_LINK_LIBRARIES + absl::city + absl::config + absl::core_headers + absl::endian + absl::fixed_array + absl::meta + absl::int128 + absl::strings + absl::optional + absl::variant + absl::utility + absl::wyhash) + set_property(TARGET absl::hash_policy_traits PROPERTY INTERFACE_LINK_LIBRARIES + absl::meta) + set_property(TARGET absl::hashtable_debug_hooks PROPERTY INTERFACE_LINK_LIBRARIES + absl::config) + set_property(TARGET absl::hashtable_debug PROPERTY INTERFACE_LINK_LIBRARIES + absl::hashtable_debug_hooks) + set_property(TARGET absl::hashtablez_sampler + PROPERTY INTERFACE_LINK_LIBRARIES + absl::base + absl::exponential_biased + absl::have_sse + absl::synchronization) + set_property(TARGET absl::inlined_vector_internal + PROPERTY INTERFACE_LINK_LIBRARIES + absl::compressed_tuple + absl::core_headers + absl::memory + absl::span + absl::type_traits) + set_property(TARGET absl::inlined_vector + PROPERTY INTERFACE_LINK_LIBRARIES + absl::algorithm + absl::core_headers + absl::inlined_vector_internal + absl::throw_delegate + absl::memory) + set_property(TARGET absl::int128 PROPERTY INTERFACE_LINK_LIBRARIES absl::config + absl::core_headers absl::bits) + set_property(TARGET absl::kernel_timeout_internal + PROPERTY INTERFACE_LINK_LIBRARIES absl::core_headers + absl::raw_logging_internal absl::time) + set_property(TARGET absl::layout + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::core_headers + absl::meta + absl::strings + absl::span + absl::utility) + set_property(TARGET absl::leak_check PROPERTY INTERFACE_LINK_LIBRARIES absl::config + absl::core_headers) + set_property(TARGET absl::log_severity PROPERTY INTERFACE_LINK_LIBRARIES + absl::core_headers) + set_property(TARGET absl::malloc_internal + PROPERTY INTERFACE_LINK_LIBRARIES + absl::base + absl::base_internal + absl::config + absl::core_headers + absl::dynamic_annotations + absl::raw_logging_internal) + set_property(TARGET absl::memory PROPERTY INTERFACE_LINK_LIBRARIES absl::core_headers + absl::meta) + set_property(TARGET absl::meta PROPERTY INTERFACE_LINK_LIBRARIES absl::type_traits) + set_property(TARGET absl::node_hash_map + PROPERTY INTERFACE_LINK_LIBRARIES + absl::container_memory + absl::hash_function_defaults + absl::node_hash_policy + absl::raw_hash_map + absl::algorithm_container + absl::memory) + set_property(TARGET absl::node_hash_policy PROPERTY INTERFACE_LINK_LIBRARIES + absl::config) + set_property(TARGET absl::node_hash_set + PROPERTY INTERFACE_LINK_LIBRARIES + absl::hash_function_defaults + absl::node_hash_policy + absl::raw_hash_set + absl::algorithm_container + absl::memory) + set_property(TARGET absl::numeric PROPERTY INTERFACE_LINK_LIBRARIES absl::int128) + set_property(TARGET absl::numeric_representation PROPERTY INTERFACE_LINK_LIBRARIES + absl::config) + set_property(TARGET absl::optional + PROPERTY INTERFACE_LINK_LIBRARIES + absl::bad_optional_access + absl::base_internal + absl::config + absl::core_headers + absl::memory + absl::type_traits + absl::utility) + set_property(TARGET absl::periodic_sampler + PROPERTY INTERFACE_LINK_LIBRARIES absl::core_headers + absl::exponential_biased) + set_property(TARGET absl::random_bit_gen_ref + PROPERTY INTERFACE_LINK_LIBRARIES + absl::core_headers + absl::random_internal_distribution_caller + absl::random_internal_fast_uniform_bits + absl::type_traits) + set_property(TARGET absl::random_distributions + PROPERTY INTERFACE_LINK_LIBRARIES + absl::base_internal + absl::config + absl::core_headers + absl::random_internal_generate_real + absl::random_internal_distribution_caller + absl::random_internal_fast_uniform_bits + absl::random_internal_fastmath + absl::random_internal_iostream_state_saver + absl::random_internal_traits + absl::random_internal_uniform_helper + absl::random_internal_wide_multiply + absl::strings + absl::type_traits) + set_property(TARGET absl::random_internal_distribution_caller + PROPERTY INTERFACE_LINK_LIBRARIES absl::config absl::utility + absl::fast_type_id) + set_property(TARGET absl::random_internal_distribution_test_util + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::core_headers + absl::raw_logging_internal + absl::strings + absl::str_format + absl::span) + set_property(TARGET absl::random_internal_fastmath PROPERTY INTERFACE_LINK_LIBRARIES + absl::bits) + set_property(TARGET absl::random_internal_fast_uniform_bits + PROPERTY INTERFACE_LINK_LIBRARIES absl::config) + set_property(TARGET absl::random_internal_generate_real + PROPERTY INTERFACE_LINK_LIBRARIES + absl::bits + absl::random_internal_fastmath + absl::random_internal_traits + absl::type_traits) + set_property(TARGET absl::random_internal_iostream_state_saver + PROPERTY INTERFACE_LINK_LIBRARIES absl::int128 absl::type_traits) + set_property(TARGET absl::random_internal_mock_helpers + PROPERTY INTERFACE_LINK_LIBRARIES absl::fast_type_id absl::optional) + set_property(TARGET absl::random_internal_nonsecure_base + PROPERTY INTERFACE_LINK_LIBRARIES + absl::core_headers + absl::optional + absl::random_internal_pool_urbg + absl::random_internal_salted_seed_seq + absl::random_internal_seed_material + absl::span + absl::type_traits) + set_property(TARGET absl::random_internal_pcg_engine + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::int128 + absl::random_internal_fastmath + absl::random_internal_iostream_state_saver + absl::type_traits) + set_property(TARGET absl::random_internal_platform PROPERTY INTERFACE_LINK_LIBRARIES + absl::config) + set_property(TARGET absl::random_internal_pool_urbg + PROPERTY INTERFACE_LINK_LIBRARIES + absl::base + absl::config + absl::core_headers + absl::endian + absl::random_internal_randen + absl::random_internal_seed_material + absl::random_internal_traits + absl::random_seed_gen_exception + absl::raw_logging_internal + absl::span) + set_property(TARGET absl::random_internal_randen_engine + PROPERTY INTERFACE_LINK_LIBRARIES + absl::endian + absl::random_internal_iostream_state_saver + absl::random_internal_randen + absl::raw_logging_internal + absl::type_traits) + set_property(TARGET absl::random_internal_randen_hwaes_impl + PROPERTY INTERFACE_LINK_LIBRARIES absl::random_internal_platform + absl::config) + set_property(TARGET absl::random_internal_randen_hwaes + PROPERTY INTERFACE_LINK_LIBRARIES absl::random_internal_platform + absl::random_internal_randen_hwaes_impl absl::config) + set_property(TARGET absl::random_internal_randen + PROPERTY INTERFACE_LINK_LIBRARIES absl::random_internal_platform + absl::random_internal_randen_hwaes + absl::random_internal_randen_slow) + set_property(TARGET absl::random_internal_randen_slow + PROPERTY INTERFACE_LINK_LIBRARIES absl::random_internal_platform + absl::config) + set_property(TARGET absl::random_internal_salted_seed_seq + PROPERTY INTERFACE_LINK_LIBRARIES + absl::inlined_vector + absl::optional + absl::span + absl::random_internal_seed_material + absl::type_traits) + set_property(TARGET absl::random_internal_seed_material + PROPERTY INTERFACE_LINK_LIBRARIES + absl::core_headers + absl::optional + absl::random_internal_fast_uniform_bits + absl::raw_logging_internal + absl::span + absl::strings) + set_property(TARGET absl::random_internal_traits PROPERTY INTERFACE_LINK_LIBRARIES + absl::config) + set_property(TARGET absl::random_internal_uniform_helper + PROPERTY INTERFACE_LINK_LIBRARIES absl::config + absl::random_internal_traits absl::type_traits) + set_property(TARGET absl::random_internal_wide_multiply + PROPERTY INTERFACE_LINK_LIBRARIES absl::bits absl::config absl::int128) + set_property(TARGET absl::random_random + PROPERTY INTERFACE_LINK_LIBRARIES + absl::random_distributions + absl::random_internal_nonsecure_base + absl::random_internal_pcg_engine + absl::random_internal_pool_urbg + absl::random_internal_randen_engine + absl::random_seed_sequences) + set_property(TARGET absl::random_seed_gen_exception PROPERTY INTERFACE_LINK_LIBRARIES + absl::config) + set_property(TARGET absl::random_seed_sequences + PROPERTY INTERFACE_LINK_LIBRARIES + absl::inlined_vector + absl::random_internal_nonsecure_base + absl::random_internal_pool_urbg + absl::random_internal_salted_seed_seq + absl::random_internal_seed_material + absl::random_seed_gen_exception + absl::span) + set_property(TARGET absl::raw_hash_map + PROPERTY INTERFACE_LINK_LIBRARIES absl::container_memory + absl::raw_hash_set absl::throw_delegate) + set_property(TARGET absl::raw_hash_set + PROPERTY INTERFACE_LINK_LIBRARIES + absl::bits + absl::compressed_tuple + absl::config + absl::container_common + absl::container_memory + absl::core_headers + absl::endian + absl::hash_policy_traits + absl::hashtable_debug_hooks + absl::have_sse + absl::layout + absl::memory + absl::meta + absl::optional + absl::utility + absl::hashtablez_sampler) + set_property(TARGET absl::raw_logging_internal + PROPERTY INTERFACE_LINK_LIBRARIES + absl::atomic_hook + absl::config + absl::core_headers + absl::log_severity) + set_property(TARGET absl::scoped_set_env + PROPERTY INTERFACE_LINK_LIBRARIES absl::config + absl::raw_logging_internal) + set_property(TARGET absl::span + PROPERTY INTERFACE_LINK_LIBRARIES + absl::algorithm + absl::core_headers + absl::throw_delegate + absl::type_traits) + set_property(TARGET absl::spinlock_wait + PROPERTY INTERFACE_LINK_LIBRARIES absl::base_internal absl::core_headers + absl::errno_saver) + set_property(TARGET absl::stacktrace + PROPERTY INTERFACE_LINK_LIBRARIES absl::debugging_internal absl::config + absl::core_headers) + set_property(TARGET absl::statusor + PROPERTY INTERFACE_LINK_LIBRARIES + absl::status + absl::core_headers + absl::raw_logging_internal + absl::type_traits + absl::strings + absl::utility + absl::variant) + set_property(TARGET absl::status + PROPERTY INTERFACE_LINK_LIBRARIES + absl::atomic_hook + absl::config + absl::core_headers + absl::raw_logging_internal + absl::inlined_vector + absl::stacktrace + absl::symbolize + absl::strings + absl::cord + absl::str_format + absl::optional) + set_property(TARGET absl::strerror PROPERTY INTERFACE_LINK_LIBRARIES absl::config + absl::core_headers absl::errno_saver) + set_property(TARGET absl::str_format_internal + PROPERTY INTERFACE_LINK_LIBRARIES + absl::bits + absl::strings + absl::config + absl::core_headers + absl::numeric_representation + absl::type_traits + absl::int128 + absl::span) + set_property(TARGET absl::str_format PROPERTY INTERFACE_LINK_LIBRARIES + absl::str_format_internal) + set_property(TARGET absl::strings_internal + PROPERTY INTERFACE_LINK_LIBRARIES + absl::config + absl::core_headers + absl::endian + absl::raw_logging_internal + absl::type_traits) + set_property(TARGET absl::strings + PROPERTY INTERFACE_LINK_LIBRARIES + absl::strings_internal + absl::base + absl::bits + absl::config + absl::core_headers + absl::endian + absl::int128 + absl::memory + absl::raw_logging_internal + absl::throw_delegate + absl::type_traits) + set_property(TARGET absl::symbolize + PROPERTY INTERFACE_LINK_LIBRARIES + absl::debugging_internal + absl::demangle_internal + absl::base + absl::config + absl::core_headers + absl::dynamic_annotations + absl::malloc_internal + absl::raw_logging_internal + absl::strings) + set_property(TARGET absl::synchronization + PROPERTY INTERFACE_LINK_LIBRARIES + absl::graphcycles_internal + absl::kernel_timeout_internal + absl::atomic_hook + absl::base + absl::base_internal + absl::config + absl::core_headers + absl::dynamic_annotations + absl::malloc_internal + absl::raw_logging_internal + absl::stacktrace + absl::symbolize + absl::time) + set_property(TARGET absl::throw_delegate + PROPERTY INTERFACE_LINK_LIBRARIES absl::config + absl::raw_logging_internal) + set_property(TARGET absl::time + PROPERTY INTERFACE_LINK_LIBRARIES + absl::base + absl::civil_time + absl::core_headers + absl::int128 + absl::raw_logging_internal + absl::strings + absl::time_zone) + set_property(TARGET absl::type_traits PROPERTY INTERFACE_LINK_LIBRARIES absl::config) + set_property(TARGET absl::utility + PROPERTY INTERFACE_LINK_LIBRARIES absl::base_internal absl::config + absl::type_traits) + set_property(TARGET absl::variant + PROPERTY INTERFACE_LINK_LIBRARIES + absl::bad_variant_access + absl::base_internal + absl::config + absl::core_headers + absl::type_traits + absl::utility) + set_property(TARGET absl::wyhash PROPERTY INTERFACE_LINK_LIBRARIES absl::config + absl::endian absl::int128) + + externalproject_add(absl_ep + ${EP_LOG_OPTIONS} + URL ${ABSL_SOURCE_URL} + URL_HASH "SHA256=${ARROW_ABSL_BUILD_SHA256_CHECKSUM}" + CMAKE_ARGS ${ABSL_CMAKE_ARGS} + BUILD_BYPRODUCTS ${ABSL_BUILD_BYPRODUCTS}) + + # Work around https://gitlab.kitware.com/cmake/cmake/issues/15052 + file(MAKE_DIRECTORY ${ABSL_INCLUDE_DIR}) + + endif() +endmacro() + +macro(build_grpc) + resolve_dependency(c-ares + HAVE_ALT + TRUE + PC_PACKAGE_NAMES + libcares) + # TODO: Don't use global includes but rather target_include_directories + get_target_property(c-ares_INCLUDE_DIR c-ares::cares INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM ${c-ares_INCLUDE_DIR}) + + # First need to build Abseil + build_absl_once() + + message(STATUS "Building gRPC from source") + + set(GRPC_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/grpc_ep-prefix/src/grpc_ep-build") + set(GRPC_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/grpc_ep-install") + set(GRPC_HOME "${GRPC_PREFIX}") + set(GRPC_INCLUDE_DIR "${GRPC_PREFIX}/include") + + set(GRPC_STATIC_LIBRARY_GPR + "${GRPC_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}gpr${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + set(GRPC_STATIC_LIBRARY_GRPC + "${GRPC_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}grpc${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + set(GRPC_STATIC_LIBRARY_GRPCPP + "${GRPC_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}grpc++${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + set(GRPC_STATIC_LIBRARY_ADDRESS_SORTING + "${GRPC_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}address_sorting${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + set(GRPC_STATIC_LIBRARY_UPB + "${GRPC_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}upb${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + set(GRPC_CPP_PLUGIN "${GRPC_PREFIX}/bin/grpc_cpp_plugin${CMAKE_EXECUTABLE_SUFFIX}") + + set(GRPC_CMAKE_PREFIX) + + add_custom_target(grpc_dependencies) + + add_dependencies(grpc_dependencies absl_ep) + if(CARES_VENDORED) + add_dependencies(grpc_dependencies cares_ep) + endif() + + if(GFLAGS_VENDORED) + add_dependencies(grpc_dependencies gflags_ep) + endif() + + if(RE2_VENDORED) + add_dependencies(grpc_dependencies re2_ep) + endif() + + add_dependencies(grpc_dependencies ${ARROW_PROTOBUF_LIBPROTOBUF} c-ares::cares + ZLIB::ZLIB) + + get_target_property(GRPC_PROTOBUF_INCLUDE_DIR ${ARROW_PROTOBUF_LIBPROTOBUF} + INTERFACE_INCLUDE_DIRECTORIES) + get_filename_component(GRPC_PB_ROOT "${GRPC_PROTOBUF_INCLUDE_DIR}" DIRECTORY) + get_target_property(GRPC_Protobuf_PROTOC_LIBRARY ${ARROW_PROTOBUF_LIBPROTOC} + IMPORTED_LOCATION) + get_target_property(GRPC_CARES_INCLUDE_DIR c-ares::cares INTERFACE_INCLUDE_DIRECTORIES) + get_filename_component(GRPC_CARES_ROOT "${GRPC_CARES_INCLUDE_DIR}" DIRECTORY) + get_target_property(GRPC_GFLAGS_INCLUDE_DIR ${GFLAGS_LIBRARIES} + INTERFACE_INCLUDE_DIRECTORIES) + get_filename_component(GRPC_GFLAGS_ROOT "${GRPC_GFLAGS_INCLUDE_DIR}" DIRECTORY) + get_target_property(GRPC_RE2_INCLUDE_DIR re2::re2 INTERFACE_INCLUDE_DIRECTORIES) + get_filename_component(GRPC_RE2_ROOT "${GRPC_RE2_INCLUDE_DIR}" DIRECTORY) + + set(GRPC_CMAKE_PREFIX "${GRPC_CMAKE_PREFIX};${GRPC_PB_ROOT}") + set(GRPC_CMAKE_PREFIX "${GRPC_CMAKE_PREFIX};${GRPC_GFLAGS_ROOT}") + set(GRPC_CMAKE_PREFIX "${GRPC_CMAKE_PREFIX};${GRPC_CARES_ROOT}") + set(GRPC_CMAKE_PREFIX "${GRPC_CMAKE_PREFIX};${GRPC_RE2_ROOT}") + + # ZLIB is never vendored + set(GRPC_CMAKE_PREFIX "${GRPC_CMAKE_PREFIX};${ZLIB_ROOT}") + set(GRPC_CMAKE_PREFIX "${GRPC_CMAKE_PREFIX};${ABSL_PREFIX}") + + if(RAPIDJSON_VENDORED) + add_dependencies(grpc_dependencies rapidjson_ep) + endif() + + # Yuck, see https://stackoverflow.com/a/45433229/776560 + string(REPLACE ";" "|" GRPC_PREFIX_PATH_ALT_SEP "${GRPC_CMAKE_PREFIX}") + + set(GRPC_CMAKE_ARGS + "${EP_COMMON_CMAKE_ARGS}" + -DCMAKE_PREFIX_PATH='${GRPC_PREFIX_PATH_ALT_SEP}' + -DgRPC_ABSL_PROVIDER=package + -DgRPC_BUILD_CSHARP_EXT=OFF + -DgRPC_BUILD_GRPC_CSHARP_PLUGIN=OFF + -DgRPC_BUILD_GRPC_NODE_PLUGIN=OFF + -DgRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN=OFF + -DgRPC_BUILD_GRPC_PHP_PLUGIN=OFF + -DgRPC_BUILD_GRPC_PYTHON_PLUGIN=OFF + -DgRPC_BUILD_GRPC_RUBY_PLUGIN=OFF + -DgRPC_BUILD_TESTS=OFF + -DgRPC_CARES_PROVIDER=package + -DgRPC_GFLAGS_PROVIDER=package + -DgRPC_MSVC_STATIC_RUNTIME=${ARROW_USE_STATIC_CRT} + -DgRPC_PROTOBUF_PROVIDER=package + -DgRPC_RE2_PROVIDER=package + -DgRPC_SSL_PROVIDER=package + -DgRPC_ZLIB_PROVIDER=package + -DCMAKE_INSTALL_PREFIX=${GRPC_PREFIX} + -DCMAKE_INSTALL_LIBDIR=lib + -DBUILD_SHARED_LIBS=OFF) + if(PROTOBUF_VENDORED) + list(APPEND GRPC_CMAKE_ARGS -DgRPC_PROTOBUF_PACKAGE_TYPE=CONFIG) + endif() + if(OPENSSL_ROOT_DIR) + list(APPEND GRPC_CMAKE_ARGS -DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR}) + endif() + + # XXX the gRPC git checkout is huge and takes a long time + # Ideally, we should be able to use the tarballs, but they don't contain + # vendored dependencies such as c-ares... + externalproject_add(grpc_ep + URL ${GRPC_SOURCE_URL} + URL_HASH "SHA256=${ARROW_GRPC_BUILD_SHA256_CHECKSUM}" + LIST_SEPARATOR | + BUILD_BYPRODUCTS ${GRPC_STATIC_LIBRARY_GPR} + ${GRPC_STATIC_LIBRARY_GRPC} + ${GRPC_STATIC_LIBRARY_GRPCPP} + ${GRPC_STATIC_LIBRARY_ADDRESS_SORTING} + ${GRPC_STATIC_LIBRARY_UPB} + ${GRPC_CPP_PLUGIN} + CMAKE_ARGS ${GRPC_CMAKE_ARGS} ${EP_LOG_OPTIONS} + DEPENDS ${grpc_dependencies}) + + # Work around https://gitlab.kitware.com/cmake/cmake/issues/15052 + file(MAKE_DIRECTORY ${GRPC_INCLUDE_DIR}) + + add_library(gRPC::upb STATIC IMPORTED) + set_target_properties(gRPC::upb + PROPERTIES IMPORTED_LOCATION "${GRPC_STATIC_LIBRARY_UPB}" + INTERFACE_INCLUDE_DIRECTORIES "${GRPC_INCLUDE_DIR}") + + set(GRPC_GPR_ABSL_LIBRARIES + absl::base + absl::statusor + absl::status + absl::cord + absl::strings + absl::synchronization + absl::time) + add_library(gRPC::gpr STATIC IMPORTED) + set_target_properties(gRPC::gpr + PROPERTIES IMPORTED_LOCATION "${GRPC_STATIC_LIBRARY_GPR}" + INTERFACE_INCLUDE_DIRECTORIES "${GRPC_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "${GRPC_GPR_ABSL_LIBRARIES}") + + add_library(gRPC::address_sorting STATIC IMPORTED) + set_target_properties(gRPC::address_sorting + PROPERTIES IMPORTED_LOCATION + "${GRPC_STATIC_LIBRARY_ADDRESS_SORTING}" + INTERFACE_INCLUDE_DIRECTORIES "${GRPC_INCLUDE_DIR}") + + add_library(gRPC::grpc STATIC IMPORTED) + set(GRPC_LINK_LIBRARIES + gRPC::gpr + gRPC::upb + gRPC::address_sorting + re2::re2 + c-ares::cares + ZLIB::ZLIB + OpenSSL::SSL + Threads::Threads) + set_target_properties(gRPC::grpc + PROPERTIES IMPORTED_LOCATION "${GRPC_STATIC_LIBRARY_GRPC}" + INTERFACE_INCLUDE_DIRECTORIES "${GRPC_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "${GRPC_LINK_LIBRARIES}") + + add_library(gRPC::grpc++ STATIC IMPORTED) + set(GRPCPP_LINK_LIBRARIES gRPC::grpc ${ARROW_PROTOBUF_LIBPROTOBUF}) + set_target_properties(gRPC::grpc++ + PROPERTIES IMPORTED_LOCATION "${GRPC_STATIC_LIBRARY_GRPCPP}" + INTERFACE_INCLUDE_DIRECTORIES "${GRPC_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "${GRPCPP_LINK_LIBRARIES}") + + add_executable(gRPC::grpc_cpp_plugin IMPORTED) + set_target_properties(gRPC::grpc_cpp_plugin PROPERTIES IMPORTED_LOCATION + ${GRPC_CPP_PLUGIN}) + + add_dependencies(grpc_ep grpc_dependencies) + add_dependencies(toolchain grpc_ep) + add_dependencies(gRPC::grpc++ grpc_ep) + add_dependencies(gRPC::grpc_cpp_plugin grpc_ep) + set(GRPC_VENDORED TRUE) + + # ar -M rejects with the "libgrpc++.a" filename because "+" is a line + # continuation character in these scripts, so we have to create a copy of the + # static lib that we will bundle later + + set(GRPC_STATIC_LIBRARY_GRPCPP_FOR_AR + "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}grpcpp${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + add_custom_command(OUTPUT ${GRPC_STATIC_LIBRARY_GRPCPP_FOR_AR} + COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:gRPC::grpc++> + ${GRPC_STATIC_LIBRARY_GRPCPP_FOR_AR} + DEPENDS grpc_ep) + add_library(gRPC::grpcpp_for_bundling STATIC IMPORTED) + set_target_properties(gRPC::grpcpp_for_bundling + PROPERTIES IMPORTED_LOCATION + "${GRPC_STATIC_LIBRARY_GRPCPP_FOR_AR}") + + set_source_files_properties("${GRPC_STATIC_LIBRARY_GRPCPP_FOR_AR}" PROPERTIES GENERATED + TRUE) + add_custom_target(grpc_copy_grpc++ ALL DEPENDS "${GRPC_STATIC_LIBRARY_GRPCPP_FOR_AR}") + add_dependencies(gRPC::grpcpp_for_bundling grpc_copy_grpc++) + + list(APPEND + ARROW_BUNDLED_STATIC_LIBS + ${GRPC_GPR_ABSL_LIBRARIES} + gRPC::address_sorting + gRPC::gpr + gRPC::grpc + gRPC::grpcpp_for_bundling + gRPC::upb) +endmacro() + +if(ARROW_WITH_GRPC) + set(ARROW_GRPC_REQUIRED_VERSION "1.17.0") + resolve_dependency(gRPC + HAVE_ALT + TRUE + REQUIRED_VERSION + ${ARROW_GRPC_REQUIRED_VERSION} + PC_PACKAGE_NAMES + grpc++) + + # TODO: Don't use global includes but rather target_include_directories + get_target_property(GRPC_INCLUDE_DIR gRPC::grpc++ INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM ${GRPC_INCLUDE_DIR}) + + if(GRPC_VENDORED) + set(GRPCPP_PP_INCLUDE TRUE) + else() + # grpc++ headers may reside in ${GRPC_INCLUDE_DIR}/grpc++ or ${GRPC_INCLUDE_DIR}/grpcpp + # depending on the gRPC version. + if(EXISTS "${GRPC_INCLUDE_DIR}/grpcpp/impl/codegen/config_protobuf.h") + set(GRPCPP_PP_INCLUDE TRUE) + elseif(EXISTS "${GRPC_INCLUDE_DIR}/grpc++/impl/codegen/config_protobuf.h") + set(GRPCPP_PP_INCLUDE FALSE) + else() + message(FATAL_ERROR "Cannot find grpc++ headers in ${GRPC_INCLUDE_DIR}") + endif() + endif() +endif() + +# ---------------------------------------------------------------------- +# GCS and dependencies + +macro(build_crc32c_once) + if(NOT TARGET crc32c_ep) + message(STATUS "Building crc32c from source") + # Build crc32c + set(CRC32C_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/crc32c_ep-install") + set(CRC32C_INCLUDE_DIR "${CRC32C_PREFIX}/include") + set(CRC32C_CMAKE_ARGS + ${EP_COMMON_CMAKE_ARGS} + -DCMAKE_INSTALL_LIBDIR=lib + "-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>" + -DCMAKE_CXX_STANDARD=11 + -DCRC32C_BUILD_TESTS=OFF + -DCRC32C_BUILD_BENCHMARKS=OFF + -DCRC32C_USE_GLOG=OFF) + + set(_CRC32C_STATIC_LIBRARY + "${CRC32C_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}crc32c${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + set(CRC32C_BUILD_BYPRODUCTS ${_CRC32C_STATIC_LIBRARY}) + set(CRC32C_LIBRARIES crc32c) + + externalproject_add(crc32c_ep + ${EP_LOG_OPTIONS} + INSTALL_DIR ${CRC32C_PREFIX} + URL ${CRC32C_SOURCE_URL} + URL_HASH "SHA256=${ARROW_CRC32C_BUILD_SHA256_CHECKSUM}" + CMAKE_ARGS ${CRC32C_CMAKE_ARGS} + BUILD_BYPRODUCTS ${CRC32C_BUILD_BYPRODUCTS}) + # Work around https://gitlab.kitware.com/cmake/cmake/issues/15052 + file(MAKE_DIRECTORY "${CRC32C_INCLUDE_DIR}") + add_library(Crc32c::crc32c STATIC IMPORTED) + set_target_properties(Crc32c::crc32c + PROPERTIES IMPORTED_LOCATION ${_CRC32C_STATIC_LIBRARY} + INTERFACE_INCLUDE_DIRECTORIES + "${CRC32C_INCLUDE_DIR}") + add_dependencies(Crc32c::crc32c crc32c_ep) + endif() +endmacro() + +macro(build_nlohmann_json_once) + if(NOT TARGET nlohmann_json_ep) + message(STATUS "Building nlohmann-json from source") + # "Build" nlohmann-json + set(NLOHMANN_JSON_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/nlohmann_json_ep-install") + set(NLOHMANN_JSON_INCLUDE_DIR "${NLOHMANN_JSON_PREFIX}/include") + set(NLOHMANN_JSON_CMAKE_ARGS + ${EP_COMMON_CMAKE_ARGS} -DCMAKE_CXX_STANDARD=11 + "-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>" -DBUILD_TESTING=OFF) + + set(NLOHMANN_JSON_BUILD_BYPRODUCTS ${NLOHMANN_JSON_PREFIX}/include/nlohmann/json.hpp) + + externalproject_add(nlohmann_json_ep + ${EP_LOG_OPTIONS} + INSTALL_DIR ${NLOHMANN_JSON_PREFIX} + URL ${NLOHMANN_JSON_SOURCE_URL} + URL_HASH "SHA256=${ARROW_NLOHMANN_JSON_BUILD_SHA256_CHECKSUM}" + CMAKE_ARGS ${NLOHMANN_JSON_CMAKE_ARGS} + BUILD_BYPRODUCTS ${NLOHMANN_JSON_BUILD_BYPRODUCTS}) + + # Work around https://gitlab.kitware.com/cmake/cmake/issues/15052 + file(MAKE_DIRECTORY ${NLOHMANN_JSON_INCLUDE_DIR}) + + add_library(nlohmann_json::nlohmann_json INTERFACE IMPORTED) + set_target_properties(nlohmann_json::nlohmann_json + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${NLOHMANN_JSON_INCLUDE_DIR}") + add_dependencies(nlohmann_json::nlohmann_json nlohmann_json_ep) + endif() +endmacro() + +macro(build_google_cloud_cpp_storage) + message(STATUS "Building google-cloud-cpp from source") + message(STATUS "Only building the google-cloud-cpp::storage component") + + # List of dependencies taken from https://github.com/googleapis/google-cloud-cpp/blob/master/doc/packaging.md + build_absl_once() + build_crc32c_once() + build_nlohmann_json_once() + + # Curl is required on all platforms, but building it internally might also trip over S3's copy. + # For now, force its inclusion from the underlying system or fail. + find_package(CURL 7.47.0 REQUIRED) + find_package(OpenSSL ${ARROW_OPENSSL_REQUIRED_VERSION} REQUIRED) + + # Build google-cloud-cpp, with only storage_client + + # Inject vendored packages via CMAKE_PREFIX_PATH + list(APPEND GOOGLE_CLOUD_CPP_PREFIX_PATH_LIST ${ABSL_PREFIX}) + list(APPEND GOOGLE_CLOUD_CPP_PREFIX_PATH_LIST ${CRC32C_PREFIX}) + list(APPEND GOOGLE_CLOUD_CPP_PREFIX_PATH_LIST ${NLOHMANN_JSON_PREFIX}) + + set(GOOGLE_CLOUD_CPP_PREFIX_PATH_LIST_SEP_CHAR "|") + list(JOIN GOOGLE_CLOUD_CPP_PREFIX_PATH_LIST + ${GOOGLE_CLOUD_CPP_PREFIX_PATH_LIST_SEP_CHAR} GOOGLE_CLOUD_CPP_PREFIX_PATH) + + set(GOOGLE_CLOUD_CPP_INSTALL_PREFIX + "${CMAKE_CURRENT_BINARY_DIR}/google_cloud_cpp_ep-install") + set(GOOGLE_CLOUD_CPP_INCLUDE_DIR "${GOOGLE_CLOUD_CPP_INSTALL_PREFIX}/include") + set(GOOGLE_CLOUD_CPP_CMAKE_ARGS + ${EP_COMMON_CMAKE_ARGS} + -DBUILD_TESTING=OFF + -DCMAKE_INSTALL_LIBDIR=lib + "-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>" + -DCMAKE_INSTALL_RPATH=$ORIGIN + -DCMAKE_PREFIX_PATH=${GOOGLE_CLOUD_CPP_PREFIX_PATH} + # Compile only the storage library and its dependencies. To enable + # other services (Spanner, Bigtable, etc.) add them (as a list) to this + # parameter. Each has its own `google-cloud-cpp::*` library. + -DGOOGLE_CLOUD_CPP_ENABLE=storage) + if(OPENSSL_ROOT_DIR) + list(APPEND GOOGLE_CLOUD_CPP_CMAKE_ARGS -DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR}) + endif() + + add_custom_target(google_cloud_cpp_dependencies) + + add_dependencies(google_cloud_cpp_dependencies absl_ep) + add_dependencies(google_cloud_cpp_dependencies crc32c_ep) + add_dependencies(google_cloud_cpp_dependencies nlohmann_json_ep) + # Typically the steps to build the AWKSSDK provide `CURL::libcurl`, but if that is + # disabled we need to provide our own. + if(NOT TARGET CURL::libcurl) + find_package(CURL REQUIRED) + if(NOT TARGET CURL::libcurl) + # For CMake 3.11 or older + add_library(CURL::libcurl UNKNOWN IMPORTED) + set_target_properties(CURL::libcurl + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${CURL_INCLUDE_DIRS}" IMPORTED_LOCATION + "${CURL_LIBRARIES}") + endif() + endif() + + set(GOOGLE_CLOUD_CPP_STATIC_LIBRARY_STORAGE + "${GOOGLE_CLOUD_CPP_INSTALL_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}google_cloud_cpp_storage${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + + set(GOOGLE_CLOUD_CPP_STATIC_LIBRARY_COMMON + "${GOOGLE_CLOUD_CPP_INSTALL_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}google_cloud_cpp_common${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + + externalproject_add(google_cloud_cpp_ep + ${EP_LOG_OPTIONS} + LIST_SEPARATOR ${GOOGLE_CLOUD_CPP_PREFIX_PATH_LIST_SEP_CHAR} + INSTALL_DIR ${GOOGLE_CLOUD_CPP_INSTALL_PREFIX} + URL ${google_cloud_cpp_storage_SOURCE_URL} + URL_HASH "SHA256=${ARROW_GOOGLE_CLOUD_CPP_BUILD_SHA256_CHECKSUM}" + CMAKE_ARGS ${GOOGLE_CLOUD_CPP_CMAKE_ARGS} + BUILD_BYPRODUCTS ${GOOGLE_CLOUD_CPP_STATIC_LIBRARY_STORAGE} + ${GOOGLE_CLOUD_CPP_STATIC_LIBRARY_COMMON} + DEPENDS google_cloud_cpp_dependencies) + + # Work around https://gitlab.kitware.com/cmake/cmake/issues/15052 + file(MAKE_DIRECTORY ${GOOGLE_CLOUD_CPP_INCLUDE_DIR}) + + add_dependencies(toolchain google_cloud_cpp_ep) + + add_library(google-cloud-cpp::common STATIC IMPORTED) + set_target_properties(google-cloud-cpp::common + PROPERTIES IMPORTED_LOCATION + "${GOOGLE_CLOUD_CPP_STATIC_LIBRARY_COMMON}" + INTERFACE_INCLUDE_DIRECTORIES + "${GOOGLE_CLOUD_CPP_INCLUDE_DIR}") + set_property(TARGET google-cloud-cpp::common + PROPERTY INTERFACE_LINK_LIBRARIES + absl::any + absl::flat_hash_map + absl::memory + absl::optional + absl::time + Threads::Threads) + + add_library(google-cloud-cpp::storage STATIC IMPORTED) + set_target_properties(google-cloud-cpp::storage + PROPERTIES IMPORTED_LOCATION + "${GOOGLE_CLOUD_CPP_STATIC_LIBRARY_STORAGE}" + INTERFACE_INCLUDE_DIRECTORIES + "${GOOGLE_CLOUD_CPP_INCLUDE_DIR}") + set_property(TARGET google-cloud-cpp::storage + PROPERTY INTERFACE_LINK_LIBRARIES + google-cloud-cpp::common + absl::memory + absl::strings + absl::str_format + absl::time + absl::variant + nlohmann_json::nlohmann_json + Crc32c::crc32c + CURL::libcurl + Threads::Threads + OpenSSL::SSL + OpenSSL::Crypto) + add_dependencies(google-cloud-cpp::storage google_cloud_cpp_ep) + + list(APPEND ARROW_BUNDLED_STATIC_LIBS google-cloud-cpp::storage + google-cloud-cpp::common) +endmacro() + +if(ARROW_WITH_GOOGLE_CLOUD_CPP) + resolve_dependency(google_cloud_cpp_storage) + get_target_property(google_cloud_cpp_storage_INCLUDE_DIR google-cloud-cpp::storage + INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM ${google_cloud_cpp_storage_INCLUDE_DIR}) + get_target_property(absl_base_INCLUDE_DIR absl::base INTERFACE_INCLUDE_DIRECTORIES) + include_directories(SYSTEM ${absl_base_INCLUDE_DIR}) + message(STATUS "Found google-cloud-cpp::storage headers: ${google_cloud_cpp_storage_INCLUDE_DIR}" + ) +endif() + +# +# HDFS thirdparty setup + +if(DEFINED ENV{HADOOP_HOME}) + set(HADOOP_HOME $ENV{HADOOP_HOME}) + if(NOT EXISTS "${HADOOP_HOME}/include/hdfs.h") + message(STATUS "Did not find hdfs.h in expected location, using vendored one") + set(HADOOP_HOME "${THIRDPARTY_DIR}/hadoop") + endif() +else() + set(HADOOP_HOME "${THIRDPARTY_DIR}/hadoop") +endif() + +set(HDFS_H_PATH "${HADOOP_HOME}/include/hdfs.h") +if(NOT EXISTS ${HDFS_H_PATH}) + message(FATAL_ERROR "Did not find hdfs.h at ${HDFS_H_PATH}") +endif() +message(STATUS "Found hdfs.h at: " ${HDFS_H_PATH}) + +include_directories(SYSTEM "${HADOOP_HOME}/include") + +# ---------------------------------------------------------------------- +# Apache ORC + +macro(build_orc) + message("Building Apache ORC from source") + set(ORC_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/orc_ep-install") + set(ORC_HOME "${ORC_PREFIX}") + set(ORC_INCLUDE_DIR "${ORC_PREFIX}/include") + set(ORC_STATIC_LIB + "${ORC_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}orc${CMAKE_STATIC_LIBRARY_SUFFIX}") + + get_target_property(ORC_PROTOBUF_INCLUDE_DIR ${ARROW_PROTOBUF_LIBPROTOBUF} + INTERFACE_INCLUDE_DIRECTORIES) + get_filename_component(ORC_PB_ROOT "${ORC_PROTOBUF_INCLUDE_DIR}" DIRECTORY) + get_target_property(ORC_PROTOBUF_LIBRARY ${ARROW_PROTOBUF_LIBPROTOBUF} + IMPORTED_LOCATION) + + get_target_property(ORC_SNAPPY_INCLUDE_DIR Snappy::snappy INTERFACE_INCLUDE_DIRECTORIES) + get_filename_component(ORC_SNAPPY_ROOT "${ORC_SNAPPY_INCLUDE_DIR}" DIRECTORY) + + get_target_property(ORC_LZ4_ROOT LZ4::lz4 INTERFACE_INCLUDE_DIRECTORIES) + get_filename_component(ORC_LZ4_ROOT "${ORC_LZ4_ROOT}" DIRECTORY) + + # Weirdly passing in PROTOBUF_LIBRARY for PROTOC_LIBRARY still results in ORC finding + # the protoc library. + set(ORC_CMAKE_ARGS + ${EP_COMMON_CMAKE_ARGS} + "-DCMAKE_INSTALL_PREFIX=${ORC_PREFIX}" + -DCMAKE_CXX_FLAGS=${EP_CXX_FLAGS} + -DSTOP_BUILD_ON_WARNING=OFF + -DBUILD_LIBHDFSPP=OFF + -DBUILD_JAVA=OFF + -DBUILD_TOOLS=OFF + -DBUILD_CPP_TESTS=OFF + -DINSTALL_VENDORED_LIBS=OFF + "-DSNAPPY_HOME=${ORC_SNAPPY_ROOT}" + "-DSNAPPY_INCLUDE_DIR=${ORC_SNAPPY_INCLUDE_DIR}" + "-DPROTOBUF_HOME=${ORC_PB_ROOT}" + "-DPROTOBUF_INCLUDE_DIR=${ORC_PROTOBUF_INCLUDE_DIR}" + "-DPROTOBUF_LIBRARY=${ORC_PROTOBUF_LIBRARY}" + "-DPROTOC_LIBRARY=${ORC_PROTOBUF_LIBRARY}" + "-DLZ4_HOME=${LZ4_HOME}" + "-DZSTD_HOME=${ZSTD_HOME}") + if(ZLIB_ROOT) + set(ORC_CMAKE_ARGS ${ORC_CMAKE_ARGS} "-DZLIB_HOME=${ZLIB_ROOT}") + endif() + + # Work around CMake bug + file(MAKE_DIRECTORY ${ORC_INCLUDE_DIR}) + + externalproject_add(orc_ep + URL ${ORC_SOURCE_URL} + URL_HASH "SHA256=${ARROW_ORC_BUILD_SHA256_CHECKSUM}" + BUILD_BYPRODUCTS ${ORC_STATIC_LIB} + CMAKE_ARGS ${ORC_CMAKE_ARGS} ${EP_LOG_OPTIONS}) + + add_dependencies(toolchain orc_ep) + + set(ORC_VENDORED 1) + add_dependencies(orc_ep ZLIB::ZLIB) + add_dependencies(orc_ep LZ4::lz4) + add_dependencies(orc_ep Snappy::snappy) + add_dependencies(orc_ep ${ARROW_PROTOBUF_LIBPROTOBUF}) + + add_library(orc::liborc STATIC IMPORTED) + set_target_properties(orc::liborc + PROPERTIES IMPORTED_LOCATION "${ORC_STATIC_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${ORC_INCLUDE_DIR}") + + add_dependencies(toolchain orc_ep) + add_dependencies(orc::liborc orc_ep) + + list(APPEND ARROW_BUNDLED_STATIC_LIBS orc::liborc) +endmacro() + +if(ARROW_ORC) + resolve_dependency(ORC) + include_directories(SYSTEM ${ORC_INCLUDE_DIR}) + message(STATUS "Found ORC static library: ${ORC_STATIC_LIB}") + message(STATUS "Found ORC headers: ${ORC_INCLUDE_DIR}") +endif() + +# ---------------------------------------------------------------------- +# AWS SDK for C++ + +macro(build_awssdk) + message("Building AWS C++ SDK from source") + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS + "4.9") + message(FATAL_ERROR "AWS C++ SDK requires gcc >= 4.9") + endif() + set(AWSSDK_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/awssdk_ep-install") + set(AWSSDK_INCLUDE_DIR "${AWSSDK_PREFIX}/include") + set(AWSSDK_LIB_DIR "lib") + + if(WIN32) + # On Windows, need to match build types + set(AWSSDK_BUILD_TYPE ${CMAKE_BUILD_TYPE}) + else() + # Otherwise, always build in release mode. + # Especially with gcc, debug builds can fail with "asm constraint" errors: + # https://github.com/TileDB-Inc/TileDB/issues/1351 + set(AWSSDK_BUILD_TYPE release) + endif() + + set(AWSSDK_COMMON_CMAKE_ARGS + ${EP_COMMON_CMAKE_ARGS} + -DBUILD_SHARED_LIBS=OFF + -DCMAKE_BUILD_TYPE=${AWSSDK_BUILD_TYPE} + -DCMAKE_INSTALL_LIBDIR=${AWSSDK_LIB_DIR} + -DENABLE_TESTING=OFF + -DENABLE_UNITY_BUILD=ON + "-DCMAKE_INSTALL_PREFIX=${AWSSDK_PREFIX}" + "-DCMAKE_PREFIX_PATH=${AWSSDK_PREFIX}") + + set(AWSSDK_CMAKE_ARGS + ${AWSSDK_COMMON_CMAKE_ARGS} + -DBUILD_DEPS=OFF + -DBUILD_ONLY=config\\$<SEMICOLON>s3\\$<SEMICOLON>transfer\\$<SEMICOLON>identity-management\\$<SEMICOLON>sts + -DMINIMIZE_SIZE=ON) + if(UNIX AND TARGET zlib_ep) + list(APPEND AWSSDK_CMAKE_ARGS -DZLIB_INCLUDE_DIR=${ZLIB_INCLUDE_DIRS} + -DZLIB_LIBRARY=${ZLIB_LIBRARIES}) + endif() + + file(MAKE_DIRECTORY ${AWSSDK_INCLUDE_DIR}) + + # AWS C++ SDK related libraries to link statically + set(_AWSSDK_LIBS + aws-cpp-sdk-identity-management + aws-cpp-sdk-sts + aws-cpp-sdk-cognito-identity + aws-cpp-sdk-s3 + aws-cpp-sdk-core + aws-c-event-stream + aws-checksums + aws-c-common) + set(AWSSDK_LIBRARIES) + foreach(_AWSSDK_LIB ${_AWSSDK_LIBS}) + # aws-c-common -> AWS-C-COMMON + string(TOUPPER ${_AWSSDK_LIB} _AWSSDK_LIB_UPPER) + # AWS-C-COMMON -> AWS_C_COMMON + string(REPLACE "-" "_" _AWSSDK_LIB_NAME_PREFIX ${_AWSSDK_LIB_UPPER}) + set(_AWSSDK_STATIC_LIBRARY + "${AWSSDK_PREFIX}/${AWSSDK_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${_AWSSDK_LIB}${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + if(${_AWSSDK_LIB} MATCHES "^aws-cpp-sdk-") + set(_AWSSDK_TARGET_NAME ${_AWSSDK_LIB}) + else() + set(_AWSSDK_TARGET_NAME AWS::${_AWSSDK_LIB}) + endif() + add_library(${_AWSSDK_TARGET_NAME} STATIC IMPORTED) + set_target_properties(${_AWSSDK_TARGET_NAME} + PROPERTIES IMPORTED_LOCATION ${_AWSSDK_STATIC_LIBRARY} + INTERFACE_INCLUDE_DIRECTORIES + "${AWSSDK_INCLUDE_DIR}") + set("${_AWSSDK_LIB_NAME_PREFIX}_STATIC_LIBRARY" ${_AWSSDK_STATIC_LIBRARY}) + list(APPEND AWSSDK_LIBRARIES ${_AWSSDK_TARGET_NAME}) + endforeach() + + externalproject_add(aws_c_common_ep + ${EP_LOG_OPTIONS} + URL ${AWS_C_COMMON_SOURCE_URL} + URL_HASH "SHA256=${ARROW_AWS_C_COMMON_BUILD_SHA256_CHECKSUM}" + CMAKE_ARGS ${AWSSDK_COMMON_CMAKE_ARGS} + BUILD_BYPRODUCTS ${AWS_C_COMMON_STATIC_LIBRARY}) + add_dependencies(AWS::aws-c-common aws_c_common_ep) + + externalproject_add(aws_checksums_ep + ${EP_LOG_OPTIONS} + URL ${AWS_CHECKSUMS_SOURCE_URL} + URL_HASH "SHA256=${ARROW_AWS_CHECKSUMS_BUILD_SHA256_CHECKSUM}" + CMAKE_ARGS ${AWSSDK_COMMON_CMAKE_ARGS} + BUILD_BYPRODUCTS ${AWS_CHECKSUMS_STATIC_LIBRARY} + DEPENDS aws_c_common_ep) + add_dependencies(AWS::aws-checksums aws_checksums_ep) + + externalproject_add(aws_c_event_stream_ep + ${EP_LOG_OPTIONS} + URL ${AWS_C_EVENT_STREAM_SOURCE_URL} + URL_HASH "SHA256=${ARROW_AWS_C_EVENT_STREAM_BUILD_SHA256_CHECKSUM}" + CMAKE_ARGS ${AWSSDK_COMMON_CMAKE_ARGS} + BUILD_BYPRODUCTS ${AWS_C_EVENT_STREAM_STATIC_LIBRARY} + DEPENDS aws_checksums_ep) + add_dependencies(AWS::aws-c-event-stream aws_c_event_stream_ep) + + set(AWSSDK_PATCH_COMMAND) + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER + "10") + # Workaround for https://github.com/aws/aws-sdk-cpp/issues/1750 + set(AWSSDK_PATCH_COMMAND "sed" "-i.bak" "-e" "s/\"-Werror\"//g" + "<SOURCE_DIR>/cmake/compiler_settings.cmake") + endif() + externalproject_add(awssdk_ep + ${EP_LOG_OPTIONS} + URL ${AWSSDK_SOURCE_URL} + URL_HASH "SHA256=${ARROW_AWSSDK_BUILD_SHA256_CHECKSUM}" + CMAKE_ARGS ${AWSSDK_CMAKE_ARGS} + PATCH_COMMAND ${AWSSDK_PATCH_COMMAND} + BUILD_BYPRODUCTS ${AWS_CPP_SDK_COGNITO_IDENTITY_STATIC_LIBRARY} + ${AWS_CPP_SDK_CORE_STATIC_LIBRARY} + ${AWS_CPP_SDK_IDENTITY_MANAGEMENT_STATIC_LIBRARY} + ${AWS_CPP_SDK_S3_STATIC_LIBRARY} + ${AWS_CPP_SDK_STS_STATIC_LIBRARY} + DEPENDS aws_c_event_stream_ep) + add_dependencies(toolchain awssdk_ep) + foreach(_AWSSDK_LIB ${_AWSSDK_LIBS}) + if(${_AWSSDK_LIB} MATCHES "^aws-cpp-sdk-") + add_dependencies(${_AWSSDK_LIB} awssdk_ep) + endif() + endforeach() + + set(AWSSDK_VENDORED TRUE) + list(APPEND ARROW_BUNDLED_STATIC_LIBS ${AWSSDK_LIBRARIES}) + set(AWSSDK_LINK_LIBRARIES ${AWSSDK_LIBRARIES}) + if(UNIX) + # on Linux and macOS curl seems to be required + find_package(CURL REQUIRED) + if(NOT TARGET CURL::libcurl) + # For CMake 3.11 or older + add_library(CURL::libcurl UNKNOWN IMPORTED) + set_target_properties(CURL::libcurl + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${CURL_INCLUDE_DIRS}" IMPORTED_LOCATION + "${CURL_LIBRARIES}") + endif() + set_property(TARGET aws-cpp-sdk-core + APPEND + PROPERTY INTERFACE_LINK_LIBRARIES CURL::libcurl) + set_property(TARGET CURL::libcurl + APPEND + PROPERTY INTERFACE_LINK_LIBRARIES OpenSSL::SSL) + if(TARGET zlib_ep) + set_property(TARGET aws-cpp-sdk-core + APPEND + PROPERTY INTERFACE_LINK_LIBRARIES ZLIB::ZLIB) + add_dependencies(awssdk_ep zlib_ep) + endif() + endif() + + # AWSSDK is static-only build +endmacro() + +if(ARROW_S3) + # See https://aws.amazon.com/blogs/developer/developer-experience-of-the-aws-sdk-for-c-now-simplified-by-cmake/ + + # Workaround to force AWS CMake configuration to look for shared libraries + if(DEFINED ENV{CONDA_PREFIX}) + if(DEFINED BUILD_SHARED_LIBS) + set(BUILD_SHARED_LIBS_WAS_SET TRUE) + set(BUILD_SHARED_LIBS_VALUE ${BUILD_SHARED_LIBS}) + else() + set(BUILD_SHARED_LIBS_WAS_SET FALSE) + endif() + set(BUILD_SHARED_LIBS "ON") + endif() + + # Need to customize the find_package() call, so cannot call resolve_dependency() + if(AWSSDK_SOURCE STREQUAL "AUTO") + find_package(AWSSDK + COMPONENTS config + s3 + transfer + identity-management + sts) + if(NOT AWSSDK_FOUND) + build_awssdk() + endif() + elseif(AWSSDK_SOURCE STREQUAL "BUNDLED") + build_awssdk() + elseif(AWSSDK_SOURCE STREQUAL "SYSTEM") + find_package(AWSSDK REQUIRED + COMPONENTS config + s3 + transfer + identity-management + sts) + endif() + + # Restore previous value of BUILD_SHARED_LIBS + if(DEFINED ENV{CONDA_PREFIX}) + if(BUILD_SHARED_LIBS_WAS_SET) + set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_VALUE}) + else() + unset(BUILD_SHARED_LIBS) + endif() + endif() + + include_directories(SYSTEM ${AWSSDK_INCLUDE_DIR}) + message(STATUS "Found AWS SDK headers: ${AWSSDK_INCLUDE_DIR}") + message(STATUS "Found AWS SDK libraries: ${AWSSDK_LINK_LIBRARIES}") + + if(APPLE) + # CoreFoundation's path is hardcoded in the CMake files provided by + # aws-sdk-cpp to use the MacOSX SDK provided by XCode which makes + # XCode a hard dependency. Command Line Tools is often used instead + # of the full XCode suite, so let the linker to find it. + set_target_properties(AWS::aws-c-common + PROPERTIES INTERFACE_LINK_LIBRARIES + "-pthread;pthread;-framework CoreFoundation") + endif() +endif() + +message(STATUS "All bundled static libraries: ${ARROW_BUNDLED_STATIC_LIBS}") + +# Write out the package configurations. + +configure_file("src/arrow/util/config.h.cmake" "src/arrow/util/config.h" ESCAPE_QUOTES) +install(FILES "${ARROW_BINARY_DIR}/src/arrow/util/config.h" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/arrow/util") diff --git a/src/arrow/cpp/cmake_modules/UseCython.cmake b/src/arrow/cpp/cmake_modules/UseCython.cmake new file mode 100644 index 000000000..f2025efb4 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/UseCython.cmake @@ -0,0 +1,187 @@ +# Define a function to create Cython modules. +# +# For more information on the Cython project, see http://cython.org/. +# "Cython is a language that makes writing C extensions for the Python language +# as easy as Python itself." +# +# This file defines a CMake function to build a Cython Python module. +# To use it, first include this file. +# +# include( UseCython ) +# +# Then call cython_add_module to create a module. +# +# cython_add_module( <target_name> <pyx_target_name> <output_files> <src1> <src2> ... <srcN> ) +# +# Where <module_name> is the desired name of the target for the resulting Python module, +# <pyx_target_name> is the desired name of the target that runs the Cython compiler +# to generate the needed C or C++ files, <output_files> is a variable to hold the +# files generated by Cython, and <src1> <src2> ... are source files +# to be compiled into the module, e.g. *.pyx, *.c, *.cxx, etc. +# only one .pyx file may be present for each target +# (this is an inherent limitation of Cython). +# +# The sample paths set with the CMake include_directories() command will be used +# for include directories to search for *.pxd when running the Cython compiler. +# +# Cache variables that effect the behavior include: +# +# CYTHON_ANNOTATE +# CYTHON_NO_DOCSTRINGS +# CYTHON_FLAGS +# +# Source file properties that effect the build process are +# +# CYTHON_IS_CXX +# CYTHON_IS_PUBLIC +# CYTHON_IS_API +# +# If this is set of a *.pyx file with CMake set_source_files_properties() +# command, the file will be compiled as a C++ file. +# +# See also FindCython.cmake + +#============================================================================= +# Copyright 2011 Kitware, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= + +# Configuration options. +set(CYTHON_ANNOTATE OFF CACHE BOOL "Create an annotated .html file when compiling *.pyx.") +set(CYTHON_NO_DOCSTRINGS OFF CACHE BOOL "Strip docstrings from the compiled module.") +set(CYTHON_FLAGS "" CACHE STRING "Extra flags to the cython compiler.") +mark_as_advanced(CYTHON_ANNOTATE CYTHON_NO_DOCSTRINGS CYTHON_FLAGS) + +find_package(Python3Alt REQUIRED) + +# (using another C++ extension breaks coverage) +set(CYTHON_CXX_EXTENSION "cpp") +set(CYTHON_C_EXTENSION "c") + +# Create a *.c or *.cpp file from a *.pyx file. +# Input the generated file basename. The generate files will put into the variable +# placed in the "generated_files" argument. Finally all the *.py and *.pyx files. +function(compile_pyx + _name + pyx_target_name + generated_files + pyx_file) + # Default to assuming all files are C. + set(cxx_arg "") + set(extension ${CYTHON_C_EXTENSION}) + set(pyx_lang "C") + set(comment "Compiling Cython C source for ${_name}...") + + get_filename_component(pyx_file_basename "${pyx_file}" NAME_WE) + + # Determine if it is a C or C++ file. + get_source_file_property(property_is_cxx ${pyx_file} CYTHON_IS_CXX) + if(${property_is_cxx}) + set(cxx_arg "--cplus") + set(extension ${CYTHON_CXX_EXTENSION}) + set(pyx_lang "CXX") + set(comment "Compiling Cython CXX source for ${_name}...") + endif() + get_source_file_property(pyx_location ${pyx_file} LOCATION) + + set(output_file "${_name}.${extension}") + + # Set additional flags. + if(CYTHON_ANNOTATE) + set(annotate_arg "--annotate") + endif() + + if(CYTHON_NO_DOCSTRINGS) + set(no_docstrings_arg "--no-docstrings") + endif() + + if(NOT WIN32) + string( TOLOWER "${CMAKE_BUILD_TYPE}" build_type ) + if("${build_type}" STREQUAL "debug" + OR "${build_type}" STREQUAL "relwithdebinfo") + set(cython_debug_arg "--gdb") + endif() + endif() + + # Determining generated file names. + get_source_file_property(property_is_public ${pyx_file} CYTHON_PUBLIC) + get_source_file_property(property_is_api ${pyx_file} CYTHON_API) + if(${property_is_api}) + set(_generated_files "${output_file}" "${_name}.h" "${name}_api.h") + elseif(${property_is_public}) + set(_generated_files "${output_file}" "${_name}.h") + else() + set(_generated_files "${output_file}") + endif() + set_source_files_properties(${_generated_files} PROPERTIES GENERATED TRUE) + + if(NOT WIN32) + # Cython creates a lot of compiler warning detritus on clang + set_source_files_properties(${_generated_files} PROPERTIES COMPILE_FLAGS + -Wno-unused-function) + endif() + + set(${generated_files} ${_generated_files} PARENT_SCOPE) + + # Add the command to run the compiler. + add_custom_target( + ${pyx_target_name} + COMMAND ${PYTHON_EXECUTABLE} + -m + cython + ${cxx_arg} + ${annotate_arg} + ${no_docstrings_arg} + ${cython_debug_arg} + ${CYTHON_FLAGS} + # Necessary for autodoc of function arguments + --directive embedsignature=True + # Necessary for Cython code coverage + --working + ${CMAKE_CURRENT_SOURCE_DIR} + --output-file + "${CMAKE_CURRENT_BINARY_DIR}/${output_file}" + "${CMAKE_CURRENT_SOURCE_DIR}/${pyx_file}" + DEPENDS ${pyx_location} + # Do not specify byproducts for now since they don't work with the older + # version of cmake available in the apt repositories. + #BYPRODUCTS ${_generated_files} + COMMENT ${comment}) + + # Remove their visibility to the user. + set(corresponding_pxd_file "" CACHE INTERNAL "") + set(header_location "" CACHE INTERNAL "") + set(pxd_location "" CACHE INTERNAL "") +endfunction() + +# cython_add_module( <name> src1 src2 ... srcN ) +# Build the Cython Python module. +function(cython_add_module _name pyx_target_name generated_files) + set(pyx_module_source "") + set(other_module_sources "") + foreach(_file ${ARGN}) + if(${_file} MATCHES ".*\\.py[x]?$") + list(APPEND pyx_module_source ${_file}) + else() + list(APPEND other_module_sources ${_file}) + endif() + endforeach() + compile_pyx(${_name} ${pyx_target_name} _generated_files ${pyx_module_source}) + set(${generated_files} ${_generated_files} PARENT_SCOPE) + include_directories(${PYTHON_INCLUDE_DIRS}) + python_add_module(${_name} ${_generated_files} ${other_module_sources}) + add_dependencies(${_name} ${pyx_target_name}) +endfunction() + +include(CMakeParseArguments) diff --git a/src/arrow/cpp/cmake_modules/Usevcpkg.cmake b/src/arrow/cpp/cmake_modules/Usevcpkg.cmake new file mode 100644 index 000000000..06ac4dd07 --- /dev/null +++ b/src/arrow/cpp/cmake_modules/Usevcpkg.cmake @@ -0,0 +1,249 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +message(STATUS "Using vcpkg to find dependencies") + +# ---------------------------------------------------------------------- +# Define macros + +# macro to list subdirectirectories (non-recursive) +macro(list_subdirs SUBDIRS DIR) + file(GLOB children_ + RELATIVE ${DIR} + ${DIR}/*) + set(subdirs_ "") + foreach(child_ ${children_}) + if(IS_DIRECTORY "${DIR}/${child_}") + list(APPEND subdirs_ ${child_}) + endif() + endforeach() + set("${SUBDIRS}" ${subdirs_}) + unset(children_) + unset(subdirs_) +endmacro() + +# ---------------------------------------------------------------------- +# Get VCPKG_ROOT + +if(DEFINED CMAKE_TOOLCHAIN_FILE) + # Get it from the CMake variable CMAKE_TOOLCHAIN_FILE + get_filename_component(_VCPKG_DOT_CMAKE "${CMAKE_TOOLCHAIN_FILE}" NAME) + if(EXISTS "${CMAKE_TOOLCHAIN_FILE}" AND _VCPKG_DOT_CMAKE STREQUAL "vcpkg.cmake") + get_filename_component(_VCPKG_BUILDSYSTEMS_DIR "${CMAKE_TOOLCHAIN_FILE}" DIRECTORY) + get_filename_component(VCPKG_ROOT "${_VCPKG_BUILDSYSTEMS_DIR}/../.." ABSOLUTE) + else() + message(FATAL_ERROR "vcpkg toolchain file not found at path specified in -DCMAKE_TOOLCHAIN_FILE" + ) + endif() +else() + if(DEFINED VCPKG_ROOT) + # Get it from the CMake variable VCPKG_ROOT + find_program(_VCPKG_BIN vcpkg + PATHS "${VCPKG_ROOT}" + NO_DEFAULT_PATH) + if(NOT _VCPKG_BIN) + message(FATAL_ERROR "vcpkg not found in directory specified in -DVCPKG_ROOT") + endif() + elseif(DEFINED ENV{VCPKG_ROOT}) + # Get it from the environment variable VCPKG_ROOT + set(VCPKG_ROOT $ENV{VCPKG_ROOT}) + find_program(_VCPKG_BIN vcpkg + PATHS "${VCPKG_ROOT}" + NO_DEFAULT_PATH) + if(NOT _VCPKG_BIN) + message(FATAL_ERROR "vcpkg not found in directory in environment variable VCPKG_ROOT" + ) + endif() + else() + # Get it from the file vcpkg.path.txt + find_program(_VCPKG_BIN vcpkg) + if(_VCPKG_BIN) + get_filename_component(_VCPKG_REAL_BIN "${_VCPKG_BIN}" REALPATH) + get_filename_component(VCPKG_ROOT "${_VCPKG_REAL_BIN}" DIRECTORY) + else() + if(CMAKE_HOST_WIN32) + set(_VCPKG_PATH_TXT "$ENV{LOCALAPPDATA}/vcpkg/vcpkg.path.txt") + else() + set(_VCPKG_PATH_TXT "$ENV{HOME}/.vcpkg/vcpkg.path.txt") + endif() + if(EXISTS "${_VCPKG_PATH_TXT}") + file(READ "${_VCPKG_PATH_TXT}" VCPKG_ROOT) + else() + message(FATAL_ERROR "vcpkg not found. Install vcpkg if not installed, " + "then run vcpkg integrate install or set environment variable VCPKG_ROOT." + ) + endif() + find_program(_VCPKG_BIN vcpkg + PATHS "${VCPKG_ROOT}" + NO_DEFAULT_PATH) + if(NOT _VCPKG_BIN) + message(FATAL_ERROR "vcpkg not found. Re-run vcpkg integrate install " + "or set environment variable VCPKG_ROOT.") + endif() + endif() + endif() + set(CMAKE_TOOLCHAIN_FILE + "${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + CACHE FILEPATH "Path to vcpkg CMake toolchain file") +endif() +message(STATUS "Using CMAKE_TOOLCHAIN_FILE: ${CMAKE_TOOLCHAIN_FILE}") +message(STATUS "Using VCPKG_ROOT: ${VCPKG_ROOT}") + +# ---------------------------------------------------------------------- +# Get VCPKG_TARGET_TRIPLET + +if(DEFINED ENV{VCPKG_DEFAULT_TRIPLET} AND NOT DEFINED VCPKG_TARGET_TRIPLET) + set(VCPKG_TARGET_TRIPLET "$ENV{VCPKG_DEFAULT_TRIPLET}") +endif() +# Explicitly set manifest mode on if it is not set and vcpkg.json exists +if(NOT DEFINED VCPKG_MANIFEST_MODE AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg.json") + set(VCPKG_MANIFEST_MODE + ON + CACHE BOOL "Use vcpkg.json manifest") + message(STATUS "vcpkg.json manifest found. Using VCPKG_MANIFEST_MODE: ON") +endif() +# vcpkg can install packages in three different places +set(_INST_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/vcpkg_installed") # try here first +set(_INST_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg_installed") # try here second +set(_INST_VCPKG_ROOT "${VCPKG_ROOT}/installed") +# Iterate over the places +foreach(_INST_DIR IN LISTS _INST_BUILD_DIR _INST_SOURCE_DIR _INST_VCPKG_ROOT "notfound") + if(_INST_DIR STREQUAL "notfound") + message(FATAL_ERROR "vcpkg installed libraries directory not found. " + "Install packages with vcpkg before executing cmake.") + elseif(NOT EXISTS "${_INST_DIR}") + continue() + elseif((_INST_DIR STREQUAL _INST_BUILD_DIR OR _INST_DIR STREQUAL _INST_SOURCE_DIR) + AND NOT VCPKG_MANIFEST_MODE) + # Do not look for packages in the build or source dirs if manifest mode is off + message(STATUS "Skipped looking for installed packages in ${_INST_DIR} " + "because -DVCPKG_MANIFEST_MODE=OFF") + continue() + else() + message(STATUS "Looking for installed packages in ${_INST_DIR}") + endif() + if(DEFINED VCPKG_TARGET_TRIPLET) + # Check if a subdirectory named VCPKG_TARGET_TRIPLET + # exists in the vcpkg installed directory + if(EXISTS "${_INST_DIR}/${VCPKG_TARGET_TRIPLET}") + set(_VCPKG_INSTALLED_DIR "${_INST_DIR}") + break() + endif() + else() + # Infer VCPKG_TARGET_TRIPLET from the name of the + # subdirectory in the vcpkg installed directory + list_subdirs(_VCPKG_TRIPLET_SUBDIRS "${_INST_DIR}") + list(REMOVE_ITEM _VCPKG_TRIPLET_SUBDIRS "vcpkg") + list(LENGTH _VCPKG_TRIPLET_SUBDIRS _NUM_VCPKG_TRIPLET_SUBDIRS) + if(_NUM_VCPKG_TRIPLET_SUBDIRS EQUAL 1) + list(GET _VCPKG_TRIPLET_SUBDIRS 0 VCPKG_TARGET_TRIPLET) + set(_VCPKG_INSTALLED_DIR "${_INST_DIR}") + break() + endif() + endif() +endforeach() +if(NOT DEFINED VCPKG_TARGET_TRIPLET) + message(FATAL_ERROR "Could not infer VCPKG_TARGET_TRIPLET. " + "Specify triplet with -DVCPKG_TARGET_TRIPLET.") +elseif(NOT DEFINED _VCPKG_INSTALLED_DIR) + message(FATAL_ERROR "Could not find installed vcpkg packages for triplet ${VCPKG_TARGET_TRIPLET}. " + "Install packages with vcpkg before executing cmake.") +endif() + +set(VCPKG_TARGET_TRIPLET + "${VCPKG_TARGET_TRIPLET}" + CACHE STRING "vcpkg triplet for the target environment") + +if(NOT DEFINED VCPKG_BUILD_TYPE) + set(VCPKG_BUILD_TYPE + "${LOWERCASE_BUILD_TYPE}" + CACHE STRING "vcpkg build type (release|debug)") +endif() + +if(NOT DEFINED VCPKG_LIBRARY_LINKAGE) + if(ARROW_DEPENDENCY_USE_SHARED) + set(VCPKG_LIBRARY_LINKAGE "dynamic") + else() + set(VCPKG_LIBRARY_LINKAGE "static") + endif() + set(VCPKG_LIBRARY_LINKAGE + "${VCPKG_LIBRARY_LINKAGE}" + CACHE STRING "vcpkg preferred library linkage (static|dynamic)") +endif() + +message(STATUS "Using vcpkg installed libraries directory: ${_VCPKG_INSTALLED_DIR}") +message(STATUS "Using VCPKG_TARGET_TRIPLET: ${VCPKG_TARGET_TRIPLET}") +message(STATUS "Using VCPKG_BUILD_TYPE: ${VCPKG_BUILD_TYPE}") +message(STATUS "Using VCPKG_LIBRARY_LINKAGE: ${VCPKG_LIBRARY_LINKAGE}") + +set(ARROW_VCPKG_PREFIX + "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}" + CACHE PATH "Path to target triplet subdirectory in vcpkg installed directory") + +set(ARROW_VCPKG + ON + CACHE BOOL "Use vcpkg for dependencies") + +set(ARROW_DEPENDENCY_SOURCE + "SYSTEM" + CACHE STRING "The specified value VCPKG is implemented internally as SYSTEM" FORCE) + +set(BOOST_ROOT + "${ARROW_VCPKG_PREFIX}" + CACHE STRING "") +set(BOOST_INCLUDEDIR + "${ARROW_VCPKG_PREFIX}/include/boost" + CACHE STRING "") +set(BOOST_LIBRARYDIR + "${ARROW_VCPKG_PREFIX}/lib" + CACHE STRING "") +set(OPENSSL_INCLUDE_DIR + "${ARROW_VCPKG_PREFIX}/include" + CACHE STRING "") +set(OPENSSL_LIBRARIES + "${ARROW_VCPKG_PREFIX}/lib" + CACHE STRING "") +set(OPENSSL_ROOT_DIR + "${ARROW_VCPKG_PREFIX}" + CACHE STRING "") +set(Thrift_ROOT + "${ARROW_VCPKG_PREFIX}/lib" + CACHE STRING "") +set(ZSTD_INCLUDE_DIR + "${ARROW_VCPKG_PREFIX}/include" + CACHE STRING "") +set(ZSTD_ROOT + "${ARROW_VCPKG_PREFIX}" + CACHE STRING "") +set(BROTLI_ROOT + "${ARROW_VCPKG_PREFIX}" + CACHE STRING "") +set(LZ4_ROOT + "${ARROW_VCPKG_PREFIX}" + CACHE STRING "") + +if(CMAKE_HOST_WIN32) + set(LZ4_MSVC_LIB_PREFIX + "" + CACHE STRING "") + set(LZ4_MSVC_STATIC_LIB_SUFFIX + "" + CACHE STRING "") + set(ZSTD_MSVC_LIB_PREFIX + "" + CACHE STRING "") +endif() diff --git a/src/arrow/cpp/cmake_modules/san-config.cmake b/src/arrow/cpp/cmake_modules/san-config.cmake new file mode 100644 index 000000000..bde9af23e --- /dev/null +++ b/src/arrow/cpp/cmake_modules/san-config.cmake @@ -0,0 +1,122 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. See accompanying LICENSE file. + +# Clang does not support using ASAN and TSAN simultaneously. +if("${ARROW_USE_ASAN}" AND "${ARROW_USE_TSAN}") + message(SEND_ERROR "Can only enable one of ASAN or TSAN at a time") +endif() + +# Flag to enable clang address sanitizer +# This will only build if clang or a recent enough gcc is the chosen compiler +if(${ARROW_USE_ASAN}) + if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" + OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" + OR (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION + VERSION_GREATER "4.8")) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -DADDRESS_SANITIZER") + else() + message(SEND_ERROR "Cannot use ASAN without clang or gcc >= 4.8") + endif() +endif() + +# Flag to enable clang undefined behavior sanitizer +# We explicitly don't enable all of the sanitizer flags: +# - disable 'vptr' because of RTTI issues across shared libraries (?) +# - disable 'alignment' because unaligned access is really OK on Nehalem and we do it +# all over the place. +# - disable 'function' because it appears to give a false positive +# (https://github.com/google/sanitizers/issues/911) +# - disable 'float-divide-by-zero' on clang, which considers it UB +# (https://bugs.llvm.org/show_bug.cgi?id=17000#c1) +# Note: GCC does not support the 'function' flag. +if(${ARROW_USE_UBSAN}) + if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL + "Clang") + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize=alignment,vptr,function,float-divide-by-zero -fno-sanitize-recover=all" + ) + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION + VERSION_GREATER_EQUAL "5.1") + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize=alignment,vptr -fno-sanitize-recover=all" + ) + else() + message(SEND_ERROR "Cannot use UBSAN without clang or gcc >= 5.1") + endif() +endif() + +# Flag to enable thread sanitizer (clang or gcc 4.8) +if(${ARROW_USE_TSAN}) + if(NOT + (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" + OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" + OR (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION + VERSION_GREATER "4.8"))) + message(SEND_ERROR "Cannot use TSAN without clang or gcc >= 4.8") + endif() + + add_definitions("-fsanitize=thread") + + # Enables dynamic_annotations.h to actually generate code + add_definitions("-DDYNAMIC_ANNOTATIONS_ENABLED") + + # changes atomicops to use the tsan implementations + add_definitions("-DTHREAD_SANITIZER") + + # Disables using the precompiled template specializations for std::string, shared_ptr, etc + # so that the annotations in the header actually take effect. + add_definitions("-D_GLIBCXX_EXTERN_TEMPLATE=0") + + # Some of the above also need to be passed to the linker. + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie -fsanitize=thread") + + # Strictly speaking, TSAN doesn't require dynamic linking. But it does + # require all code to be position independent, and the easiest way to + # guarantee that is via dynamic linking (not all 3rd party archives are + # compiled with -fPIC e.g. boost). + if("${ARROW_LINK}" STREQUAL "a") + message("Using dynamic linking for TSAN") + set(ARROW_LINK "d") + elseif("${ARROW_LINK}" STREQUAL "s") + message(SEND_ERROR "Cannot use TSAN with static linking") + endif() +endif() + +if(${ARROW_USE_COVERAGE}) + if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL + "Clang") + add_definitions("-fsanitize-coverage=pc-table,inline-8bit-counters,edge,no-prune,trace-cmp,trace-div,trace-gep" + ) + + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -fsanitize-coverage=pc-table,inline-8bit-counters,edge,no-prune,trace-cmp,trace-div,trace-gep" + ) + else() + message(SEND_ERROR "You can only enable coverage with clang") + endif() +endif() + +if("${ARROW_USE_UBSAN}" + OR "${ARROW_USE_ASAN}" + OR "${ARROW_USE_TSAN}") + # GCC 4.8 and 4.9 (latest as of this writing) don't allow you to specify + # disallowed entries for the sanitizer. + if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL + "Clang") + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -fsanitize-blacklist=${BUILD_SUPPORT_DIR}/sanitizer-disallowed-entries.txt" + ) + else() + message(WARNING "GCC does not support specifying a sanitizer disallowed entries list. Known sanitizer check failures will not be suppressed." + ) + endif() +endif() |