# 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()