1# Licensed to the Apache Software Foundation (ASF) under one 2# or more contributor license agreements. See the NOTICE file 3# distributed with this work for additional information 4# regarding copyright ownership. The ASF licenses this file 5# to you under the Apache License, Version 2.0 (the 6# "License"); you may not use this file except in compliance 7# with the License. You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, 12# software distributed under the License is distributed on an 13# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14# KIND, either express or implied. See the License for the 15# specific language governing permissions and limitations 16# under the License. 17 18# - Find Arrow (arrow/api.h, libarrow.a, libarrow.so) 19# This module defines 20# ARROW_FOUND, whether Arrow has been found 21# ARROW_FULL_SO_VERSION, full shared object version of found Arrow "100.0.0" 22# ARROW_IMPORT_LIB, path to libarrow's import library (Windows only) 23# ARROW_INCLUDE_DIR, directory containing headers 24# ARROW_LIBS, deprecated. Use ARROW_LIB_DIR instead 25# ARROW_LIB_DIR, directory containing Arrow libraries 26# ARROW_SHARED_IMP_LIB, deprecated. Use ARROW_IMPORT_LIB instead 27# ARROW_SHARED_LIB, path to libarrow's shared library 28# ARROW_SO_VERSION, shared object version of found Arrow such as "100" 29# ARROW_STATIC_LIB, path to libarrow.a 30# ARROW_VERSION, version of found Arrow 31# ARROW_VERSION_MAJOR, major version of found Arrow 32# ARROW_VERSION_MINOR, minor version of found Arrow 33# ARROW_VERSION_PATCH, patch version of found Arrow 34 35if(DEFINED ARROW_FOUND) 36 return() 37endif() 38 39include(FindPkgConfig) 40include(FindPackageHandleStandardArgs) 41 42if(WIN32 AND NOT MINGW) 43 # This is used to handle builds using e.g. clang in an MSVC setting. 44 set(MSVC_TOOLCHAIN TRUE) 45else() 46 set(MSVC_TOOLCHAIN FALSE) 47endif() 48 49set(ARROW_SEARCH_LIB_PATH_SUFFIXES) 50if(CMAKE_LIBRARY_ARCHITECTURE) 51 list(APPEND ARROW_SEARCH_LIB_PATH_SUFFIXES "lib/${CMAKE_LIBRARY_ARCHITECTURE}") 52endif() 53list(APPEND 54 ARROW_SEARCH_LIB_PATH_SUFFIXES 55 "lib64" 56 "lib32" 57 "lib" 58 "bin") 59set(ARROW_CONFIG_SUFFIXES 60 "_RELEASE" 61 "_RELWITHDEBINFO" 62 "_MINSIZEREL" 63 "_DEBUG" 64 "") 65if(CMAKE_BUILD_TYPE) 66 string(TOUPPER ${CMAKE_BUILD_TYPE} ARROW_CONFIG_SUFFIX_PREFERRED) 67 set(ARROW_CONFIG_SUFFIX_PREFERRED "_${ARROW_CONFIG_SUFFIX_PREFERRED}") 68 list(INSERT ARROW_CONFIG_SUFFIXES 0 "${ARROW_CONFIG_SUFFIX_PREFERRED}") 69endif() 70 71if(NOT DEFINED ARROW_MSVC_STATIC_LIB_SUFFIX) 72 if(MSVC_TOOLCHAIN) 73 set(ARROW_MSVC_STATIC_LIB_SUFFIX "_static") 74 else() 75 set(ARROW_MSVC_STATIC_LIB_SUFFIX "") 76 endif() 77endif() 78 79# Internal function. 80# 81# Set shared library name for ${base_name} to ${output_variable}. 82# 83# Example: 84# arrow_build_shared_library_name(ARROW_SHARED_LIBRARY_NAME arrow) 85# # -> ARROW_SHARED_LIBRARY_NAME=libarrow.so on Linux 86# # -> ARROW_SHARED_LIBRARY_NAME=libarrow.dylib on macOS 87# # -> ARROW_SHARED_LIBRARY_NAME=arrow.dll with MSVC on Windows 88# # -> ARROW_SHARED_LIBRARY_NAME=libarrow.dll with MinGW on Windows 89function(arrow_build_shared_library_name output_variable base_name) 90 set(${output_variable} 91 "${CMAKE_SHARED_LIBRARY_PREFIX}${base_name}${CMAKE_SHARED_LIBRARY_SUFFIX}" 92 PARENT_SCOPE) 93endfunction() 94 95# Internal function. 96# 97# Set import library name for ${base_name} to ${output_variable}. 98# This is useful only for MSVC build. Import library is used only 99# with MSVC build. 100# 101# Example: 102# arrow_build_import_library_name(ARROW_IMPORT_LIBRARY_NAME arrow) 103# # -> ARROW_IMPORT_LIBRARY_NAME=arrow on Linux (meaningless) 104# # -> ARROW_IMPORT_LIBRARY_NAME=arrow on macOS (meaningless) 105# # -> ARROW_IMPORT_LIBRARY_NAME=arrow.lib with MSVC on Windows 106# # -> ARROW_IMPORT_LIBRARY_NAME=libarrow.dll.a with MinGW on Windows 107function(arrow_build_import_library_name output_variable base_name) 108 set(${output_variable} 109 "${CMAKE_IMPORT_LIBRARY_PREFIX}${base_name}${CMAKE_IMPORT_LIBRARY_SUFFIX}" 110 PARENT_SCOPE) 111endfunction() 112 113# Internal function. 114# 115# Set static library name for ${base_name} to ${output_variable}. 116# 117# Example: 118# arrow_build_static_library_name(ARROW_STATIC_LIBRARY_NAME arrow) 119# # -> ARROW_STATIC_LIBRARY_NAME=libarrow.a on Linux 120# # -> ARROW_STATIC_LIBRARY_NAME=libarrow.a on macOS 121# # -> ARROW_STATIC_LIBRARY_NAME=arrow.lib with MSVC on Windows 122# # -> ARROW_STATIC_LIBRARY_NAME=libarrow.dll.a with MinGW on Windows 123function(arrow_build_static_library_name output_variable base_name) 124 set(${output_variable} 125 "${CMAKE_STATIC_LIBRARY_PREFIX}${base_name}${ARROW_MSVC_STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}" 126 PARENT_SCOPE) 127endfunction() 128 129# Internal function. 130# 131# Set macro value for ${macro_name} in ${header_content} to ${output_variable}. 132# 133# Example: 134# arrow_extract_macro_value(version_major 135# "ARROW_VERSION_MAJOR" 136# "#define ARROW_VERSION_MAJOR 1.0.0") 137# # -> version_major=1.0.0 138function(arrow_extract_macro_value output_variable macro_name header_content) 139 string(REGEX MATCH "#define +${macro_name} +[^\r\n]+" macro_definition 140 "${header_content}") 141 string(REGEX REPLACE "^#define +${macro_name} +(.+)$" "\\1" macro_value 142 "${macro_definition}") 143 set(${output_variable} 144 "${macro_value}" 145 PARENT_SCOPE) 146endfunction() 147 148# Internal macro only for arrow_find_package. 149# 150# Find package in HOME. 151macro(arrow_find_package_home) 152 find_path(${prefix}_include_dir "${header_path}" 153 PATHS "${home}" 154 PATH_SUFFIXES "include" 155 NO_DEFAULT_PATH) 156 set(include_dir "${${prefix}_include_dir}") 157 set(${prefix}_INCLUDE_DIR 158 "${include_dir}" 159 PARENT_SCOPE) 160 161 if(MSVC_TOOLCHAIN) 162 set(CMAKE_SHARED_LIBRARY_SUFFIXES_ORIGINAL ${CMAKE_FIND_LIBRARY_SUFFIXES}) 163 # .dll isn't found by find_library with MSVC because .dll isn't included in 164 # CMAKE_FIND_LIBRARY_SUFFIXES. 165 list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_SHARED_LIBRARY_SUFFIX}") 166 endif() 167 find_library(${prefix}_shared_lib 168 NAMES "${shared_lib_name}" 169 PATHS "${home}" 170 PATH_SUFFIXES ${ARROW_SEARCH_LIB_PATH_SUFFIXES} 171 NO_DEFAULT_PATH) 172 if(MSVC_TOOLCHAIN) 173 set(CMAKE_SHARED_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_ORIGINAL}) 174 endif() 175 set(shared_lib "${${prefix}_shared_lib}") 176 set(${prefix}_SHARED_LIB 177 "${shared_lib}" 178 PARENT_SCOPE) 179 if(shared_lib) 180 add_library(${target_shared} SHARED IMPORTED) 181 set_target_properties(${target_shared} PROPERTIES IMPORTED_LOCATION "${shared_lib}") 182 if(include_dir) 183 set_target_properties(${target_shared} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES 184 "${include_dir}") 185 endif() 186 find_library(${prefix}_import_lib 187 NAMES "${import_lib_name}" 188 PATHS "${home}" 189 PATH_SUFFIXES ${ARROW_SEARCH_LIB_PATH_SUFFIXES} 190 NO_DEFAULT_PATH) 191 set(import_lib "${${prefix}_import_lib}") 192 set(${prefix}_IMPORT_LIB 193 "${import_lib}" 194 PARENT_SCOPE) 195 if(import_lib) 196 set_target_properties(${target_shared} PROPERTIES IMPORTED_IMPLIB "${import_lib}") 197 endif() 198 endif() 199 200 find_library(${prefix}_static_lib 201 NAMES "${static_lib_name}" 202 PATHS "${home}" 203 PATH_SUFFIXES ${ARROW_SEARCH_LIB_PATH_SUFFIXES} 204 NO_DEFAULT_PATH) 205 set(static_lib "${${prefix}_static_lib}") 206 set(${prefix}_STATIC_LIB 207 "${static_lib}" 208 PARENT_SCOPE) 209 if(static_lib) 210 add_library(${target_static} STATIC IMPORTED) 211 set_target_properties(${target_static} PROPERTIES IMPORTED_LOCATION "${static_lib}") 212 if(include_dir) 213 set_target_properties(${target_static} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES 214 "${include_dir}") 215 endif() 216 endif() 217endmacro() 218 219# Internal macro only for arrow_find_package. 220# 221# Find package by CMake package configuration. 222macro(arrow_find_package_cmake_package_configuration) 223 find_package(${cmake_package_name} CONFIG) 224 if(${cmake_package_name}_FOUND) 225 set(${prefix}_USE_CMAKE_PACKAGE_CONFIG 226 TRUE 227 PARENT_SCOPE) 228 if(TARGET ${target_shared}) 229 foreach(suffix ${ARROW_CONFIG_SUFFIXES}) 230 get_target_property(shared_lib ${target_shared} IMPORTED_LOCATION${suffix}) 231 if(shared_lib) 232 # Remove shared library version: 233 # libarrow.so.100.0.0 -> libarrow.so 234 # Because ARROW_HOME and pkg-config approaches don't add 235 # shared library version. 236 string(REGEX REPLACE "(${CMAKE_SHARED_LIBRARY_SUFFIX})[.0-9]+$" "\\1" 237 shared_lib "${shared_lib}") 238 set(${prefix}_SHARED_LIB 239 "${shared_lib}" 240 PARENT_SCOPE) 241 break() 242 endif() 243 endforeach() 244 endif() 245 if(TARGET ${target_static}) 246 foreach(suffix ${ARROW_CONFIG_SUFFIXES}) 247 get_target_property(static_lib ${target_static} IMPORTED_LOCATION${suffix}) 248 if(static_lib) 249 set(${prefix}_STATIC_LIB 250 "${static_lib}" 251 PARENT_SCOPE) 252 break() 253 endif() 254 endforeach() 255 endif() 256 endif() 257endmacro() 258 259# Internal macro only for arrow_find_package. 260# 261# Find package by pkg-config. 262macro(arrow_find_package_pkg_config) 263 pkg_check_modules(${prefix}_PC ${pkg_config_name}) 264 if(${prefix}_PC_FOUND) 265 set(${prefix}_USE_PKG_CONFIG 266 TRUE 267 PARENT_SCOPE) 268 269 set(include_dir "${${prefix}_PC_INCLUDEDIR}") 270 set(lib_dir "${${prefix}_PC_LIBDIR}") 271 set(shared_lib_paths "${${prefix}_PC_LINK_LIBRARIES}") 272 # Use the first shared library path as the IMPORTED_LOCATION 273 # for ${target_shared}. This assumes that the first shared library 274 # path is the shared library path for this module. 275 list(GET shared_lib_paths 0 first_shared_lib_path) 276 # Use the rest shared library paths as the INTERFACE_LINK_LIBRARIES 277 # for ${target_shared}. This assumes that the rest shared library 278 # paths are dependency library paths for this module. 279 list(LENGTH shared_lib_paths n_shared_lib_paths) 280 if(n_shared_lib_paths LESS_EQUAL 1) 281 set(rest_shared_lib_paths) 282 else() 283 list(SUBLIST 284 shared_lib_paths 285 1 286 -1 287 rest_shared_lib_paths) 288 endif() 289 290 set(${prefix}_VERSION 291 "${${prefix}_PC_VERSION}" 292 PARENT_SCOPE) 293 set(${prefix}_INCLUDE_DIR 294 "${include_dir}" 295 PARENT_SCOPE) 296 set(${prefix}_SHARED_LIB 297 "${first_shared_lib_path}" 298 PARENT_SCOPE) 299 300 add_library(${target_shared} SHARED IMPORTED) 301 set_target_properties(${target_shared} 302 PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${include_dir}" 303 INTERFACE_LINK_LIBRARIES "${rest_shared_lib_paths}" 304 IMPORTED_LOCATION "${first_shared_lib_path}") 305 get_target_property(shared_lib ${target_shared} IMPORTED_LOCATION) 306 307 find_library(${prefix}_static_lib 308 NAMES "${static_lib_name}" 309 PATHS "${lib_dir}" 310 NO_DEFAULT_PATH) 311 set(static_lib "${${prefix}_static_lib}") 312 set(${prefix}_STATIC_LIB 313 "${static_lib}" 314 PARENT_SCOPE) 315 if(static_lib) 316 add_library(${target_static} STATIC IMPORTED) 317 set_target_properties(${target_static} 318 PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${include_dir}" 319 IMPORTED_LOCATION "${static_lib}") 320 endif() 321 endif() 322endmacro() 323 324function(arrow_find_package 325 prefix 326 home 327 base_name 328 header_path 329 cmake_package_name 330 pkg_config_name) 331 arrow_build_shared_library_name(shared_lib_name ${base_name}) 332 arrow_build_import_library_name(import_lib_name ${base_name}) 333 arrow_build_static_library_name(static_lib_name ${base_name}) 334 335 set(target_shared ${base_name}_shared) 336 set(target_static ${base_name}_static) 337 338 if(home) 339 arrow_find_package_home() 340 set(${prefix}_FIND_APPROACH 341 "HOME: ${home}" 342 PARENT_SCOPE) 343 else() 344 arrow_find_package_cmake_package_configuration() 345 if(${cmake_package_name}_FOUND) 346 set(${prefix}_FIND_APPROACH 347 "CMake package configuration: ${cmake_package_name}" 348 PARENT_SCOPE) 349 else() 350 arrow_find_package_pkg_config() 351 set(${prefix}_FIND_APPROACH 352 "pkg-config: ${pkg_config_name}" 353 PARENT_SCOPE) 354 endif() 355 endif() 356 357 if(NOT include_dir) 358 if(TARGET ${target_shared}) 359 get_target_property(include_dir ${target_shared} INTERFACE_INCLUDE_DIRECTORIES) 360 elseif(TARGET ${target_static}) 361 get_target_property(include_dir ${target_static} INTERFACE_INCLUDE_DIRECTORIES) 362 endif() 363 endif() 364 if(include_dir) 365 set(${prefix}_INCLUDE_DIR 366 "${include_dir}" 367 PARENT_SCOPE) 368 endif() 369 370 if(shared_lib) 371 get_filename_component(lib_dir "${shared_lib}" DIRECTORY) 372 elseif(static_lib) 373 get_filename_component(lib_dir "${static_lib}" DIRECTORY) 374 else() 375 set(lib_dir NOTFOUND) 376 endif() 377 set(${prefix}_LIB_DIR 378 "${lib_dir}" 379 PARENT_SCOPE) 380 # For backward compatibility 381 set(${prefix}_LIBS 382 "${lib_dir}" 383 PARENT_SCOPE) 384endfunction() 385 386if(NOT "$ENV{ARROW_HOME}" STREQUAL "") 387 file(TO_CMAKE_PATH "$ENV{ARROW_HOME}" ARROW_HOME) 388endif() 389arrow_find_package(ARROW 390 "${ARROW_HOME}" 391 arrow 392 arrow/api.h 393 Arrow 394 arrow) 395 396if(ARROW_HOME) 397 if(ARROW_INCLUDE_DIR) 398 file(READ "${ARROW_INCLUDE_DIR}/arrow/util/config.h" ARROW_CONFIG_H_CONTENT) 399 arrow_extract_macro_value(ARROW_VERSION_MAJOR "ARROW_VERSION_MAJOR" 400 "${ARROW_CONFIG_H_CONTENT}") 401 arrow_extract_macro_value(ARROW_VERSION_MINOR "ARROW_VERSION_MINOR" 402 "${ARROW_CONFIG_H_CONTENT}") 403 arrow_extract_macro_value(ARROW_VERSION_PATCH "ARROW_VERSION_PATCH" 404 "${ARROW_CONFIG_H_CONTENT}") 405 if("${ARROW_VERSION_MAJOR}" STREQUAL "" 406 OR "${ARROW_VERSION_MINOR}" STREQUAL "" 407 OR "${ARROW_VERSION_PATCH}" STREQUAL "") 408 set(ARROW_VERSION "0.0.0") 409 else() 410 set(ARROW_VERSION 411 "${ARROW_VERSION_MAJOR}.${ARROW_VERSION_MINOR}.${ARROW_VERSION_PATCH}") 412 endif() 413 414 arrow_extract_macro_value(ARROW_SO_VERSION_QUOTED "ARROW_SO_VERSION" 415 "${ARROW_CONFIG_H_CONTENT}") 416 string(REGEX REPLACE "^\"(.+)\"$" "\\1" ARROW_SO_VERSION "${ARROW_SO_VERSION_QUOTED}") 417 arrow_extract_macro_value(ARROW_FULL_SO_VERSION_QUOTED "ARROW_FULL_SO_VERSION" 418 "${ARROW_CONFIG_H_CONTENT}") 419 string(REGEX REPLACE "^\"(.+)\"$" "\\1" ARROW_FULL_SO_VERSION 420 "${ARROW_FULL_SO_VERSION_QUOTED}") 421 endif() 422else() 423 if(ARROW_USE_CMAKE_PACKAGE_CONFIG) 424 find_package(Arrow CONFIG) 425 elseif(ARROW_USE_PKG_CONFIG) 426 pkg_get_variable(ARROW_SO_VERSION arrow so_version) 427 pkg_get_variable(ARROW_FULL_SO_VERSION arrow full_so_version) 428 endif() 429endif() 430 431set(ARROW_ABI_VERSION ${ARROW_SO_VERSION}) 432 433mark_as_advanced(ARROW_ABI_VERSION 434 ARROW_CONFIG_SUFFIXES 435 ARROW_FULL_SO_VERSION 436 ARROW_IMPORT_LIB 437 ARROW_INCLUDE_DIR 438 ARROW_LIBS 439 ARROW_LIB_DIR 440 ARROW_SEARCH_LIB_PATH_SUFFIXES 441 ARROW_SHARED_IMP_LIB 442 ARROW_SHARED_LIB 443 ARROW_SO_VERSION 444 ARROW_STATIC_LIB 445 ARROW_VERSION 446 ARROW_VERSION_MAJOR 447 ARROW_VERSION_MINOR 448 ARROW_VERSION_PATCH) 449 450find_package_handle_standard_args( 451 Arrow 452 REQUIRED_VARS # The first required variable is shown 453 # in the found message. So this list is 454 # not sorted alphabetically. 455 ARROW_INCLUDE_DIR ARROW_LIB_DIR ARROW_FULL_SO_VERSION ARROW_SO_VERSION 456 VERSION_VAR ARROW_VERSION) 457set(ARROW_FOUND ${Arrow_FOUND}) 458 459if(Arrow_FOUND AND NOT Arrow_FIND_QUIETLY) 460 message(STATUS "Arrow version: ${ARROW_VERSION} (${ARROW_FIND_APPROACH})") 461 message(STATUS "Arrow SO and ABI version: ${ARROW_SO_VERSION}") 462 message(STATUS "Arrow full SO version: ${ARROW_FULL_SO_VERSION}") 463 message(STATUS "Found the Arrow core shared library: ${ARROW_SHARED_LIB}") 464 message(STATUS "Found the Arrow core import library: ${ARROW_IMPORT_LIB}") 465 message(STATUS "Found the Arrow core static library: ${ARROW_STATIC_LIB}") 466endif() 467