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
18include(ProcessorCount)
19processorcount(NPROC)
20
21add_custom_target(rapidjson)
22add_custom_target(toolchain)
23add_custom_target(toolchain-benchmarks)
24add_custom_target(toolchain-tests)
25
26# Accumulate all bundled targets and we will splice them together later as
27# libarrow_dependencies.a so that third party libraries have something usable
28# to create statically-linked builds with some BUNDLED dependencies, including
29# allocators like jemalloc and mimalloc
30set(ARROW_BUNDLED_STATIC_LIBS)
31
32# Accumulate all system dependencies to provide suitable static link
33# parameters to the third party libraries.
34set(ARROW_SYSTEM_DEPENDENCIES)
35
36# ----------------------------------------------------------------------
37# Toolchain linkage options
38
39set(ARROW_RE2_LINKAGE
40    "static"
41    CACHE STRING "How to link the re2 library. static|shared (default static)")
42
43if(ARROW_PROTOBUF_USE_SHARED)
44  set(Protobuf_USE_STATIC_LIBS OFF)
45else()
46  set(Protobuf_USE_STATIC_LIBS ON)
47endif()
48
49# ----------------------------------------------------------------------
50# Resolve the dependencies
51
52set(ARROW_THIRDPARTY_DEPENDENCIES
53    AWSSDK
54    benchmark
55    Boost
56    Brotli
57    BZip2
58    c-ares
59    gflags
60    GLOG
61    gRPC
62    GTest
63    LLVM
64    Lz4
65    ORC
66    re2
67    Protobuf
68    RapidJSON
69    Snappy
70    Thrift
71    utf8proc
72    ZLIB
73    zstd)
74
75# TODO(wesm): External GTest shared libraries are not currently
76# supported when building with MSVC because of the way that
77# conda-forge packages have 4 variants of the libraries packaged
78# together
79if(MSVC AND "${GTest_SOURCE}" STREQUAL "")
80  set(GTest_SOURCE "BUNDLED")
81endif()
82
83# For backward compatibility. We use "BOOST_SOURCE" if "Boost_SOURCE"
84# isn't specified and "BOOST_SOURCE" is specified.
85# We renamed "BOOST" dependency name to "Boost" in 3.0.0 because
86# upstreams (CMake and Boost) use "Boost" not "BOOST" as package name.
87if("${Boost_SOURCE}" STREQUAL "" AND NOT "${BOOST_SOURCE}" STREQUAL "")
88  set(Boost_SOURCE ${BOOST_SOURCE})
89endif()
90
91# For backward compatibility. We use "RE2_SOURCE" if "re2_SOURCE"
92# isn't specified and "RE2_SOURCE" is specified.
93# We renamed "RE2" dependency name to "re2" in 3.0.0 because
94# upstream uses "re2" not "RE2" as package name.
95if("${re2_SOURCE}" STREQUAL "" AND NOT "${RE2_SOURCE}" STREQUAL "")
96  set(re2_SOURCE ${RE2_SOURCE})
97endif()
98
99message(STATUS "Using ${ARROW_DEPENDENCY_SOURCE} approach to find dependencies")
100
101if(ARROW_DEPENDENCY_SOURCE STREQUAL "CONDA")
102  if(MSVC)
103    set(ARROW_PACKAGE_PREFIX "$ENV{CONDA_PREFIX}/Library")
104  else()
105    set(ARROW_PACKAGE_PREFIX $ENV{CONDA_PREFIX})
106  endif()
107  set(ARROW_ACTUAL_DEPENDENCY_SOURCE "SYSTEM")
108  message(STATUS "Using CONDA_PREFIX for ARROW_PACKAGE_PREFIX: ${ARROW_PACKAGE_PREFIX}")
109else()
110  set(ARROW_ACTUAL_DEPENDENCY_SOURCE "${ARROW_DEPENDENCY_SOURCE}")
111endif()
112
113if(ARROW_PACKAGE_PREFIX)
114  message(STATUS "Setting (unset) dependency *_ROOT variables: ${ARROW_PACKAGE_PREFIX}")
115  set(ENV{PKG_CONFIG_PATH} "${ARROW_PACKAGE_PREFIX}/lib/pkgconfig/")
116
117  if(NOT ENV{BOOST_ROOT})
118    set(ENV{BOOST_ROOT} ${ARROW_PACKAGE_PREFIX})
119  endif()
120  if(NOT ENV{Boost_ROOT})
121    set(ENV{Boost_ROOT} ${ARROW_PACKAGE_PREFIX})
122  endif()
123endif()
124
125# For each dependency, set dependency source to global default, if unset
126foreach(DEPENDENCY ${ARROW_THIRDPARTY_DEPENDENCIES})
127  if("${${DEPENDENCY}_SOURCE}" STREQUAL "")
128    set(${DEPENDENCY}_SOURCE ${ARROW_ACTUAL_DEPENDENCY_SOURCE})
129    # If no ROOT was supplied and we have a global prefix, use it
130    if(NOT ${DEPENDENCY}_ROOT AND ARROW_PACKAGE_PREFIX)
131      set(${DEPENDENCY}_ROOT ${ARROW_PACKAGE_PREFIX})
132    endif()
133  endif()
134endforeach()
135
136macro(build_dependency DEPENDENCY_NAME)
137  if("${DEPENDENCY_NAME}" STREQUAL "AWSSDK")
138    build_awssdk()
139  elseif("${DEPENDENCY_NAME}" STREQUAL "benchmark")
140    build_benchmark()
141  elseif("${DEPENDENCY_NAME}" STREQUAL "Boost")
142    build_boost()
143  elseif("${DEPENDENCY_NAME}" STREQUAL "Brotli")
144    build_brotli()
145  elseif("${DEPENDENCY_NAME}" STREQUAL "BZip2")
146    build_bzip2()
147  elseif("${DEPENDENCY_NAME}" STREQUAL "c-ares")
148    build_cares()
149  elseif("${DEPENDENCY_NAME}" STREQUAL "gflags")
150    build_gflags()
151  elseif("${DEPENDENCY_NAME}" STREQUAL "GLOG")
152    build_glog()
153  elseif("${DEPENDENCY_NAME}" STREQUAL "gRPC")
154    build_grpc()
155  elseif("${DEPENDENCY_NAME}" STREQUAL "GTest")
156    build_gtest()
157  elseif("${DEPENDENCY_NAME}" STREQUAL "Lz4")
158    build_lz4()
159  elseif("${DEPENDENCY_NAME}" STREQUAL "ORC")
160    build_orc()
161  elseif("${DEPENDENCY_NAME}" STREQUAL "Protobuf")
162    build_protobuf()
163  elseif("${DEPENDENCY_NAME}" STREQUAL "RapidJSON")
164    build_rapidjson()
165  elseif("${DEPENDENCY_NAME}" STREQUAL "re2")
166    build_re2()
167  elseif("${DEPENDENCY_NAME}" STREQUAL "Snappy")
168    build_snappy()
169  elseif("${DEPENDENCY_NAME}" STREQUAL "Thrift")
170    build_thrift()
171  elseif("${DEPENDENCY_NAME}" STREQUAL "utf8proc")
172    build_utf8proc()
173  elseif("${DEPENDENCY_NAME}" STREQUAL "ZLIB")
174    build_zlib()
175  elseif("${DEPENDENCY_NAME}" STREQUAL "zstd")
176    build_zstd()
177  else()
178    message(FATAL_ERROR "Unknown thirdparty dependency to build: ${DEPENDENCY_NAME}")
179  endif()
180endmacro()
181
182# Find modules are needed by the consumer in case of a static build, or if the
183# linkage is PUBLIC or INTERFACE.
184macro(provide_find_module PACKAGE_NAME)
185  set(module_ "${CMAKE_SOURCE_DIR}/cmake_modules/Find${PACKAGE_NAME}.cmake")
186  if(EXISTS "${module_}")
187    message(STATUS "Providing CMake module for ${PACKAGE_NAME}")
188    install(FILES "${module_}" DESTINATION "${ARROW_CMAKE_INSTALL_DIR}")
189  endif()
190  unset(module_)
191endmacro()
192
193macro(resolve_dependency DEPENDENCY_NAME)
194  set(options)
195  set(one_value_args HAVE_ALT IS_RUNTIME_DEPENDENCY REQUIRED_VERSION USE_CONFIG)
196  cmake_parse_arguments(ARG
197                        "${options}"
198                        "${one_value_args}"
199                        "${multi_value_args}"
200                        ${ARGN})
201  if(ARG_UNPARSED_ARGUMENTS)
202    message(SEND_ERROR "Error: unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}")
203  endif()
204  if("${ARG_IS_RUNTIME_DEPENDENCY}" STREQUAL "")
205    set(ARG_IS_RUNTIME_DEPENDENCY TRUE)
206  endif()
207
208  if(ARG_HAVE_ALT)
209    set(PACKAGE_NAME "${DEPENDENCY_NAME}Alt")
210  else()
211    set(PACKAGE_NAME ${DEPENDENCY_NAME})
212  endif()
213  set(FIND_PACKAGE_ARGUMENTS ${PACKAGE_NAME})
214  if(ARG_REQUIRED_VERSION)
215    list(APPEND FIND_PACKAGE_ARGUMENTS ${ARG_REQUIRED_VERSION})
216  endif()
217  if(ARG_USE_CONFIG)
218    list(APPEND FIND_PACKAGE_ARGUMENTS CONFIG)
219  endif()
220  if(${DEPENDENCY_NAME}_SOURCE STREQUAL "AUTO")
221    find_package(${FIND_PACKAGE_ARGUMENTS})
222    if(${${PACKAGE_NAME}_FOUND})
223      set(${DEPENDENCY_NAME}_SOURCE "SYSTEM")
224    else()
225      build_dependency(${DEPENDENCY_NAME})
226      set(${DEPENDENCY_NAME}_SOURCE "BUNDLED")
227    endif()
228  elseif(${DEPENDENCY_NAME}_SOURCE STREQUAL "BUNDLED")
229    build_dependency(${DEPENDENCY_NAME})
230  elseif(${DEPENDENCY_NAME}_SOURCE STREQUAL "SYSTEM")
231    find_package(${FIND_PACKAGE_ARGUMENTS} REQUIRED)
232  endif()
233  if(${DEPENDENCY_NAME}_SOURCE STREQUAL "SYSTEM" AND ARG_IS_RUNTIME_DEPENDENCY)
234    provide_find_module(${PACKAGE_NAME})
235    list(APPEND ARROW_SYSTEM_DEPENDENCIES ${PACKAGE_NAME})
236  endif()
237endmacro()
238
239# ----------------------------------------------------------------------
240# Thirdparty versions, environment variables, source URLs
241
242set(THIRDPARTY_DIR "${arrow_SOURCE_DIR}/thirdparty")
243
244# Include vendored Flatbuffers
245include_directories(SYSTEM "${THIRDPARTY_DIR}/flatbuffers/include")
246
247# ----------------------------------------------------------------------
248# Some EP's require other EP's
249
250if(ARROW_THRIFT)
251  set(ARROW_WITH_ZLIB ON)
252endif()
253
254if(ARROW_HIVESERVER2 OR ARROW_PARQUET)
255  set(ARROW_WITH_THRIFT ON)
256  if(ARROW_HIVESERVER2)
257    set(ARROW_THRIFT_REQUIRED_COMPONENTS COMPILER)
258  else()
259    set(ARROW_THRIFT_REQUIRED_COMPONENTS)
260  endif()
261else()
262  set(ARROW_WITH_THRIFT OFF)
263endif()
264
265if(ARROW_FLIGHT)
266  set(ARROW_WITH_GRPC ON)
267  # gRPC requires zlib
268  set(ARROW_WITH_ZLIB ON)
269endif()
270
271if(ARROW_JSON)
272  set(ARROW_WITH_RAPIDJSON ON)
273endif()
274
275if(ARROW_ORC OR ARROW_FLIGHT OR ARROW_GANDIVA)
276  set(ARROW_WITH_PROTOBUF ON)
277endif()
278
279if(ARROW_S3)
280  set(ARROW_WITH_ZLIB ON)
281endif()
282
283if(NOT ARROW_COMPUTE)
284  # utf8proc is only potentially used in kernels for now
285  set(ARROW_WITH_UTF8PROC OFF)
286endif()
287if((NOT ARROW_COMPUTE) AND (NOT ARROW_GANDIVA) AND (NOT ARROW_WITH_GRPC))
288  set(ARROW_WITH_RE2 OFF)
289endif()
290
291# ----------------------------------------------------------------------
292# Versions and URLs for toolchain builds, which also can be used to configure
293# offline builds
294# Note: We should not use the Apache dist server for build dependencies
295
296macro(set_urls URLS)
297  set(${URLS} ${ARGN})
298  if(CMAKE_VERSION VERSION_LESS 3.7)
299    # ExternalProject doesn't support backup URLs;
300    # Feature only available starting in 3.7
301    list(GET ${URLS} 0 ${URLS})
302  endif()
303endmacro()
304
305# Read toolchain versions from cpp/thirdparty/versions.txt
306file(STRINGS "${THIRDPARTY_DIR}/versions.txt" TOOLCHAIN_VERSIONS_TXT)
307foreach(_VERSION_ENTRY ${TOOLCHAIN_VERSIONS_TXT})
308  # Exclude comments
309  if(NOT
310     ((_VERSION_ENTRY MATCHES "^[^#][A-Za-z0-9-_]+_VERSION=")
311      OR (_VERSION_ENTRY MATCHES "^[^#][A-Za-z0-9-_]+_CHECKSUM=")))
312    continue()
313  endif()
314
315  string(REGEX MATCH "^[^=]*" _VARIABLE_NAME ${_VERSION_ENTRY})
316  string(REPLACE "${_VARIABLE_NAME}=" "" _VARIABLE_VALUE ${_VERSION_ENTRY})
317
318  # Skip blank or malformed lines
319  if(_VARIABLE_VALUE STREQUAL "")
320    continue()
321  endif()
322
323  # For debugging
324  message(STATUS "${_VARIABLE_NAME}: ${_VARIABLE_VALUE}")
325
326  set(${_VARIABLE_NAME} ${_VARIABLE_VALUE})
327endforeach()
328
329if(DEFINED ENV{ARROW_ABSL_URL})
330  set(ABSL_SOURCE_URL "$ENV{ARROW_ABSL_URL}")
331else()
332  set_urls(
333    ABSL_SOURCE_URL
334    "https://github.com/abseil/abseil-cpp/archive/${ARROW_ABSL_BUILD_VERSION}.tar.gz")
335endif()
336
337if(DEFINED ENV{ARROW_AWS_C_COMMON_URL})
338  set(AWS_C_COMMON_SOURCE_URL "$ENV{ARROW_AWS_C_COMMON_URL}")
339else()
340  set_urls(
341    AWS_C_COMMON_SOURCE_URL
342    "https://github.com/awslabs/aws-c-common/archive/${ARROW_AWS_C_COMMON_BUILD_VERSION}.tar.gz"
343    )
344endif()
345
346if(DEFINED ENV{ARROW_AWS_CHECKSUMS_URL})
347  set(AWS_CHECKSUMS_SOURCE_URL "$ENV{ARROW_AWS_CHECKSUMS_URL}")
348else()
349  set_urls(
350    AWS_CHECKSUMS_SOURCE_URL
351    "https://github.com/awslabs/aws-checksums/archive/${ARROW_AWS_CHECKSUMS_BUILD_VERSION}.tar.gz"
352    )
353endif()
354
355if(DEFINED ENV{ARROW_AWS_C_EVENT_STREAM_URL})
356  set(AWS_C_EVENT_STREAM_SOURCE_URL "$ENV{ARROW_AWS_C_EVENT_STREAM_URL}")
357else()
358  set_urls(
359    AWS_C_EVENT_STREAM_SOURCE_URL
360    "https://github.com/awslabs/aws-c-event-stream/archive/${ARROW_AWS_C_EVENT_STREAM_BUILD_VERSION}.tar.gz"
361    )
362endif()
363
364if(DEFINED ENV{ARROW_AWSSDK_URL})
365  set(AWSSDK_SOURCE_URL "$ENV{ARROW_AWSSDK_URL}")
366else()
367  set_urls(
368    AWSSDK_SOURCE_URL
369    "https://github.com/aws/aws-sdk-cpp/archive/${ARROW_AWSSDK_BUILD_VERSION}.tar.gz"
370    "https://github.com/ursa-labs/thirdparty/releases/download/latest/aws-sdk-cpp-${ARROW_AWSSDK_BUILD_VERSION}.tar.gz"
371    "https://dl.bintray.com/ursalabs/arrow-awssdk/aws-sdk-cpp-${ARROW_AWSSDK_BUILD_VERSION}.tar.gz/aws-sdk-cpp-${ARROW_AWSSDK_BUILD_VERSION}.tar.gz"
372    )
373endif()
374
375if(DEFINED ENV{ARROW_BOOST_URL})
376  set(BOOST_SOURCE_URL "$ENV{ARROW_BOOST_URL}")
377else()
378  string(REPLACE "." "_" ARROW_BOOST_BUILD_VERSION_UNDERSCORES
379                 ${ARROW_BOOST_BUILD_VERSION})
380  set_urls(
381    BOOST_SOURCE_URL
382    # These are trimmed boost bundles we maintain.
383    # See cpp/build-support/trim-boost.sh
384    "https://dl.bintray.com/ursalabs/arrow-boost/boost_${ARROW_BOOST_BUILD_VERSION_UNDERSCORES}.tar.gz"
385    "https://dl.bintray.com/boostorg/release/${ARROW_BOOST_BUILD_VERSION}/source/boost_${ARROW_BOOST_BUILD_VERSION_UNDERSCORES}.tar.gz"
386    "https://github.com/boostorg/boost/archive/boost-${ARROW_BOOST_BUILD_VERSION}.tar.gz"
387    # FIXME(ARROW-6407) automate uploading this archive to ensure it reflects
388    # our currently used packages and doesn't fall out of sync with
389    # ${ARROW_BOOST_BUILD_VERSION_UNDERSCORES}
390    "https://github.com/ursa-labs/thirdparty/releases/download/latest/boost_${ARROW_BOOST_BUILD_VERSION_UNDERSCORES}.tar.gz"
391    )
392endif()
393
394if(DEFINED ENV{ARROW_BROTLI_URL})
395  set(BROTLI_SOURCE_URL "$ENV{ARROW_BROTLI_URL}")
396else()
397  set_urls(
398    BROTLI_SOURCE_URL
399    "https://github.com/google/brotli/archive/${ARROW_BROTLI_BUILD_VERSION}.tar.gz"
400    "https://github.com/ursa-labs/thirdparty/releases/download/latest/brotli-${ARROW_BROTLI_BUILD_VERSION}.tar.gz"
401    )
402endif()
403
404if(DEFINED ENV{ARROW_CARES_URL})
405  set(CARES_SOURCE_URL "$ENV{ARROW_CARES_URL}")
406else()
407  set_urls(
408    CARES_SOURCE_URL
409    "https://c-ares.haxx.se/download/c-ares-${ARROW_CARES_BUILD_VERSION}.tar.gz"
410    "https://github.com/ursa-labs/thirdparty/releases/download/latest/cares-${ARROW_CARES_BUILD_VERSION}.tar.gz"
411    )
412endif()
413
414if(DEFINED ENV{ARROW_GBENCHMARK_URL})
415  set(GBENCHMARK_SOURCE_URL "$ENV{ARROW_GBENCHMARK_URL}")
416else()
417  set_urls(
418    GBENCHMARK_SOURCE_URL
419    "https://github.com/google/benchmark/archive/${ARROW_GBENCHMARK_BUILD_VERSION}.tar.gz"
420    "https://github.com/ursa-labs/thirdparty/releases/download/latest/gbenchmark-${ARROW_GBENCHMARK_BUILD_VERSION}.tar.gz"
421    )
422endif()
423
424if(DEFINED ENV{ARROW_GFLAGS_URL})
425  set(GFLAGS_SOURCE_URL "$ENV{ARROW_GFLAGS_URL}")
426else()
427  set_urls(
428    GFLAGS_SOURCE_URL
429    "https://github.com/gflags/gflags/archive/${ARROW_GFLAGS_BUILD_VERSION}.tar.gz"
430    "https://github.com/ursa-labs/thirdparty/releases/download/latest/gflags-${ARROW_GFLAGS_BUILD_VERSION}.tar.gz"
431    )
432endif()
433
434if(DEFINED ENV{ARROW_GLOG_URL})
435  set(GLOG_SOURCE_URL "$ENV{ARROW_GLOG_URL}")
436else()
437  set_urls(
438    GLOG_SOURCE_URL
439    "https://github.com/google/glog/archive/${ARROW_GLOG_BUILD_VERSION}.tar.gz"
440    "https://github.com/ursa-labs/thirdparty/releases/download/latest/glog-${ARROW_GLOG_BUILD_VERSION}.tar.gz"
441    )
442endif()
443
444if(DEFINED ENV{ARROW_GRPC_URL})
445  set(GRPC_SOURCE_URL "$ENV{ARROW_GRPC_URL}")
446else()
447  set_urls(
448    GRPC_SOURCE_URL
449    "https://github.com/grpc/grpc/archive/${ARROW_GRPC_BUILD_VERSION}.tar.gz"
450    "https://github.com/ursa-labs/thirdparty/releases/download/latest/grpc-${ARROW_GRPC_BUILD_VERSION}.tar.gz"
451    )
452endif()
453
454if(DEFINED ENV{ARROW_GTEST_URL})
455  set(GTEST_SOURCE_URL "$ENV{ARROW_GTEST_URL}")
456else()
457  set_urls(
458    GTEST_SOURCE_URL
459    "https://github.com/google/googletest/archive/release-${ARROW_GTEST_BUILD_VERSION}.tar.gz"
460    "https://chromium.googlesource.com/external/github.com/google/googletest/+archive/release-${ARROW_GTEST_BUILD_VERSION}.tar.gz"
461    "https://github.com/ursa-labs/thirdparty/releases/download/latest/gtest-${ARROW_GTEST_BUILD_VERSION}.tar.gz"
462    "https://dl.bintray.com/ursalabs/arrow-gtest/gtest-${ARROW_GTEST_BUILD_VERSION}.tar.gz"
463    )
464endif()
465
466if(DEFINED ENV{ARROW_JEMALLOC_URL})
467  set(JEMALLOC_SOURCE_URL "$ENV{ARROW_JEMALLOC_URL}")
468else()
469  set_urls(
470    JEMALLOC_SOURCE_URL
471    "https://github.com/jemalloc/jemalloc/releases/download/${ARROW_JEMALLOC_BUILD_VERSION}/jemalloc-${ARROW_JEMALLOC_BUILD_VERSION}.tar.bz2"
472    "https://github.com/ursa-labs/thirdparty/releases/download/latest/jemalloc-${ARROW_JEMALLOC_BUILD_VERSION}.tar.bz2"
473    )
474endif()
475
476if(DEFINED ENV{ARROW_MIMALLOC_URL})
477  set(MIMALLOC_SOURCE_URL "$ENV{ARROW_MIMALLOC_URL}")
478else()
479  set_urls(
480    MIMALLOC_SOURCE_URL
481    "https://github.com/microsoft/mimalloc/archive/${ARROW_MIMALLOC_BUILD_VERSION}.tar.gz"
482    "https://github.com/ursa-labs/thirdparty/releases/download/latest/mimalloc-${ARROW_MIMALLOC_BUILD_VERSION}.tar.gz"
483    )
484endif()
485
486if(DEFINED ENV{ARROW_LZ4_URL})
487  set(LZ4_SOURCE_URL "$ENV{ARROW_LZ4_URL}")
488else()
489  set_urls(
490    LZ4_SOURCE_URL "https://github.com/lz4/lz4/archive/${ARROW_LZ4_BUILD_VERSION}.tar.gz"
491    "https://github.com/ursa-labs/thirdparty/releases/download/latest/lz4-${ARROW_LZ4_BUILD_VERSION}.tar.gz"
492    )
493endif()
494
495if(DEFINED ENV{ARROW_ORC_URL})
496  set(ORC_SOURCE_URL "$ENV{ARROW_ORC_URL}")
497else()
498  set_urls(
499    ORC_SOURCE_URL
500    "https://github.com/apache/orc/archive/rel/release-${ARROW_ORC_BUILD_VERSION}.tar.gz"
501    "https://github.com/ursa-labs/thirdparty/releases/download/latest/orc-${ARROW_ORC_BUILD_VERSION}.tar.gz"
502    )
503endif()
504
505if(DEFINED ENV{ARROW_PROTOBUF_URL})
506  set(PROTOBUF_SOURCE_URL "$ENV{ARROW_PROTOBUF_URL}")
507else()
508  string(SUBSTRING ${ARROW_PROTOBUF_BUILD_VERSION} 1 -1
509                   ARROW_PROTOBUF_STRIPPED_BUILD_VERSION)
510  # strip the leading `v`
511  set_urls(
512    PROTOBUF_SOURCE_URL
513    "https://github.com/protocolbuffers/protobuf/releases/download/${ARROW_PROTOBUF_BUILD_VERSION}/protobuf-all-${ARROW_PROTOBUF_STRIPPED_BUILD_VERSION}.tar.gz"
514    "https://github.com/ursa-labs/thirdparty/releases/download/latest/protobuf-${ARROW_PROTOBUF_BUILD_VERSION}.tar.gz"
515    )
516endif()
517
518if(DEFINED ENV{ARROW_RE2_URL})
519  set(RE2_SOURCE_URL "$ENV{ARROW_RE2_URL}")
520else()
521  set_urls(
522    RE2_SOURCE_URL
523    "https://github.com/google/re2/archive/${ARROW_RE2_BUILD_VERSION}.tar.gz"
524    "https://github.com/ursa-labs/thirdparty/releases/download/latest/re2-${ARROW_RE2_BUILD_VERSION}.tar.gz"
525    )
526endif()
527
528if(DEFINED ENV{ARROW_RAPIDJSON_URL})
529  set(RAPIDJSON_SOURCE_URL "$ENV{ARROW_RAPIDJSON_URL}")
530else()
531  set_urls(
532    RAPIDJSON_SOURCE_URL
533    "https://github.com/miloyip/rapidjson/archive/${ARROW_RAPIDJSON_BUILD_VERSION}.tar.gz"
534    "https://github.com/ursa-labs/thirdparty/releases/download/latest/rapidjson-${ARROW_RAPIDJSON_BUILD_VERSION}.tar.gz"
535    )
536endif()
537
538if(DEFINED ENV{ARROW_SNAPPY_URL})
539  set(SNAPPY_SOURCE_URL "$ENV{ARROW_SNAPPY_URL}")
540else()
541  set_urls(
542    SNAPPY_SOURCE_URL
543    "https://github.com/google/snappy/archive/${ARROW_SNAPPY_BUILD_VERSION}.tar.gz"
544    "https://github.com/ursa-labs/thirdparty/releases/download/latest/snappy-${ARROW_SNAPPY_BUILD_VERSION}.tar.gz"
545    )
546endif()
547
548if(DEFINED ENV{ARROW_THRIFT_URL})
549  set(THRIFT_SOURCE_URL "$ENV{ARROW_THRIFT_URL}")
550else()
551  set_urls(
552    THRIFT_SOURCE_URL
553    "http://www.apache.org/dyn/closer.cgi?action=download&filename=/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
554    "https://downloads.apache.org/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
555    "https://github.com/apache/thrift/archive/v${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
556    "https://apache.claz.org/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
557    "https://apache.cs.utah.edu/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
558    "https://apache.mirrors.lucidnetworks.net/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
559    "https://apache.osuosl.org/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
560    "https://ftp.wayne.edu/apache/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
561    "https://mirror.olnevhost.net/pub/apache/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
562    "https://mirrors.gigenet.com/apache/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
563    "https://mirrors.koehn.com/apache/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
564    "https://mirrors.ocf.berkeley.edu/apache/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
565    "https://mirrors.sonic.net/apache/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
566    "https://us.mirrors.quenda.co/apache/thrift/${ARROW_THRIFT_BUILD_VERSION}/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
567    "https://github.com/ursa-labs/thirdparty/releases/download/latest/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
568    "https://dl.bintray.com/ursalabs/arrow-thrift/thrift-${ARROW_THRIFT_BUILD_VERSION}.tar.gz"
569    )
570endif()
571
572if(DEFINED ENV{ARROW_ZLIB_URL})
573  set(ZLIB_SOURCE_URL "$ENV{ARROW_ZLIB_URL}")
574else()
575  set_urls(
576    ZLIB_SOURCE_URL "https://zlib.net/fossils/zlib-${ARROW_ZLIB_BUILD_VERSION}.tar.gz"
577    "https://github.com/ursa-labs/thirdparty/releases/download/latest/zlib-${ARROW_ZLIB_BUILD_VERSION}.tar.gz"
578    )
579endif()
580
581if(DEFINED ENV{ARROW_ZSTD_URL})
582  set(ZSTD_SOURCE_URL "$ENV{ARROW_ZSTD_URL}")
583else()
584  set_urls(
585    ZSTD_SOURCE_URL
586    "https://github.com/facebook/zstd/archive/${ARROW_ZSTD_BUILD_VERSION}.tar.gz"
587    "https://github.com/ursa-labs/thirdparty/releases/download/latest/zstd-${ARROW_ZSTD_BUILD_VERSION}.tar.gz"
588    )
589endif()
590
591if(DEFINED ENV{ARROW_BZIP2_SOURCE_URL})
592  set(ARROW_BZIP2_SOURCE_URL "$ENV{ARROW_BZIP2_SOURCE_URL}")
593else()
594  set_urls(
595    ARROW_BZIP2_SOURCE_URL
596    "https://sourceware.org/pub/bzip2/bzip2-${ARROW_BZIP2_BUILD_VERSION}.tar.gz"
597    "https://github.com/ursa-labs/thirdparty/releases/download/latest/bzip2-${ARROW_BZIP2_BUILD_VERSION}.tar.gz"
598    )
599endif()
600
601if(DEFINED ENV{ARROW_UTF8PROC_SOURCE_URL})
602  set(ARROW_UTF8PROC_SOURCE_URL "$ENV{ARROW_UTF8PROC_SOURCE_URL}")
603else()
604  set_urls(
605    ARROW_UTF8PROC_SOURCE_URL
606    "https://github.com/JuliaStrings/utf8proc/archive/${ARROW_UTF8PROC_BUILD_VERSION}.tar.gz"
607    )
608endif()
609
610# ----------------------------------------------------------------------
611# ExternalProject options
612
613set(EP_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${UPPERCASE_BUILD_TYPE}}")
614set(EP_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${UPPERCASE_BUILD_TYPE}}")
615
616if(NOT MSVC_TOOLCHAIN)
617  # Set -fPIC on all external projects
618  set(EP_CXX_FLAGS "${EP_CXX_FLAGS} -fPIC")
619  set(EP_C_FLAGS "${EP_C_FLAGS} -fPIC")
620endif()
621
622# CC/CXX environment variables are captured on the first invocation of the
623# builder (e.g make or ninja) instead of when CMake is invoked into to build
624# directory. This leads to issues if the variables are exported in a subshell
625# and the invocation of make/ninja is in distinct subshell without the same
626# environment (CC/CXX).
627set(EP_COMMON_TOOLCHAIN -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
628                        -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER})
629
630if(CMAKE_AR)
631  set(EP_COMMON_TOOLCHAIN ${EP_COMMON_TOOLCHAIN} -DCMAKE_AR=${CMAKE_AR})
632endif()
633
634if(CMAKE_RANLIB)
635  set(EP_COMMON_TOOLCHAIN ${EP_COMMON_TOOLCHAIN} -DCMAKE_RANLIB=${CMAKE_RANLIB})
636endif()
637
638# External projects are still able to override the following declarations.
639# cmake command line will favor the last defined variable when a duplicate is
640# encountered. This requires that `EP_COMMON_CMAKE_ARGS` is always the first
641# argument.
642set(EP_COMMON_CMAKE_ARGS
643    ${EP_COMMON_TOOLCHAIN}
644    ${EP_COMMON_CMAKE_ARGS}
645    -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
646    -DCMAKE_C_FLAGS=${EP_C_FLAGS}
647    -DCMAKE_C_FLAGS_${UPPERCASE_BUILD_TYPE}=${EP_C_FLAGS}
648    -DCMAKE_CXX_FLAGS=${EP_CXX_FLAGS}
649    -DCMAKE_CXX_FLAGS_${UPPERCASE_BUILD_TYPE}=${EP_CXX_FLAGS}
650    -DCMAKE_EXPORT_NO_PACKAGE_REGISTRY=${CMAKE_EXPORT_NO_PACKAGE_REGISTRY}
651    -DCMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=${CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY})
652
653if(NOT ARROW_VERBOSE_THIRDPARTY_BUILD)
654  set(EP_LOG_OPTIONS
655      LOG_CONFIGURE
656      1
657      LOG_BUILD
658      1
659      LOG_INSTALL
660      1
661      LOG_DOWNLOAD
662      1
663      LOG_OUTPUT_ON_FAILURE
664      1)
665  set(Boost_DEBUG FALSE)
666else()
667  set(EP_LOG_OPTIONS)
668  set(Boost_DEBUG TRUE)
669endif()
670
671# Ensure that a default make is set
672if("${MAKE}" STREQUAL "")
673  if(NOT MSVC)
674    find_program(MAKE make)
675  endif()
676endif()
677
678# Using make -j in sub-make is fragile
679# see discussion https://github.com/apache/arrow/pull/2779
680if(${CMAKE_GENERATOR} MATCHES "Makefiles")
681  set(MAKE_BUILD_ARGS "")
682else()
683  # limit the maximum number of jobs for ninja
684  set(MAKE_BUILD_ARGS "-j${NPROC}")
685endif()
686
687# ----------------------------------------------------------------------
688# Find pthreads
689
690set(THREADS_PREFER_PTHREAD_FLAG ON)
691find_package(Threads REQUIRED)
692
693# ----------------------------------------------------------------------
694# Add Boost dependencies (code adapted from Apache Kudu)
695
696macro(build_boost)
697  set(BOOST_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/boost_ep-prefix/src/boost_ep")
698
699  # This is needed by the thrift_ep build
700  set(BOOST_ROOT ${BOOST_PREFIX})
701
702  if(ARROW_BOOST_REQUIRE_LIBRARY)
703    set(BOOST_LIB_DIR "${BOOST_PREFIX}/stage/lib")
704    set(BOOST_BUILD_LINK "static")
705    if("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG")
706      set(BOOST_BUILD_VARIANT "debug")
707    else()
708      set(BOOST_BUILD_VARIANT "release")
709    endif()
710    if(MSVC)
711      set(BOOST_CONFIGURE_COMMAND ".\\\\bootstrap.bat")
712    else()
713      set(BOOST_CONFIGURE_COMMAND "./bootstrap.sh")
714    endif()
715
716    set(BOOST_BUILD_WITH_LIBRARIES "filesystem" "regex" "system")
717    string(REPLACE ";" "," BOOST_CONFIGURE_LIBRARIES "${BOOST_BUILD_WITH_LIBRARIES}")
718    list(APPEND BOOST_CONFIGURE_COMMAND "--prefix=${BOOST_PREFIX}"
719                "--with-libraries=${BOOST_CONFIGURE_LIBRARIES}")
720    set(BOOST_BUILD_COMMAND "./b2" "-j${NPROC}" "link=${BOOST_BUILD_LINK}"
721                            "variant=${BOOST_BUILD_VARIANT}")
722    if(MSVC)
723      string(REGEX
724             REPLACE "([0-9])$" ".\\1" BOOST_TOOLSET_MSVC_VERSION ${MSVC_TOOLSET_VERSION})
725      list(APPEND BOOST_BUILD_COMMAND "toolset=msvc-${BOOST_TOOLSET_MSVC_VERSION}")
726      set(BOOST_BUILD_WITH_LIBRARIES_MSVC)
727      foreach(_BOOST_LIB ${BOOST_BUILD_WITH_LIBRARIES})
728        list(APPEND BOOST_BUILD_WITH_LIBRARIES_MSVC "--with-${_BOOST_LIB}")
729      endforeach()
730      list(APPEND BOOST_BUILD_COMMAND ${BOOST_BUILD_WITH_LIBRARIES_MSVC})
731    else()
732      list(APPEND BOOST_BUILD_COMMAND "cxxflags=-fPIC")
733    endif()
734
735    if(MSVC)
736      string(REGEX
737             REPLACE "^([0-9]+)\\.([0-9]+)\\.[0-9]+$" "\\1_\\2"
738                     ARROW_BOOST_BUILD_VERSION_NO_MICRO_UNDERSCORE
739                     ${ARROW_BOOST_BUILD_VERSION})
740      set(BOOST_LIBRARY_SUFFIX "-vc${MSVC_TOOLSET_VERSION}-mt")
741      if(BOOST_BUILD_VARIANT STREQUAL "debug")
742        set(BOOST_LIBRARY_SUFFIX "${BOOST_LIBRARY_SUFFIX}-gd")
743      endif()
744      set(BOOST_LIBRARY_SUFFIX
745          "${BOOST_LIBRARY_SUFFIX}-x64-${ARROW_BOOST_BUILD_VERSION_NO_MICRO_UNDERSCORE}")
746    else()
747      set(BOOST_LIBRARY_SUFFIX "")
748    endif()
749    set(
750      BOOST_STATIC_SYSTEM_LIBRARY
751      "${BOOST_LIB_DIR}/libboost_system${BOOST_LIBRARY_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}"
752      )
753    set(
754      BOOST_STATIC_FILESYSTEM_LIBRARY
755      "${BOOST_LIB_DIR}/libboost_filesystem${BOOST_LIBRARY_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}"
756      )
757    set(
758      BOOST_STATIC_REGEX_LIBRARY
759      "${BOOST_LIB_DIR}/libboost_regex${BOOST_LIBRARY_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}"
760      )
761    set(BOOST_SYSTEM_LIBRARY boost_system_static)
762    set(BOOST_FILESYSTEM_LIBRARY boost_filesystem_static)
763    set(BOOST_BUILD_PRODUCTS ${BOOST_STATIC_SYSTEM_LIBRARY}
764                             ${BOOST_STATIC_FILESYSTEM_LIBRARY})
765
766    add_thirdparty_lib(boost_system STATIC_LIB "${BOOST_STATIC_SYSTEM_LIBRARY}")
767
768    add_thirdparty_lib(boost_filesystem STATIC_LIB "${BOOST_STATIC_FILESYSTEM_LIBRARY}")
769
770    add_thirdparty_lib(boost_regex STATIC_LIB "${BOOST_STATIC_REGEX_LIBRARY}")
771
772    externalproject_add(boost_ep
773                        URL ${BOOST_SOURCE_URL}
774                        BUILD_BYPRODUCTS ${BOOST_BUILD_PRODUCTS}
775                        BUILD_IN_SOURCE 1
776                        CONFIGURE_COMMAND ${BOOST_CONFIGURE_COMMAND}
777                        BUILD_COMMAND ${BOOST_BUILD_COMMAND}
778                        INSTALL_COMMAND "" ${EP_LOG_OPTIONS})
779    list(APPEND ARROW_BUNDLED_STATIC_LIBS boost_system_static boost_filesystem_static
780                boost_regex_static)
781  else()
782    externalproject_add(boost_ep
783                        ${EP_LOG_OPTIONS}
784                        BUILD_COMMAND ""
785                        CONFIGURE_COMMAND ""
786                        INSTALL_COMMAND ""
787                        URL ${BOOST_SOURCE_URL})
788  endif()
789  set(Boost_INCLUDE_DIR "${BOOST_PREFIX}")
790  set(Boost_INCLUDE_DIRS "${Boost_INCLUDE_DIR}")
791  add_dependencies(toolchain boost_ep)
792  set(BOOST_VENDORED TRUE)
793endmacro()
794
795if(ARROW_FLIGHT AND ARROW_BUILD_TESTS)
796  set(ARROW_BOOST_REQUIRED_VERSION "1.64")
797else()
798  set(ARROW_BOOST_REQUIRED_VERSION "1.58")
799endif()
800
801set(Boost_USE_MULTITHREADED ON)
802if(MSVC AND ARROW_USE_STATIC_CRT)
803  set(Boost_USE_STATIC_RUNTIME ON)
804endif()
805set(Boost_ADDITIONAL_VERSIONS
806    "1.74.0"
807    "1.74"
808    "1.73.0"
809    "1.73"
810    "1.72.0"
811    "1.72"
812    "1.71.0"
813    "1.71"
814    "1.70.0"
815    "1.70"
816    "1.69.0"
817    "1.69"
818    "1.68.0"
819    "1.68"
820    "1.67.0"
821    "1.67"
822    "1.66.0"
823    "1.66"
824    "1.65.0"
825    "1.65"
826    "1.64.0"
827    "1.64"
828    "1.63.0"
829    "1.63"
830    "1.62.0"
831    "1.61"
832    "1.61.0"
833    "1.62"
834    "1.60.0"
835    "1.60")
836
837# Thrift needs Boost if we're building the bundled version with version < 0.13,
838# so we first need to determine whether we're building it
839if(ARROW_WITH_THRIFT AND Thrift_SOURCE STREQUAL "AUTO")
840  find_package(Thrift 0.11.0 MODULE COMPONENTS ${ARROW_THRIFT_REQUIRED_COMPONENTS})
841  if(NOT Thrift_FOUND AND NOT THRIFT_FOUND)
842    set(Thrift_SOURCE "BUNDLED")
843  endif()
844endif()
845
846# Thrift < 0.13 has a compile-time header dependency on boost
847if(Thrift_SOURCE STREQUAL "BUNDLED" AND ARROW_THRIFT_BUILD_VERSION VERSION_LESS "0.13")
848  set(THRIFT_REQUIRES_BOOST TRUE)
849elseif(THRIFT_VERSION VERSION_LESS "0.13")
850  set(THRIFT_REQUIRES_BOOST TRUE)
851else()
852  set(THRIFT_REQUIRES_BOOST FALSE)
853endif()
854
855# Compilers that don't support int128_t have a compile-time
856# (header-only) dependency on Boost for int128_t.
857if(ARROW_USE_UBSAN)
858  # NOTE: Avoid native int128_t on clang with UBSan as it produces linker errors
859  # (such as "undefined reference to '__muloti4'")
860  set(ARROW_USE_NATIVE_INT128 FALSE)
861else()
862  include(CheckCXXSymbolExists)
863  check_cxx_symbol_exists("__SIZEOF_INT128__" "" ARROW_USE_NATIVE_INT128)
864endif()
865
866# - Gandiva has a compile-time (header-only) dependency on Boost, not runtime.
867# - Tests need Boost at runtime.
868# - S3FS and Flight benchmarks need Boost at runtime.
869if(ARROW_BUILD_INTEGRATION
870   OR ARROW_BUILD_TESTS
871   OR (ARROW_FLIGHT AND ARROW_BUILD_BENCHMARKS)
872   OR (ARROW_S3 AND ARROW_BUILD_BENCHMARKS))
873  set(ARROW_BOOST_REQUIRED TRUE)
874  set(ARROW_BOOST_REQUIRE_LIBRARY TRUE)
875elseif(ARROW_GANDIVA
876       OR (ARROW_WITH_THRIFT AND THRIFT_REQUIRES_BOOST)
877       OR (NOT ARROW_USE_NATIVE_INT128))
878  set(ARROW_BOOST_REQUIRED TRUE)
879  set(ARROW_BOOST_REQUIRE_LIBRARY FALSE)
880else()
881  set(ARROW_BOOST_REQUIRED FALSE)
882endif()
883
884if(ARROW_BOOST_REQUIRED)
885  resolve_dependency(Boost
886                     HAVE_ALT
887                     TRUE
888                     REQUIRED_VERSION
889                     ${ARROW_BOOST_REQUIRED_VERSION}
890                     IS_RUNTIME_DEPENDENCY
891                     # libarrow.so doesn't depend on libboost*.
892                     FALSE)
893
894  if(TARGET Boost::system)
895    set(BOOST_SYSTEM_LIBRARY Boost::system)
896    set(BOOST_FILESYSTEM_LIBRARY Boost::filesystem)
897  elseif(BoostAlt_FOUND)
898    set(BOOST_SYSTEM_LIBRARY ${Boost_SYSTEM_LIBRARY})
899    set(BOOST_FILESYSTEM_LIBRARY ${Boost_FILESYSTEM_LIBRARY})
900  else()
901    set(BOOST_SYSTEM_LIBRARY boost_system_static)
902    set(BOOST_FILESYSTEM_LIBRARY boost_filesystem_static)
903  endif()
904  set(ARROW_BOOST_LIBS ${BOOST_SYSTEM_LIBRARY} ${BOOST_FILESYSTEM_LIBRARY})
905
906  message(STATUS "Boost include dir: ${Boost_INCLUDE_DIR}")
907  message(STATUS "Boost libraries: ${ARROW_BOOST_LIBS}")
908
909  include_directories(SYSTEM ${Boost_INCLUDE_DIR})
910endif()
911
912# ----------------------------------------------------------------------
913# Snappy
914
915macro(build_snappy)
916  message(STATUS "Building snappy from source")
917  set(SNAPPY_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/snappy_ep/src/snappy_ep-install")
918  set(SNAPPY_STATIC_LIB_NAME snappy)
919  set(
920    SNAPPY_STATIC_LIB
921    "${SNAPPY_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}${SNAPPY_STATIC_LIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}"
922    )
923
924  set(SNAPPY_CMAKE_ARGS ${EP_COMMON_CMAKE_ARGS} -DCMAKE_INSTALL_LIBDIR=lib
925                        -DSNAPPY_BUILD_TESTS=OFF
926                        "-DCMAKE_INSTALL_PREFIX=${SNAPPY_PREFIX}")
927
928  externalproject_add(snappy_ep
929                      ${EP_LOG_OPTIONS}
930                      BUILD_IN_SOURCE 1
931                      INSTALL_DIR ${SNAPPY_PREFIX}
932                      URL ${SNAPPY_SOURCE_URL}
933                      CMAKE_ARGS ${SNAPPY_CMAKE_ARGS}
934                      BUILD_BYPRODUCTS "${SNAPPY_STATIC_LIB}")
935
936  file(MAKE_DIRECTORY "${SNAPPY_PREFIX}/include")
937
938  add_library(Snappy::snappy STATIC IMPORTED)
939  set_target_properties(Snappy::snappy
940                        PROPERTIES IMPORTED_LOCATION "${SNAPPY_STATIC_LIB}"
941                                   INTERFACE_INCLUDE_DIRECTORIES
942                                   "${SNAPPY_PREFIX}/include")
943  add_dependencies(toolchain snappy_ep)
944  add_dependencies(Snappy::snappy snappy_ep)
945
946  list(APPEND ARROW_BUNDLED_STATIC_LIBS Snappy::snappy)
947endmacro()
948
949if(ARROW_WITH_SNAPPY)
950  resolve_dependency(Snappy)
951  # TODO: Don't use global includes but rather target_include_directories
952  get_target_property(SNAPPY_INCLUDE_DIRS Snappy::snappy INTERFACE_INCLUDE_DIRECTORIES)
953  include_directories(SYSTEM ${SNAPPY_INCLUDE_DIRS})
954endif()
955
956# ----------------------------------------------------------------------
957# Brotli
958
959macro(build_brotli)
960  message(STATUS "Building brotli from source")
961  set(BROTLI_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/brotli_ep/src/brotli_ep-install")
962  set(BROTLI_INCLUDE_DIR "${BROTLI_PREFIX}/include")
963  set(BROTLI_LIB_DIR lib)
964  set(
965    BROTLI_STATIC_LIBRARY_ENC
966    "${BROTLI_PREFIX}/${BROTLI_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}brotlienc-static${CMAKE_STATIC_LIBRARY_SUFFIX}"
967    )
968  set(
969    BROTLI_STATIC_LIBRARY_DEC
970    "${BROTLI_PREFIX}/${BROTLI_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}brotlidec-static${CMAKE_STATIC_LIBRARY_SUFFIX}"
971    )
972  set(
973    BROTLI_STATIC_LIBRARY_COMMON
974    "${BROTLI_PREFIX}/${BROTLI_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}brotlicommon-static${CMAKE_STATIC_LIBRARY_SUFFIX}"
975    )
976  set(BROTLI_CMAKE_ARGS ${EP_COMMON_CMAKE_ARGS} "-DCMAKE_INSTALL_PREFIX=${BROTLI_PREFIX}"
977                        -DCMAKE_INSTALL_LIBDIR=${BROTLI_LIB_DIR})
978
979  externalproject_add(brotli_ep
980                      URL ${BROTLI_SOURCE_URL}
981                      BUILD_BYPRODUCTS "${BROTLI_STATIC_LIBRARY_ENC}"
982                                       "${BROTLI_STATIC_LIBRARY_DEC}"
983                                       "${BROTLI_STATIC_LIBRARY_COMMON}"
984                                       ${BROTLI_BUILD_BYPRODUCTS}
985                                       ${EP_LOG_OPTIONS}
986                      CMAKE_ARGS ${BROTLI_CMAKE_ARGS}
987                      STEP_TARGETS headers_copy)
988
989  add_dependencies(toolchain brotli_ep)
990  file(MAKE_DIRECTORY "${BROTLI_INCLUDE_DIR}")
991
992  add_library(Brotli::brotlicommon STATIC IMPORTED)
993  set_target_properties(Brotli::brotlicommon
994                        PROPERTIES IMPORTED_LOCATION "${BROTLI_STATIC_LIBRARY_COMMON}"
995                                   INTERFACE_INCLUDE_DIRECTORIES "${BROTLI_INCLUDE_DIR}")
996  add_dependencies(Brotli::brotlicommon brotli_ep)
997
998  add_library(Brotli::brotlienc STATIC IMPORTED)
999  set_target_properties(Brotli::brotlienc
1000                        PROPERTIES IMPORTED_LOCATION "${BROTLI_STATIC_LIBRARY_ENC}"
1001                                   INTERFACE_INCLUDE_DIRECTORIES "${BROTLI_INCLUDE_DIR}")
1002  add_dependencies(Brotli::brotlienc brotli_ep)
1003
1004  add_library(Brotli::brotlidec STATIC IMPORTED)
1005  set_target_properties(Brotli::brotlidec
1006                        PROPERTIES IMPORTED_LOCATION "${BROTLI_STATIC_LIBRARY_DEC}"
1007                                   INTERFACE_INCLUDE_DIRECTORIES "${BROTLI_INCLUDE_DIR}")
1008  add_dependencies(Brotli::brotlidec brotli_ep)
1009
1010  list(APPEND ARROW_BUNDLED_STATIC_LIBS Brotli::brotlicommon Brotli::brotlienc
1011              Brotli::brotlidec)
1012endmacro()
1013
1014if(ARROW_WITH_BROTLI)
1015  resolve_dependency(Brotli)
1016  # TODO: Don't use global includes but rather target_include_directories
1017  get_target_property(BROTLI_INCLUDE_DIR Brotli::brotlicommon
1018                      INTERFACE_INCLUDE_DIRECTORIES)
1019  include_directories(SYSTEM ${BROTLI_INCLUDE_DIR})
1020endif()
1021
1022if(PARQUET_REQUIRE_ENCRYPTION AND NOT ARROW_PARQUET)
1023  set(PARQUET_REQUIRE_ENCRYPTION OFF)
1024endif()
1025set(ARROW_OPENSSL_REQUIRED_VERSION "1.0.2")
1026if(BREW_BIN AND NOT OPENSSL_ROOT_DIR)
1027  execute_process(COMMAND ${BREW_BIN} --prefix "openssl@1.1"
1028                  OUTPUT_VARIABLE OPENSSL11_BREW_PREFIX
1029                  OUTPUT_STRIP_TRAILING_WHITESPACE)
1030  if(OPENSSL11_BREW_PREFIX)
1031    set(OPENSSL_ROOT_DIR ${OPENSSL11_BREW_PREFIX})
1032  else()
1033    execute_process(COMMAND ${BREW_BIN} --prefix "openssl"
1034                    OUTPUT_VARIABLE OPENSSL_BREW_PREFIX
1035                    OUTPUT_STRIP_TRAILING_WHITESPACE)
1036    if(OPENSSL_BREW_PREFIX)
1037      set(OPENSSL_ROOT_DIR ${OPENSSL_BREW_PREFIX})
1038    endif()
1039  endif()
1040endif()
1041
1042set(ARROW_USE_OPENSSL OFF)
1043if(PARQUET_REQUIRE_ENCRYPTION OR ARROW_FLIGHT OR ARROW_S3)
1044  # OpenSSL is required
1045  if(ARROW_OPENSSL_USE_SHARED)
1046    # Find shared OpenSSL libraries.
1047    set(OpenSSL_USE_STATIC_LIBS OFF)
1048    # Seems that different envs capitalize this differently?
1049    set(OPENSSL_USE_STATIC_LIBS OFF)
1050    set(BUILD_SHARED_LIBS_KEEP ${BUILD_SHARED_LIBS})
1051    set(BUILD_SHARED_LIBS ON)
1052
1053    find_package(OpenSSL ${ARROW_OPENSSL_REQUIRED_VERSION} REQUIRED)
1054    set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_KEEP})
1055    unset(BUILD_SHARED_LIBS_KEEP)
1056  else()
1057    # Find static OpenSSL headers and libs
1058    set(OpenSSL_USE_STATIC_LIBS ON)
1059    set(OPENSSL_USE_STATIC_LIBS ON)
1060    find_package(OpenSSL ${ARROW_OPENSSL_REQUIRED_VERSION} REQUIRED)
1061  endif()
1062  set(ARROW_USE_OPENSSL ON)
1063endif()
1064
1065if(ARROW_USE_OPENSSL)
1066  message(STATUS "Found OpenSSL Crypto Library: ${OPENSSL_CRYPTO_LIBRARY}")
1067  message(STATUS "Building with OpenSSL (Version: ${OPENSSL_VERSION}) support")
1068
1069  list(APPEND ARROW_SYSTEM_DEPENDENCIES "OpenSSL")
1070
1071  include_directories(SYSTEM ${OPENSSL_INCLUDE_DIR})
1072else()
1073  message(
1074    STATUS
1075      "Building without OpenSSL support. Minimum OpenSSL version ${ARROW_OPENSSL_REQUIRED_VERSION} required."
1076    )
1077endif()
1078
1079# ----------------------------------------------------------------------
1080# GLOG
1081
1082macro(build_glog)
1083  message(STATUS "Building glog from source")
1084  set(GLOG_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/glog_ep-prefix/src/glog_ep")
1085  set(GLOG_INCLUDE_DIR "${GLOG_BUILD_DIR}/include")
1086  if(${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG")
1087    set(GLOG_LIB_SUFFIX "d")
1088  else()
1089    set(GLOG_LIB_SUFFIX "")
1090  endif()
1091  set(
1092    GLOG_STATIC_LIB
1093    "${GLOG_BUILD_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}glog${GLOG_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}"
1094    )
1095  set(GLOG_CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
1096  set(GLOG_CMAKE_C_FLAGS "${EP_C_FLAGS} -fPIC")
1097  if(Threads::Threads)
1098    set(GLOG_CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -pthread")
1099    set(GLOG_CMAKE_C_FLAGS "${EP_C_FLAGS} -fPIC -pthread")
1100  endif()
1101
1102  if(APPLE)
1103    # If we don't set this flag, the binary built with 10.13 cannot be used in 10.12.
1104    set(GLOG_CMAKE_CXX_FLAGS "${GLOG_CMAKE_CXX_FLAGS} -mmacosx-version-min=10.9")
1105  endif()
1106
1107  set(GLOG_CMAKE_ARGS
1108      ${EP_COMMON_CMAKE_ARGS}
1109      "-DCMAKE_INSTALL_PREFIX=${GLOG_BUILD_DIR}"
1110      -DBUILD_SHARED_LIBS=OFF
1111      -DBUILD_TESTING=OFF
1112      -DWITH_GFLAGS=OFF
1113      -DCMAKE_CXX_FLAGS_${UPPERCASE_BUILD_TYPE}=${GLOG_CMAKE_CXX_FLAGS}
1114      -DCMAKE_C_FLAGS_${UPPERCASE_BUILD_TYPE}=${GLOG_CMAKE_C_FLAGS}
1115      -DCMAKE_CXX_FLAGS=${GLOG_CMAKE_CXX_FLAGS})
1116  externalproject_add(glog_ep
1117                      URL ${GLOG_SOURCE_URL}
1118                      BUILD_IN_SOURCE 1
1119                      BUILD_BYPRODUCTS "${GLOG_STATIC_LIB}"
1120                      CMAKE_ARGS ${GLOG_CMAKE_ARGS} ${EP_LOG_OPTIONS})
1121
1122  add_dependencies(toolchain glog_ep)
1123  file(MAKE_DIRECTORY "${GLOG_INCLUDE_DIR}")
1124
1125  add_library(glog::glog STATIC IMPORTED)
1126  set_target_properties(glog::glog
1127                        PROPERTIES IMPORTED_LOCATION "${GLOG_STATIC_LIB}"
1128                                   INTERFACE_INCLUDE_DIRECTORIES "${GLOG_INCLUDE_DIR}")
1129  add_dependencies(glog::glog glog_ep)
1130
1131  list(APPEND ARROW_BUNDLED_STATIC_LIBS glog::glog)
1132endmacro()
1133
1134if(ARROW_USE_GLOG)
1135  resolve_dependency(GLOG)
1136  # TODO: Don't use global includes but rather target_include_directories
1137  get_target_property(GLOG_INCLUDE_DIR glog::glog INTERFACE_INCLUDE_DIRECTORIES)
1138  include_directories(SYSTEM ${GLOG_INCLUDE_DIR})
1139endif()
1140
1141# ----------------------------------------------------------------------
1142# gflags
1143
1144if(ARROW_BUILD_TESTS
1145   OR ARROW_BUILD_BENCHMARKS
1146   OR ARROW_BUILD_INTEGRATION
1147   OR ARROW_PLASMA
1148   OR ARROW_USE_GLOG
1149   OR ARROW_WITH_GRPC)
1150  set(ARROW_NEED_GFLAGS 1)
1151else()
1152  set(ARROW_NEED_GFLAGS 0)
1153endif()
1154
1155macro(build_gflags)
1156  message(STATUS "Building gflags from source")
1157
1158  set(GFLAGS_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/gflags_ep-prefix/src/gflags_ep")
1159  set(GFLAGS_INCLUDE_DIR "${GFLAGS_PREFIX}/include")
1160  if(${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG")
1161    set(GFLAGS_LIB_SUFFIX "_debug")
1162  else()
1163    set(GFLAGS_LIB_SUFFIX "")
1164  endif()
1165  if(MSVC)
1166    set(GFLAGS_STATIC_LIB "${GFLAGS_PREFIX}/lib/gflags_static${GFLAGS_LIB_SUFFIX}.lib")
1167  else()
1168    set(GFLAGS_STATIC_LIB "${GFLAGS_PREFIX}/lib/libgflags${GFLAGS_LIB_SUFFIX}.a")
1169  endif()
1170  set(GFLAGS_CMAKE_ARGS
1171      ${EP_COMMON_CMAKE_ARGS}
1172      "-DCMAKE_INSTALL_PREFIX=${GFLAGS_PREFIX}"
1173      -DBUILD_SHARED_LIBS=OFF
1174      -DBUILD_STATIC_LIBS=ON
1175      -DBUILD_PACKAGING=OFF
1176      -DBUILD_TESTING=OFF
1177      -DBUILD_CONFIG_TESTS=OFF
1178      -DINSTALL_HEADERS=ON)
1179
1180  file(MAKE_DIRECTORY "${GFLAGS_INCLUDE_DIR}")
1181  externalproject_add(gflags_ep
1182                      URL ${GFLAGS_SOURCE_URL} ${EP_LOG_OPTIONS}
1183                      BUILD_IN_SOURCE 1
1184                      BUILD_BYPRODUCTS "${GFLAGS_STATIC_LIB}"
1185                      CMAKE_ARGS ${GFLAGS_CMAKE_ARGS})
1186
1187  add_dependencies(toolchain gflags_ep)
1188
1189  add_thirdparty_lib(gflags STATIC_LIB ${GFLAGS_STATIC_LIB})
1190  set(GFLAGS_LIBRARY gflags_static)
1191  set_target_properties(${GFLAGS_LIBRARY}
1192                        PROPERTIES INTERFACE_COMPILE_DEFINITIONS "GFLAGS_IS_A_DLL=0"
1193                                   INTERFACE_INCLUDE_DIRECTORIES "${GFLAGS_INCLUDE_DIR}")
1194  if(MSVC)
1195    set_target_properties(${GFLAGS_LIBRARY}
1196                          PROPERTIES INTERFACE_LINK_LIBRARIES "shlwapi.lib")
1197  endif()
1198  set(GFLAGS_LIBRARIES ${GFLAGS_LIBRARY})
1199
1200  set(GFLAGS_VENDORED TRUE)
1201
1202  list(APPEND ARROW_BUNDLED_STATIC_LIBS gflags_static)
1203endmacro()
1204
1205if(ARROW_NEED_GFLAGS)
1206  set(ARROW_GFLAGS_REQUIRED_VERSION "2.1.0")
1207  resolve_dependency(gflags
1208                     HAVE_ALT
1209                     TRUE
1210                     REQUIRED_VERSION
1211                     ${ARROW_GFLAGS_REQUIRED_VERSION}
1212                     IS_RUNTIME_DEPENDENCY
1213                     FALSE)
1214  # TODO: Don't use global includes but rather target_include_directories
1215  include_directories(SYSTEM ${GFLAGS_INCLUDE_DIR})
1216
1217  if(NOT TARGET ${GFLAGS_LIBRARIES})
1218    if(TARGET gflags-shared)
1219      set(GFLAGS_LIBRARIES gflags-shared)
1220    elseif(TARGET gflags_shared)
1221      set(GFLAGS_LIBRARIES gflags_shared)
1222    endif()
1223  endif()
1224endif()
1225
1226# ----------------------------------------------------------------------
1227# Thrift
1228
1229macro(build_thrift)
1230  message("Building Apache Thrift from source")
1231  set(THRIFT_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/thrift_ep-install")
1232  set(THRIFT_INCLUDE_DIR "${THRIFT_PREFIX}/include")
1233  set(THRIFT_CMAKE_ARGS
1234      ${EP_COMMON_CMAKE_ARGS}
1235      "-DCMAKE_INSTALL_PREFIX=${THRIFT_PREFIX}"
1236      "-DCMAKE_INSTALL_RPATH=${THRIFT_PREFIX}/lib"
1237      -DBUILD_COMPILER=OFF
1238      -DBUILD_SHARED_LIBS=OFF
1239      # DWITH_SHARED_LIB is removed in 0.13
1240      -DWITH_SHARED_LIB=OFF
1241      -DBUILD_TESTING=OFF
1242      -DBUILD_EXAMPLES=OFF
1243      -DBUILD_TUTORIALS=OFF
1244      -DWITH_QT4=OFF
1245      -DWITH_C_GLIB=OFF
1246      -DWITH_JAVA=OFF
1247      -DWITH_PYTHON=OFF
1248      -DWITH_HASKELL=OFF
1249      -DWITH_CPP=ON
1250      -DWITH_STATIC_LIB=ON
1251      -DWITH_LIBEVENT=OFF
1252      # Work around https://gitlab.kitware.com/cmake/cmake/issues/18865
1253      -DBoost_NO_BOOST_CMAKE=ON)
1254
1255  # Thrift also uses boost. Forward important boost settings if there were ones passed.
1256  if(DEFINED BOOST_ROOT)
1257    list(APPEND THRIFT_CMAKE_ARGS "-DBOOST_ROOT=${BOOST_ROOT}")
1258  endif()
1259  if(DEFINED Boost_NAMESPACE)
1260    list(APPEND THRIFT_CMAKE_ARGS "-DBoost_NAMESPACE=${Boost_NAMESPACE}")
1261  endif()
1262
1263  set(THRIFT_STATIC_LIB_NAME "${CMAKE_STATIC_LIBRARY_PREFIX}thrift")
1264  if(MSVC)
1265    if(ARROW_USE_STATIC_CRT)
1266      set(THRIFT_STATIC_LIB_NAME "${THRIFT_STATIC_LIB_NAME}mt")
1267      list(APPEND THRIFT_CMAKE_ARGS "-DWITH_MT=ON")
1268    else()
1269      set(THRIFT_STATIC_LIB_NAME "${THRIFT_STATIC_LIB_NAME}md")
1270      list(APPEND THRIFT_CMAKE_ARGS "-DWITH_MT=OFF")
1271    endif()
1272  endif()
1273  if(${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG")
1274    set(THRIFT_STATIC_LIB_NAME "${THRIFT_STATIC_LIB_NAME}d")
1275  endif()
1276  set(THRIFT_STATIC_LIB
1277      "${THRIFT_PREFIX}/lib/${THRIFT_STATIC_LIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}")
1278
1279  if(BOOST_VENDORED)
1280    set(THRIFT_DEPENDENCIES ${THRIFT_DEPENDENCIES} boost_ep)
1281  endif()
1282
1283  externalproject_add(thrift_ep
1284                      URL ${THRIFT_SOURCE_URL}
1285                      URL_HASH "MD5=${ARROW_THRIFT_BUILD_MD5_CHECKSUM}"
1286                      BUILD_BYPRODUCTS "${THRIFT_STATIC_LIB}"
1287                      CMAKE_ARGS ${THRIFT_CMAKE_ARGS}
1288                      DEPENDS ${THRIFT_DEPENDENCIES} ${EP_LOG_OPTIONS})
1289
1290  add_library(thrift::thrift STATIC IMPORTED)
1291  # The include directory must exist before it is referenced by a target.
1292  file(MAKE_DIRECTORY "${THRIFT_INCLUDE_DIR}")
1293  set_target_properties(thrift::thrift
1294                        PROPERTIES IMPORTED_LOCATION "${THRIFT_STATIC_LIB}"
1295                                   INTERFACE_INCLUDE_DIRECTORIES "${THRIFT_INCLUDE_DIR}")
1296  add_dependencies(toolchain thrift_ep)
1297  add_dependencies(thrift::thrift thrift_ep)
1298  set(THRIFT_VERSION ${ARROW_THRIFT_BUILD_VERSION})
1299
1300  list(APPEND ARROW_BUNDLED_STATIC_LIBS thrift::thrift)
1301endmacro()
1302
1303if(ARROW_WITH_THRIFT)
1304  # We already may have looked for Thrift earlier, when considering whether
1305  # to build Boost, so don't look again if already found.
1306  if(NOT Thrift_FOUND AND NOT THRIFT_FOUND)
1307    # Thrift c++ code generated by 0.13 requires 0.11 or greater
1308    resolve_dependency(Thrift REQUIRED_VERSION 0.11.0)
1309  endif()
1310  # TODO: Don't use global includes but rather target_include_directories
1311  include_directories(SYSTEM ${THRIFT_INCLUDE_DIR})
1312endif()
1313
1314# ----------------------------------------------------------------------
1315# Protocol Buffers (required for ORC and Flight and Gandiva libraries)
1316
1317macro(build_protobuf)
1318  message("Building Protocol Buffers from source")
1319  set(PROTOBUF_VENDORED TRUE)
1320  set(PROTOBUF_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/protobuf_ep-install")
1321  set(PROTOBUF_INCLUDE_DIR "${PROTOBUF_PREFIX}/include")
1322  # Newer protobuf releases always have a lib prefix independent from CMAKE_STATIC_LIBRARY_PREFIX
1323  set(PROTOBUF_STATIC_LIB
1324      "${PROTOBUF_PREFIX}/lib/libprotobuf${CMAKE_STATIC_LIBRARY_SUFFIX}")
1325  set(PROTOC_STATIC_LIB "${PROTOBUF_PREFIX}/lib/libprotoc${CMAKE_STATIC_LIBRARY_SUFFIX}")
1326  set(Protobuf_PROTOC_LIBRARY "${PROTOC_STATIC_LIB}")
1327  set(PROTOBUF_COMPILER "${PROTOBUF_PREFIX}/bin/protoc")
1328
1329  if(CMAKE_VERSION VERSION_LESS 3.7)
1330    set(PROTOBUF_CONFIGURE_ARGS
1331        "AR=${CMAKE_AR}"
1332        "RANLIB=${CMAKE_RANLIB}"
1333        "CC=${CMAKE_C_COMPILER}"
1334        "CXX=${CMAKE_CXX_COMPILER}"
1335        "--disable-shared"
1336        "--prefix=${PROTOBUF_PREFIX}"
1337        "CFLAGS=${EP_C_FLAGS}"
1338        "CXXFLAGS=${EP_CXX_FLAGS}")
1339    set(PROTOBUF_BUILD_COMMAND ${MAKE} ${MAKE_BUILD_ARGS})
1340    if(CMAKE_OSX_SYSROOT)
1341      list(APPEND PROTOBUF_CONFIGURE_ARGS "SDKROOT=${CMAKE_OSX_SYSROOT}")
1342      list(APPEND PROTOBUF_BUILD_COMMAND "SDKROOT=${CMAKE_OSX_SYSROOT}")
1343    endif()
1344    set(PROTOBUF_EXTERNAL_PROJECT_ADD_ARGS
1345        CONFIGURE_COMMAND
1346        "./configure"
1347        ${PROTOBUF_CONFIGURE_ARGS}
1348        BUILD_COMMAND
1349        ${PROTOBUF_BUILD_COMMAND})
1350  else()
1351    set(PROTOBUF_CMAKE_ARGS
1352        ${EP_COMMON_CMAKE_ARGS}
1353        -DBUILD_SHARED_LIBS=OFF
1354        -DCMAKE_INSTALL_LIBDIR=lib
1355        "-DCMAKE_INSTALL_PREFIX=${PROTOBUF_PREFIX}"
1356        -Dprotobuf_BUILD_TESTS=OFF
1357        -Dprotobuf_DEBUG_POSTFIX=)
1358    if(MSVC AND NOT ARROW_USE_STATIC_CRT)
1359      list(APPEND PROTOBUF_CMAKE_ARGS "-Dprotobuf_MSVC_STATIC_RUNTIME=OFF")
1360    endif()
1361    if(ZLIB_ROOT)
1362      list(APPEND PROTOBUF_CMAKE_ARGS "-DZLIB_ROOT=${ZLIB_ROOT}")
1363    endif()
1364    set(PROTOBUF_EXTERNAL_PROJECT_ADD_ARGS CMAKE_ARGS ${PROTOBUF_CMAKE_ARGS} SOURCE_SUBDIR
1365                                           "cmake")
1366  endif()
1367
1368  externalproject_add(protobuf_ep
1369                      ${PROTOBUF_EXTERNAL_PROJECT_ADD_ARGS}
1370                      BUILD_BYPRODUCTS "${PROTOBUF_STATIC_LIB}" "${PROTOBUF_COMPILER}"
1371                                       ${EP_LOG_OPTIONS}
1372                      BUILD_IN_SOURCE 1
1373                      URL ${PROTOBUF_SOURCE_URL})
1374
1375  file(MAKE_DIRECTORY "${PROTOBUF_INCLUDE_DIR}")
1376
1377  add_library(arrow::protobuf::libprotobuf STATIC IMPORTED)
1378  set_target_properties(
1379    arrow::protobuf::libprotobuf
1380    PROPERTIES IMPORTED_LOCATION "${PROTOBUF_STATIC_LIB}" INTERFACE_INCLUDE_DIRECTORIES
1381               "${PROTOBUF_INCLUDE_DIR}")
1382  add_library(arrow::protobuf::libprotoc STATIC IMPORTED)
1383  set_target_properties(
1384    arrow::protobuf::libprotoc
1385    PROPERTIES IMPORTED_LOCATION "${PROTOC_STATIC_LIB}" INTERFACE_INCLUDE_DIRECTORIES
1386               "${PROTOBUF_INCLUDE_DIR}")
1387  add_executable(arrow::protobuf::protoc IMPORTED)
1388  set_target_properties(arrow::protobuf::protoc
1389                        PROPERTIES IMPORTED_LOCATION "${PROTOBUF_COMPILER}")
1390
1391  add_dependencies(toolchain protobuf_ep)
1392  add_dependencies(arrow::protobuf::libprotobuf protobuf_ep)
1393
1394  list(APPEND ARROW_BUNDLED_STATIC_LIBS arrow::protobuf::libprotobuf)
1395endmacro()
1396
1397if(ARROW_WITH_PROTOBUF)
1398  if(ARROW_WITH_GRPC)
1399    # gRPC 1.21.0 or later require Protobuf 3.7.0 or later.
1400    set(ARROW_PROTOBUF_REQUIRED_VERSION "3.7.0")
1401  elseif(ARROW_GANDIVA_JAVA)
1402    # google::protobuf::MessageLite::ByteSize() is deprecated since
1403    # Protobuf 3.4.0.
1404    set(ARROW_PROTOBUF_REQUIRED_VERSION "3.4.0")
1405  else()
1406    set(ARROW_PROTOBUF_REQUIRED_VERSION "2.6.1")
1407  endif()
1408  resolve_dependency(Protobuf REQUIRED_VERSION ${ARROW_PROTOBUF_REQUIRED_VERSION})
1409
1410  if(ARROW_PROTOBUF_USE_SHARED AND MSVC_TOOLCHAIN)
1411    add_definitions(-DPROTOBUF_USE_DLLS)
1412  endif()
1413
1414  # TODO: Don't use global includes but rather target_include_directories
1415  include_directories(SYSTEM ${PROTOBUF_INCLUDE_DIR})
1416
1417  if(TARGET arrow::protobuf::libprotobuf)
1418    set(ARROW_PROTOBUF_LIBPROTOBUF arrow::protobuf::libprotobuf)
1419  else()
1420    # CMake 3.8 or older don't define the targets
1421    if(NOT TARGET protobuf::libprotobuf)
1422      add_library(protobuf::libprotobuf UNKNOWN IMPORTED)
1423      set_target_properties(protobuf::libprotobuf
1424                            PROPERTIES IMPORTED_LOCATION "${PROTOBUF_LIBRARY}"
1425                                       INTERFACE_INCLUDE_DIRECTORIES
1426                                       "${PROTOBUF_INCLUDE_DIR}")
1427    endif()
1428    set(ARROW_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)
1429  endif()
1430  if(TARGET arrow::protobuf::libprotoc)
1431    set(ARROW_PROTOBUF_LIBPROTOC arrow::protobuf::libprotoc)
1432  else()
1433    # CMake 3.8 or older don't define the targets
1434    if(NOT TARGET protobuf::libprotoc)
1435      if(PROTOBUF_PROTOC_LIBRARY AND NOT Protobuf_PROTOC_LIBRARY)
1436        # Old CMake versions have a different casing.
1437        set(Protobuf_PROTOC_LIBRARY ${PROTOBUF_PROTOC_LIBRARY})
1438      endif()
1439      if(NOT Protobuf_PROTOC_LIBRARY)
1440        message(FATAL_ERROR "libprotoc was set to ${Protobuf_PROTOC_LIBRARY}")
1441      endif()
1442      add_library(protobuf::libprotoc UNKNOWN IMPORTED)
1443      set_target_properties(protobuf::libprotoc
1444                            PROPERTIES IMPORTED_LOCATION "${Protobuf_PROTOC_LIBRARY}"
1445                                       INTERFACE_INCLUDE_DIRECTORIES
1446                                       "${PROTOBUF_INCLUDE_DIR}")
1447    endif()
1448    set(ARROW_PROTOBUF_LIBPROTOC protobuf::libprotoc)
1449  endif()
1450  if(TARGET arrow::protobuf::protoc)
1451    set(ARROW_PROTOBUF_PROTOC arrow::protobuf::protoc)
1452  else()
1453    if(NOT TARGET protobuf::protoc)
1454      add_executable(protobuf::protoc IMPORTED)
1455      set_target_properties(protobuf::protoc
1456                            PROPERTIES IMPORTED_LOCATION "${PROTOBUF_PROTOC_EXECUTABLE}")
1457    endif()
1458    set(ARROW_PROTOBUF_PROTOC protobuf::protoc)
1459  endif()
1460
1461  # Log protobuf paths as we often see issues with mixed sources for
1462  # the libraries and protoc.
1463  get_target_property(PROTOBUF_PROTOC_EXECUTABLE ${ARROW_PROTOBUF_PROTOC}
1464                      IMPORTED_LOCATION)
1465  message(STATUS "Found protoc: ${PROTOBUF_PROTOC_EXECUTABLE}")
1466  # Protobuf_PROTOC_LIBRARY is set by all versions of FindProtobuf.cmake
1467  message(STATUS "Found libprotoc: ${Protobuf_PROTOC_LIBRARY}")
1468  get_target_property(PROTOBUF_LIBRARY ${ARROW_PROTOBUF_LIBPROTOBUF} IMPORTED_LOCATION)
1469  message(STATUS "Found libprotobuf: ${PROTOBUF_LIBRARY}")
1470  message(STATUS "Found protobuf headers: ${PROTOBUF_INCLUDE_DIR}")
1471endif()
1472
1473# ----------------------------------------------------------------------
1474# jemalloc - Unix-only high-performance allocator
1475
1476if(ARROW_JEMALLOC)
1477  message(STATUS "Building (vendored) jemalloc from source")
1478  # We only use a vendored jemalloc as we want to control its version.
1479  # Also our build of jemalloc is specially prefixed so that it will not
1480  # conflict with the default allocator as well as other jemalloc
1481  # installations.
1482  # find_package(jemalloc)
1483
1484  set(ARROW_JEMALLOC_USE_SHARED OFF)
1485  set(JEMALLOC_PREFIX
1486      "${CMAKE_CURRENT_BINARY_DIR}/jemalloc_ep-prefix/src/jemalloc_ep/dist/")
1487  set(JEMALLOC_STATIC_LIB
1488      "${JEMALLOC_PREFIX}/lib/libjemalloc_pic${CMAKE_STATIC_LIBRARY_SUFFIX}")
1489  set(JEMALLOC_CONFIGURE_COMMAND ./configure "AR=${CMAKE_AR}" "CC=${CMAKE_C_COMPILER}")
1490  if(CMAKE_OSX_SYSROOT)
1491    list(APPEND JEMALLOC_CONFIGURE_COMMAND "SDKROOT=${CMAKE_OSX_SYSROOT}")
1492  endif()
1493  list(APPEND JEMALLOC_CONFIGURE_COMMAND
1494              "--prefix=${JEMALLOC_PREFIX}"
1495              "--with-jemalloc-prefix=je_arrow_"
1496              "--with-private-namespace=je_arrow_private_"
1497              "--without-export"
1498              "--disable-shared"
1499              # Don't override operator new()
1500              "--disable-cxx" "--disable-libdl"
1501              # See https://github.com/jemalloc/jemalloc/issues/1237
1502              "--disable-initial-exec-tls" ${EP_LOG_OPTIONS})
1503  set(JEMALLOC_BUILD_COMMAND ${MAKE} ${MAKE_BUILD_ARGS})
1504  if(CMAKE_OSX_SYSROOT)
1505    list(APPEND JEMALLOC_BUILD_COMMAND "SDKROOT=${CMAKE_OSX_SYSROOT}")
1506  endif()
1507  externalproject_add(
1508    jemalloc_ep
1509    URL ${JEMALLOC_SOURCE_URL}
1510    PATCH_COMMAND
1511      touch doc/jemalloc.3 doc/jemalloc.html
1512      # The prefix "je_arrow_" must be kept in sync with the value in memory_pool.cc
1513    CONFIGURE_COMMAND ${JEMALLOC_CONFIGURE_COMMAND}
1514    BUILD_IN_SOURCE 1
1515    BUILD_COMMAND ${JEMALLOC_BUILD_COMMAND}
1516    BUILD_BYPRODUCTS "${JEMALLOC_STATIC_LIB}"
1517    INSTALL_COMMAND ${MAKE} -j1 install)
1518
1519  # Don't use the include directory directly so that we can point to a path
1520  # that is unique to our codebase.
1521  include_directories(SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/jemalloc_ep-prefix/src/")
1522  # The include directory must exist before it is referenced by a target.
1523  file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/jemalloc_ep-prefix/src/")
1524  add_library(jemalloc::jemalloc STATIC IMPORTED)
1525  set_target_properties(jemalloc::jemalloc
1526                        PROPERTIES INTERFACE_LINK_LIBRARIES
1527                                   Threads::Threads
1528                                   IMPORTED_LOCATION
1529                                   "${JEMALLOC_STATIC_LIB}"
1530                                   INTERFACE_INCLUDE_DIRECTORIES
1531                                   "${CMAKE_CURRENT_BINARY_DIR}/jemalloc_ep-prefix/src")
1532  add_dependencies(jemalloc::jemalloc jemalloc_ep)
1533
1534  list(APPEND ARROW_BUNDLED_STATIC_LIBS jemalloc::jemalloc)
1535endif()
1536
1537# ----------------------------------------------------------------------
1538# mimalloc - Cross-platform high-performance allocator, from Microsoft
1539
1540if(ARROW_MIMALLOC)
1541  message(STATUS "Building (vendored) mimalloc from source")
1542  # We only use a vendored mimalloc as we want to control its build options.
1543
1544  set(MIMALLOC_LIB_BASE_NAME "mimalloc")
1545  if(WIN32)
1546    set(MIMALLOC_LIB_BASE_NAME "${MIMALLOC_LIB_BASE_NAME}-static")
1547  endif()
1548  if(${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG")
1549    set(MIMALLOC_LIB_BASE_NAME "${MIMALLOC_LIB_BASE_NAME}-${LOWERCASE_BUILD_TYPE}")
1550  endif()
1551
1552  set(MIMALLOC_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/mimalloc_ep/src/mimalloc_ep")
1553  set(MIMALLOC_INCLUDE_DIR "${MIMALLOC_PREFIX}/lib/mimalloc-1.6/include")
1554  set(
1555    MIMALLOC_STATIC_LIB
1556    "${MIMALLOC_PREFIX}/lib/mimalloc-1.6/${CMAKE_STATIC_LIBRARY_PREFIX}${MIMALLOC_LIB_BASE_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}"
1557    )
1558
1559  set(MIMALLOC_CMAKE_ARGS
1560      ${EP_COMMON_CMAKE_ARGS}
1561      "-DCMAKE_INSTALL_PREFIX=${MIMALLOC_PREFIX}"
1562      -DMI_OVERRIDE=OFF
1563      -DMI_LOCAL_DYNAMIC_TLS=ON
1564      -DMI_BUILD_OBJECT=OFF
1565      -DMI_BUILD_SHARED=OFF
1566      -DMI_BUILD_TESTS=OFF)
1567
1568  externalproject_add(mimalloc_ep
1569                      URL ${MIMALLOC_SOURCE_URL}
1570                      CMAKE_ARGS ${MIMALLOC_CMAKE_ARGS}
1571                      BUILD_BYPRODUCTS "${MIMALLOC_STATIC_LIB}")
1572
1573  include_directories(SYSTEM ${MIMALLOC_INCLUDE_DIR})
1574  file(MAKE_DIRECTORY ${MIMALLOC_INCLUDE_DIR})
1575
1576  add_library(mimalloc::mimalloc STATIC IMPORTED)
1577  set_target_properties(mimalloc::mimalloc
1578                        PROPERTIES INTERFACE_LINK_LIBRARIES
1579                                   Threads::Threads
1580                                   IMPORTED_LOCATION
1581                                   "${MIMALLOC_STATIC_LIB}"
1582                                   INTERFACE_INCLUDE_DIRECTORIES
1583                                   "${MIMALLOC_INCLUDE_DIR}")
1584  add_dependencies(mimalloc::mimalloc mimalloc_ep)
1585  add_dependencies(toolchain mimalloc_ep)
1586
1587  list(APPEND ARROW_BUNDLED_STATIC_LIBS mimalloc::mimalloc)
1588endif()
1589
1590# ----------------------------------------------------------------------
1591# Google gtest
1592
1593macro(build_gtest)
1594  message(STATUS "Building gtest from source")
1595  set(GTEST_VENDORED TRUE)
1596  set(GTEST_CMAKE_CXX_FLAGS ${EP_CXX_FLAGS})
1597
1598  if(CMAKE_BUILD_TYPE MATCHES DEBUG)
1599    set(CMAKE_GTEST_DEBUG_EXTENSION "d")
1600  else()
1601    set(CMAKE_GTEST_DEBUG_EXTENSION "")
1602  endif()
1603
1604  if(APPLE)
1605    set(GTEST_CMAKE_CXX_FLAGS ${GTEST_CMAKE_CXX_FLAGS} -DGTEST_USE_OWN_TR1_TUPLE=1
1606                              -Wno-unused-value -Wno-ignored-attributes)
1607  endif()
1608
1609  if(MSVC)
1610    set(GTEST_CMAKE_CXX_FLAGS "${GTEST_CMAKE_CXX_FLAGS} -DGTEST_CREATE_SHARED_LIBRARY=1")
1611  endif()
1612
1613  set(GTEST_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/googletest_ep-prefix")
1614  set(GTEST_INCLUDE_DIR "${GTEST_PREFIX}/include")
1615
1616  set(_GTEST_LIBRARY_DIR "${GTEST_PREFIX}/lib")
1617
1618  if(MSVC)
1619    set(_GTEST_IMPORTED_TYPE IMPORTED_IMPLIB)
1620    set(_GTEST_LIBRARY_SUFFIX
1621        "${CMAKE_GTEST_DEBUG_EXTENSION}${CMAKE_IMPORT_LIBRARY_SUFFIX}")
1622  else()
1623    set(_GTEST_IMPORTED_TYPE IMPORTED_LOCATION)
1624    set(_GTEST_LIBRARY_SUFFIX
1625        "${CMAKE_GTEST_DEBUG_EXTENSION}${CMAKE_SHARED_LIBRARY_SUFFIX}")
1626
1627  endif()
1628
1629  set(GTEST_SHARED_LIB
1630      "${_GTEST_LIBRARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}gtest${_GTEST_LIBRARY_SUFFIX}")
1631  set(GMOCK_SHARED_LIB
1632      "${_GTEST_LIBRARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}gmock${_GTEST_LIBRARY_SUFFIX}")
1633  set(
1634    GTEST_MAIN_SHARED_LIB
1635    "${_GTEST_LIBRARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}gtest_main${_GTEST_LIBRARY_SUFFIX}"
1636    )
1637  set(GTEST_CMAKE_ARGS
1638      ${EP_COMMON_TOOLCHAIN}
1639      -DBUILD_SHARED_LIBS=ON
1640      -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
1641      -DCMAKE_CXX_FLAGS=${GTEST_CMAKE_CXX_FLAGS}
1642      -DCMAKE_CXX_FLAGS_${UPPERCASE_BUILD_TYPE}=${GTEST_CMAKE_CXX_FLAGS}
1643      -DCMAKE_INSTALL_LIBDIR=lib
1644      -DCMAKE_INSTALL_NAME_DIR=$<INSTALL_PREFIX$<ANGLE-R>/lib
1645      -DCMAKE_INSTALL_PREFIX=${GTEST_PREFIX}
1646      -DCMAKE_MACOSX_RPATH=OFF)
1647  set(GMOCK_INCLUDE_DIR "${GTEST_PREFIX}/include")
1648
1649  add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=1)
1650
1651  if(MSVC AND NOT ARROW_USE_STATIC_CRT)
1652    set(GTEST_CMAKE_ARGS ${GTEST_CMAKE_ARGS} -Dgtest_force_shared_crt=ON)
1653  endif()
1654
1655  externalproject_add(googletest_ep
1656                      URL ${GTEST_SOURCE_URL}
1657                      BUILD_BYPRODUCTS ${GTEST_SHARED_LIB} ${GTEST_MAIN_SHARED_LIB}
1658                                       ${GMOCK_SHARED_LIB}
1659                      CMAKE_ARGS ${GTEST_CMAKE_ARGS} ${EP_LOG_OPTIONS})
1660  if(WIN32)
1661    # Copy the built shared libraries to the same directory as our
1662    # test programs because Windows doesn't provided rpath (run-time
1663    # search path) feature. We need to put these shared libraries to
1664    # the same directory as our test programs or add
1665    # _GTEST_LIBRARY_DIR to PATH when we run our test programs. We
1666    # choose the former because the latter may be forgotten.
1667    set(_GTEST_RUNTIME_DIR "${GTEST_PREFIX}/bin")
1668    set(_GTEST_RUNTIME_SUFFIX
1669        "${CMAKE_GTEST_DEBUG_EXTENSION}${CMAKE_SHARED_LIBRARY_SUFFIX}")
1670    set(
1671      _GTEST_RUNTIME_LIB
1672      "${_GTEST_RUNTIME_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}gtest${_GTEST_RUNTIME_SUFFIX}")
1673    set(
1674      _GMOCK_RUNTIME_LIB
1675      "${_GTEST_RUNTIME_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}gmock${_GTEST_RUNTIME_SUFFIX}")
1676    set(
1677      _GTEST_MAIN_RUNTIME_LIB
1678      "${_GTEST_RUNTIME_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}gtest_main${_GTEST_RUNTIME_SUFFIX}"
1679      )
1680    if(CMAKE_VERSION VERSION_LESS 3.9)
1681      message(
1682        FATAL_ERROR
1683          "Building GoogleTest from source on Windows requires at least CMake 3.9")
1684    endif()
1685    get_property(_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
1686    if(_GENERATOR_IS_MULTI_CONFIG)
1687      set(_GTEST_RUNTIME_OUTPUT_DIR "${BUILD_OUTPUT_ROOT_DIRECTORY}/${CMAKE_BUILD_TYPE}")
1688    else()
1689      set(_GTEST_RUNTIME_OUTPUT_DIR ${BUILD_OUTPUT_ROOT_DIRECTORY})
1690    endif()
1691    externalproject_add_step(googletest_ep copy
1692                             COMMAND ${CMAKE_COMMAND} -E make_directory
1693                                     ${_GTEST_RUNTIME_OUTPUT_DIR}
1694                             COMMAND ${CMAKE_COMMAND}
1695                                     -E
1696                                     copy
1697                                     ${_GTEST_RUNTIME_LIB}
1698                                     ${_GTEST_RUNTIME_OUTPUT_DIR}
1699                             COMMAND ${CMAKE_COMMAND}
1700                                     -E
1701                                     copy
1702                                     ${_GMOCK_RUNTIME_LIB}
1703                                     ${_GTEST_RUNTIME_OUTPUT_DIR}
1704                             COMMAND ${CMAKE_COMMAND}
1705                                     -E
1706                                     copy
1707                                     ${_GTEST_MAIN_RUNTIME_LIB}
1708                                     ${_GTEST_RUNTIME_OUTPUT_DIR}
1709                             DEPENDEES install)
1710  endif()
1711
1712  # The include directory must exist before it is referenced by a target.
1713  file(MAKE_DIRECTORY "${GTEST_INCLUDE_DIR}")
1714
1715  add_library(GTest::gtest SHARED IMPORTED)
1716  set_target_properties(GTest::gtest
1717                        PROPERTIES ${_GTEST_IMPORTED_TYPE} "${GTEST_SHARED_LIB}"
1718                                   INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIR}")
1719
1720  add_library(GTest::gtest_main SHARED IMPORTED)
1721  set_target_properties(GTest::gtest_main
1722                        PROPERTIES ${_GTEST_IMPORTED_TYPE} "${GTEST_MAIN_SHARED_LIB}"
1723                                   INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIR}")
1724
1725  add_library(GTest::gmock SHARED IMPORTED)
1726  set_target_properties(GTest::gmock
1727                        PROPERTIES ${_GTEST_IMPORTED_TYPE} "${GMOCK_SHARED_LIB}"
1728                                   INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIR}")
1729  add_dependencies(toolchain-tests googletest_ep)
1730  add_dependencies(GTest::gtest googletest_ep)
1731  add_dependencies(GTest::gtest_main googletest_ep)
1732  add_dependencies(GTest::gmock googletest_ep)
1733endmacro()
1734
1735if(ARROW_TESTING)
1736  resolve_dependency(GTest
1737                     REQUIRED_VERSION
1738                     1.10.0
1739                     USE_CONFIG
1740                     TRUE)
1741
1742  if(NOT GTEST_VENDORED)
1743    # TODO(wesm): This logic does not work correctly with the MSVC static libraries
1744    # built for the shared crt
1745
1746    #     set(CMAKE_REQUIRED_LIBRARIES GTest::GTest GTest::Main GTest::GMock)
1747    #     CHECK_CXX_SOURCE_COMPILES("
1748    # #include <gmock/gmock.h>
1749    # #include <gtest/gtest.h>
1750
1751    # class A {
1752    #   public:
1753    #     int run() const { return 1; }
1754    # };
1755
1756    # class B : public A {
1757    #   public:
1758    #     MOCK_CONST_METHOD0(run, int());
1759    # };
1760
1761    # TEST(Base, Test) {
1762    #   B b;
1763    # }" GTEST_COMPILES_WITHOUT_MACRO)
1764    #     if (NOT GTEST_COMPILES_WITHOUT_MACRO)
1765    #       message(STATUS "Setting GTEST_LINKED_AS_SHARED_LIBRARY=1 on GTest::GTest")
1766    #       add_compile_definitions("GTEST_LINKED_AS_SHARED_LIBRARY=1")
1767    #     endif()
1768    #     set(CMAKE_REQUIRED_LIBRARIES)
1769  endif()
1770
1771  get_target_property(GTEST_INCLUDE_DIR GTest::gtest INTERFACE_INCLUDE_DIRECTORIES)
1772  # TODO: Don't use global includes but rather target_include_directories
1773  include_directories(SYSTEM ${GTEST_INCLUDE_DIR})
1774endif()
1775
1776macro(build_benchmark)
1777  message(STATUS "Building benchmark from source")
1778  if(CMAKE_VERSION VERSION_LESS 3.6)
1779    message(FATAL_ERROR "Building gbenchmark from source requires at least CMake 3.6")
1780  endif()
1781
1782  if(NOT MSVC)
1783    set(GBENCHMARK_CMAKE_CXX_FLAGS "${EP_CXX_FLAGS} -std=c++11")
1784  endif()
1785
1786  if(APPLE
1787     AND (CMAKE_CXX_COMPILER_ID
1788          STREQUAL
1789          "AppleClang"
1790          OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
1791    set(GBENCHMARK_CMAKE_CXX_FLAGS "${GBENCHMARK_CMAKE_CXX_FLAGS} -stdlib=libc++")
1792  endif()
1793
1794  set(GBENCHMARK_PREFIX
1795      "${CMAKE_CURRENT_BINARY_DIR}/gbenchmark_ep/src/gbenchmark_ep-install")
1796  set(GBENCHMARK_INCLUDE_DIR "${GBENCHMARK_PREFIX}/include")
1797  set(
1798    GBENCHMARK_STATIC_LIB
1799    "${GBENCHMARK_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}benchmark${CMAKE_STATIC_LIBRARY_SUFFIX}"
1800    )
1801  set(
1802    GBENCHMARK_MAIN_STATIC_LIB
1803    "${GBENCHMARK_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}benchmark_main${CMAKE_STATIC_LIBRARY_SUFFIX}"
1804    )
1805  set(GBENCHMARK_CMAKE_ARGS
1806      ${EP_COMMON_CMAKE_ARGS}
1807      "-DCMAKE_INSTALL_PREFIX=${GBENCHMARK_PREFIX}"
1808      -DCMAKE_INSTALL_LIBDIR=lib
1809      -DBENCHMARK_ENABLE_TESTING=OFF
1810      -DCMAKE_CXX_FLAGS=${GBENCHMARK_CMAKE_CXX_FLAGS})
1811  if(APPLE)
1812    set(GBENCHMARK_CMAKE_ARGS ${GBENCHMARK_CMAKE_ARGS} "-DBENCHMARK_USE_LIBCXX=ON")
1813  endif()
1814
1815  externalproject_add(gbenchmark_ep
1816                      URL ${GBENCHMARK_SOURCE_URL}
1817                      BUILD_BYPRODUCTS "${GBENCHMARK_STATIC_LIB}"
1818                                       "${GBENCHMARK_MAIN_STATIC_LIB}"
1819                      CMAKE_ARGS ${GBENCHMARK_CMAKE_ARGS} ${EP_LOG_OPTIONS})
1820
1821  # The include directory must exist before it is referenced by a target.
1822  file(MAKE_DIRECTORY "${GBENCHMARK_INCLUDE_DIR}")
1823
1824  add_library(benchmark::benchmark STATIC IMPORTED)
1825  set_target_properties(benchmark::benchmark
1826                        PROPERTIES IMPORTED_LOCATION "${GBENCHMARK_STATIC_LIB}"
1827                                   INTERFACE_INCLUDE_DIRECTORIES
1828                                   "${GBENCHMARK_INCLUDE_DIR}")
1829
1830  add_library(benchmark::benchmark_main STATIC IMPORTED)
1831  set_target_properties(benchmark::benchmark_main
1832                        PROPERTIES IMPORTED_LOCATION "${GBENCHMARK_MAIN_STATIC_LIB}"
1833                                   INTERFACE_INCLUDE_DIRECTORIES
1834                                   "${GBENCHMARK_INCLUDE_DIR}")
1835
1836  add_dependencies(toolchain-benchmarks gbenchmark_ep)
1837  add_dependencies(benchmark::benchmark gbenchmark_ep)
1838  add_dependencies(benchmark::benchmark_main gbenchmark_ep)
1839endmacro()
1840
1841if(ARROW_BUILD_BENCHMARKS)
1842  # ArgsProduct() is available since 1.5.2
1843  set(BENCHMARK_REQUIRED_VERSION 1.5.2)
1844  if("${ARROW_DEPENDENCY_SOURCE}" STREQUAL "CONDA"
1845     AND "${benchmark_SOURCE}" STREQUAL "SYSTEM")
1846    # TODO: Remove this workaround once
1847    # https://github.com/google/benchmark/issues/1046 is resolved.
1848    #
1849    # benchmark doesn't set suitable version when we use released
1850    # archive. So the benchmark package on conda-forge isn't report
1851    # the real version. We accept all the benchmark package with
1852    # conda. Conda users should install benchmark 1.5.2 or later by
1853    # ci/conda_env_cpp.yml.
1854    set(BENCHMARK_REQUIRED_VERSION 0.0.0)
1855  endif()
1856  resolve_dependency(benchmark REQUIRED_VERSION ${BENCHMARK_REQUIRED_VERSION})
1857  # TODO: Don't use global includes but rather target_include_directories
1858  get_target_property(BENCHMARK_INCLUDE_DIR benchmark::benchmark
1859                      INTERFACE_INCLUDE_DIRECTORIES)
1860  include_directories(SYSTEM ${BENCHMARK_INCLUDE_DIR})
1861endif()
1862
1863macro(build_rapidjson)
1864  message(STATUS "Building RapidJSON from source")
1865  set(RAPIDJSON_PREFIX
1866      "${CMAKE_CURRENT_BINARY_DIR}/rapidjson_ep/src/rapidjson_ep-install")
1867  set(RAPIDJSON_CMAKE_ARGS
1868      ${EP_COMMON_CMAKE_ARGS}
1869      -DRAPIDJSON_BUILD_DOC=OFF
1870      -DRAPIDJSON_BUILD_EXAMPLES=OFF
1871      -DRAPIDJSON_BUILD_TESTS=OFF
1872      "-DCMAKE_INSTALL_PREFIX=${RAPIDJSON_PREFIX}")
1873
1874  externalproject_add(rapidjson_ep
1875                      ${EP_LOG_OPTIONS}
1876                      PREFIX "${CMAKE_BINARY_DIR}"
1877                      URL ${RAPIDJSON_SOURCE_URL}
1878                      CMAKE_ARGS ${RAPIDJSON_CMAKE_ARGS})
1879
1880  set(RAPIDJSON_INCLUDE_DIR "${RAPIDJSON_PREFIX}/include")
1881
1882  add_dependencies(toolchain rapidjson_ep)
1883  add_dependencies(toolchain-tests rapidjson_ep)
1884  add_dependencies(rapidjson rapidjson_ep)
1885
1886  set(RAPIDJSON_VENDORED TRUE)
1887endmacro()
1888
1889if(ARROW_WITH_RAPIDJSON)
1890  set(ARROW_RAPIDJSON_REQUIRED_VERSION "1.1.0")
1891  resolve_dependency(RapidJSON
1892                     HAVE_ALT
1893                     TRUE
1894                     REQUIRED_VERSION
1895                     ${ARROW_RAPIDJSON_REQUIRED_VERSION}
1896                     IS_RUNTIME_DEPENDENCY
1897                     FALSE)
1898
1899  if(RapidJSON_INCLUDE_DIR)
1900    set(RAPIDJSON_INCLUDE_DIR "${RapidJSON_INCLUDE_DIR}")
1901  endif()
1902
1903  # TODO: Don't use global includes but rather target_include_directories
1904  include_directories(SYSTEM ${RAPIDJSON_INCLUDE_DIR})
1905endif()
1906
1907macro(build_zlib)
1908  message(STATUS "Building ZLIB from source")
1909  set(ZLIB_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/zlib_ep/src/zlib_ep-install")
1910  if(MSVC)
1911    if(${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG")
1912      set(ZLIB_STATIC_LIB_NAME zlibstaticd.lib)
1913    else()
1914      set(ZLIB_STATIC_LIB_NAME zlibstatic.lib)
1915    endif()
1916  else()
1917    set(ZLIB_STATIC_LIB_NAME libz.a)
1918  endif()
1919  set(ZLIB_STATIC_LIB "${ZLIB_PREFIX}/lib/${ZLIB_STATIC_LIB_NAME}")
1920  set(ZLIB_CMAKE_ARGS ${EP_COMMON_CMAKE_ARGS} "-DCMAKE_INSTALL_PREFIX=${ZLIB_PREFIX}"
1921                      -DBUILD_SHARED_LIBS=OFF)
1922
1923  externalproject_add(zlib_ep
1924                      URL ${ZLIB_SOURCE_URL} ${EP_LOG_OPTIONS}
1925                      BUILD_BYPRODUCTS "${ZLIB_STATIC_LIB}"
1926                      CMAKE_ARGS ${ZLIB_CMAKE_ARGS})
1927
1928  file(MAKE_DIRECTORY "${ZLIB_PREFIX}/include")
1929
1930  add_library(ZLIB::ZLIB STATIC IMPORTED)
1931  set(ZLIB_LIBRARIES ${ZLIB_STATIC_LIB})
1932  set(ZLIB_INCLUDE_DIRS "${ZLIB_PREFIX}/include")
1933  set_target_properties(ZLIB::ZLIB
1934                        PROPERTIES IMPORTED_LOCATION ${ZLIB_LIBRARIES}
1935                                   INTERFACE_INCLUDE_DIRECTORIES ${ZLIB_INCLUDE_DIRS})
1936
1937  add_dependencies(toolchain zlib_ep)
1938  add_dependencies(ZLIB::ZLIB zlib_ep)
1939
1940  list(APPEND ARROW_BUNDLED_STATIC_LIBS ZLIB::ZLIB)
1941endmacro()
1942
1943if(ARROW_WITH_ZLIB)
1944  resolve_dependency(ZLIB)
1945
1946  # TODO: Don't use global includes but rather target_include_directories
1947  get_target_property(ZLIB_INCLUDE_DIR ZLIB::ZLIB INTERFACE_INCLUDE_DIRECTORIES)
1948  include_directories(SYSTEM ${ZLIB_INCLUDE_DIR})
1949endif()
1950
1951macro(build_lz4)
1952  message(STATUS "Building lz4 from source")
1953  set(LZ4_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/lz4_ep-prefix/src/lz4_ep")
1954  set(LZ4_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/lz4_ep-prefix")
1955
1956  if(MSVC)
1957    if(ARROW_USE_STATIC_CRT)
1958      if(${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG")
1959        set(LZ4_RUNTIME_LIBRARY_LINKAGE "/p:RuntimeLibrary=MultiThreadedDebug")
1960      else()
1961        set(LZ4_RUNTIME_LIBRARY_LINKAGE "/p:RuntimeLibrary=MultiThreaded")
1962      endif()
1963    endif()
1964    set(LZ4_STATIC_LIB
1965        "${LZ4_BUILD_DIR}/build/VS2010/bin/x64_${CMAKE_BUILD_TYPE}/liblz4_static.lib")
1966    set(LZ4_BUILD_COMMAND
1967        BUILD_COMMAND
1968        msbuild.exe
1969        /m
1970        /p:Configuration=${CMAKE_BUILD_TYPE}
1971        /p:Platform=x64
1972        /p:PlatformToolset=v140
1973        ${LZ4_RUNTIME_LIBRARY_LINKAGE}
1974        /t:Build
1975        ${LZ4_BUILD_DIR}/build/VS2010/lz4.sln)
1976  else()
1977    set(LZ4_STATIC_LIB "${LZ4_BUILD_DIR}/lib/liblz4.a")
1978    set(LZ4_BUILD_COMMAND BUILD_COMMAND ${CMAKE_SOURCE_DIR}/build-support/build-lz4-lib.sh
1979                          "AR=${CMAKE_AR}" "OS=${CMAKE_SYSTEM_NAME}")
1980  endif()
1981
1982  # We need to copy the header in lib to directory outside of the build
1983  externalproject_add(lz4_ep
1984                      URL ${LZ4_SOURCE_URL} ${EP_LOG_OPTIONS}
1985                      UPDATE_COMMAND ${CMAKE_COMMAND}
1986                                     -E
1987                                     copy_directory
1988                                     "${LZ4_BUILD_DIR}/lib"
1989                                     "${LZ4_PREFIX}/include"
1990                                     ${LZ4_PATCH_COMMAND}
1991                      CONFIGURE_COMMAND ""
1992                      INSTALL_COMMAND ""
1993                      BINARY_DIR ${LZ4_BUILD_DIR}
1994                      BUILD_BYPRODUCTS ${LZ4_STATIC_LIB} ${LZ4_BUILD_COMMAND})
1995
1996  file(MAKE_DIRECTORY "${LZ4_PREFIX}/include")
1997  add_library(LZ4::lz4 STATIC IMPORTED)
1998  set_target_properties(LZ4::lz4
1999                        PROPERTIES IMPORTED_LOCATION "${LZ4_STATIC_LIB}"
2000                                   INTERFACE_INCLUDE_DIRECTORIES "${LZ4_PREFIX}/include")
2001  add_dependencies(toolchain lz4_ep)
2002  add_dependencies(LZ4::lz4 lz4_ep)
2003
2004  list(APPEND ARROW_BUNDLED_STATIC_LIBS LZ4::lz4)
2005endmacro()
2006
2007if(ARROW_WITH_LZ4)
2008  resolve_dependency(Lz4)
2009
2010  # TODO: Don't use global includes but rather target_include_directories
2011  get_target_property(LZ4_INCLUDE_DIR LZ4::lz4 INTERFACE_INCLUDE_DIRECTORIES)
2012  include_directories(SYSTEM ${LZ4_INCLUDE_DIR})
2013endif()
2014
2015macro(build_zstd)
2016  message(STATUS "Building zstd from source")
2017  set(ZSTD_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/zstd_ep-install")
2018
2019  set(ZSTD_CMAKE_ARGS
2020      ${EP_COMMON_TOOLCHAIN}
2021      "-DCMAKE_INSTALL_PREFIX=${ZSTD_PREFIX}"
2022      -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
2023      -DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR}
2024      -DZSTD_BUILD_PROGRAMS=off
2025      -DZSTD_BUILD_SHARED=off
2026      -DZSTD_BUILD_STATIC=on
2027      -DZSTD_MULTITHREAD_SUPPORT=off)
2028
2029  if(MSVC)
2030    set(ZSTD_STATIC_LIB "${ZSTD_PREFIX}/${CMAKE_INSTALL_LIBDIR}/zstd_static.lib")
2031    if(ARROW_USE_STATIC_CRT)
2032      set(ZSTD_CMAKE_ARGS ${ZSTD_CMAKE_ARGS} "-DZSTD_USE_STATIC_RUNTIME=on")
2033    endif()
2034  else()
2035    set(ZSTD_STATIC_LIB "${ZSTD_PREFIX}/${CMAKE_INSTALL_LIBDIR}/libzstd.a")
2036    # Only pass our C flags on Unix as on MSVC it leads to a
2037    # "incompatible command-line options" error
2038    set(ZSTD_CMAKE_ARGS
2039        ${ZSTD_CMAKE_ARGS}
2040        -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
2041        -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
2042        -DCMAKE_C_FLAGS=${EP_C_FLAGS}
2043        -DCMAKE_CXX_FLAGS=${EP_CXX_FLAGS})
2044  endif()
2045
2046  if(CMAKE_VERSION VERSION_LESS 3.7)
2047    message(FATAL_ERROR "Building zstd using ExternalProject requires at least CMake 3.7")
2048  endif()
2049
2050  externalproject_add(zstd_ep
2051                      ${EP_LOG_OPTIONS}
2052                      CMAKE_ARGS ${ZSTD_CMAKE_ARGS}
2053                      SOURCE_SUBDIR "build/cmake"
2054                      INSTALL_DIR ${ZSTD_PREFIX}
2055                      URL ${ZSTD_SOURCE_URL}
2056                      BUILD_BYPRODUCTS "${ZSTD_STATIC_LIB}")
2057
2058  file(MAKE_DIRECTORY "${ZSTD_PREFIX}/include")
2059
2060  add_library(zstd::libzstd STATIC IMPORTED)
2061  set_target_properties(zstd::libzstd
2062                        PROPERTIES IMPORTED_LOCATION "${ZSTD_STATIC_LIB}"
2063                                   INTERFACE_INCLUDE_DIRECTORIES "${ZSTD_PREFIX}/include")
2064
2065  add_dependencies(toolchain zstd_ep)
2066  add_dependencies(zstd::libzstd zstd_ep)
2067
2068  list(APPEND ARROW_BUNDLED_STATIC_LIBS zstd::libzstd)
2069endmacro()
2070
2071if(ARROW_WITH_ZSTD)
2072  resolve_dependency(zstd)
2073
2074  if(TARGET zstd::libzstd)
2075    set(ARROW_ZSTD_LIBZSTD zstd::libzstd)
2076  else()
2077    # "SYSTEM" source will prioritize cmake config, which exports
2078    # zstd::libzstd_{static,shared}
2079    if(ARROW_ZSTD_USE_SHARED)
2080      if(TARGET zstd::libzstd_shared)
2081        set(ARROW_ZSTD_LIBZSTD zstd::libzstd_shared)
2082      endif()
2083    else()
2084      if(TARGET zstd::libzstd_static)
2085        set(ARROW_ZSTD_LIBZSTD zstd::libzstd_static)
2086      endif()
2087    endif()
2088  endif()
2089
2090  # TODO: Don't use global includes but rather target_include_directories
2091  get_target_property(ZSTD_INCLUDE_DIR ${ARROW_ZSTD_LIBZSTD}
2092                      INTERFACE_INCLUDE_DIRECTORIES)
2093  include_directories(SYSTEM ${ZSTD_INCLUDE_DIR})
2094endif()
2095
2096# ----------------------------------------------------------------------
2097# RE2 (required for Gandiva)
2098
2099macro(build_re2)
2100  message(STATUS "Building RE2 from source")
2101  set(RE2_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/re2_ep-install")
2102  set(RE2_STATIC_LIB
2103      "${RE2_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}re2${CMAKE_STATIC_LIBRARY_SUFFIX}")
2104
2105  set(RE2_CMAKE_ARGS ${EP_COMMON_CMAKE_ARGS} "-DCMAKE_INSTALL_PREFIX=${RE2_PREFIX}"
2106                     -DCMAKE_INSTALL_LIBDIR=lib)
2107
2108  externalproject_add(re2_ep
2109                      ${EP_LOG_OPTIONS}
2110                      INSTALL_DIR ${RE2_PREFIX}
2111                      URL ${RE2_SOURCE_URL}
2112                      CMAKE_ARGS ${RE2_CMAKE_ARGS}
2113                      BUILD_BYPRODUCTS "${RE2_STATIC_LIB}")
2114
2115  file(MAKE_DIRECTORY "${RE2_PREFIX}/include")
2116  add_library(re2::re2 STATIC IMPORTED)
2117  set_target_properties(re2::re2
2118                        PROPERTIES IMPORTED_LOCATION "${RE2_STATIC_LIB}"
2119                                   INTERFACE_INCLUDE_DIRECTORIES "${RE2_PREFIX}/include")
2120
2121  add_dependencies(toolchain re2_ep)
2122  add_dependencies(re2::re2 re2_ep)
2123  set(RE2_VENDORED TRUE)
2124  # Set values so that FindRE2 finds this too
2125  set(RE2_LIB ${RE2_STATIC_LIB})
2126  set(RE2_INCLUDE_DIR "${RE2_PREFIX}/include")
2127
2128  list(APPEND ARROW_BUNDLED_STATIC_LIBS re2::re2)
2129endmacro()
2130
2131if(ARROW_WITH_RE2)
2132  resolve_dependency(re2 HAVE_ALT TRUE)
2133  add_definitions(-DARROW_WITH_RE2)
2134
2135  # TODO: Don't use global includes but rather target_include_directories
2136  get_target_property(RE2_INCLUDE_DIR re2::re2 INTERFACE_INCLUDE_DIRECTORIES)
2137  include_directories(SYSTEM ${RE2_INCLUDE_DIR})
2138endif()
2139
2140macro(build_bzip2)
2141  message(STATUS "Building BZip2 from source")
2142  set(BZIP2_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/bzip2_ep-install")
2143  set(
2144    BZIP2_STATIC_LIB
2145    "${BZIP2_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}bz2${CMAKE_STATIC_LIBRARY_SUFFIX}")
2146
2147  set(BZIP2_EXTRA_ARGS "CC=${CMAKE_C_COMPILER}" "CFLAGS=${EP_C_FLAGS}")
2148
2149  externalproject_add(bzip2_ep
2150                      ${EP_LOG_OPTIONS}
2151                      CONFIGURE_COMMAND ""
2152                      BUILD_IN_SOURCE 1
2153                      BUILD_COMMAND ${MAKE} libbz2.a ${MAKE_BUILD_ARGS}
2154                                    ${BZIP2_EXTRA_ARGS}
2155                      INSTALL_COMMAND ${MAKE} install PREFIX=${BZIP2_PREFIX}
2156                                      ${BZIP2_EXTRA_ARGS}
2157                      INSTALL_DIR ${BZIP2_PREFIX}
2158                      URL ${ARROW_BZIP2_SOURCE_URL}
2159                      BUILD_BYPRODUCTS "${BZIP2_STATIC_LIB}")
2160
2161  file(MAKE_DIRECTORY "${BZIP2_PREFIX}/include")
2162  add_library(BZip2::BZip2 STATIC IMPORTED)
2163  set_target_properties(
2164    BZip2::BZip2
2165    PROPERTIES IMPORTED_LOCATION "${BZIP2_STATIC_LIB}" INTERFACE_INCLUDE_DIRECTORIES
2166               "${BZIP2_PREFIX}/include")
2167  set(BZIP2_INCLUDE_DIR "${BZIP2_PREFIX}/include")
2168
2169  add_dependencies(toolchain bzip2_ep)
2170  add_dependencies(BZip2::BZip2 bzip2_ep)
2171
2172  list(APPEND ARROW_BUNDLED_STATIC_LIBS BZip2::BZip2)
2173endmacro()
2174
2175if(ARROW_WITH_BZ2)
2176  resolve_dependency(BZip2)
2177
2178  if(NOT TARGET BZip2::BZip2)
2179    add_library(BZip2::BZip2 UNKNOWN IMPORTED)
2180    set_target_properties(BZip2::BZip2
2181                          PROPERTIES IMPORTED_LOCATION "${BZIP2_LIBRARIES}"
2182                                     INTERFACE_INCLUDE_DIRECTORIES "${BZIP2_INCLUDE_DIR}")
2183  endif()
2184  include_directories(SYSTEM "${BZIP2_INCLUDE_DIR}")
2185endif()
2186
2187macro(build_utf8proc)
2188  message(STATUS "Building utf8proc from source")
2189  set(UTF8PROC_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/utf8proc_ep-install")
2190  if(MSVC)
2191    set(UTF8PROC_STATIC_LIB "${UTF8PROC_PREFIX}/lib/utf8proc_static.lib")
2192  else()
2193    set(
2194      UTF8PROC_STATIC_LIB
2195      "${UTF8PROC_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}utf8proc${CMAKE_STATIC_LIBRARY_SUFFIX}"
2196      )
2197  endif()
2198
2199  set(UTF8PROC_CMAKE_ARGS
2200      ${EP_COMMON_TOOLCHAIN}
2201      "-DCMAKE_INSTALL_PREFIX=${UTF8PROC_PREFIX}"
2202      -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
2203      -DCMAKE_INSTALL_LIBDIR=lib
2204      -DBUILD_SHARED_LIBS=OFF)
2205
2206  externalproject_add(utf8proc_ep
2207                      ${EP_LOG_OPTIONS}
2208                      CMAKE_ARGS ${UTF8PROC_CMAKE_ARGS}
2209                      INSTALL_DIR ${UTF8PROC_PREFIX}
2210                      URL ${ARROW_UTF8PROC_SOURCE_URL}
2211                      BUILD_BYPRODUCTS "${UTF8PROC_STATIC_LIB}")
2212
2213  file(MAKE_DIRECTORY "${UTF8PROC_PREFIX}/include")
2214  add_library(utf8proc::utf8proc STATIC IMPORTED)
2215  set_target_properties(utf8proc::utf8proc
2216                        PROPERTIES IMPORTED_LOCATION
2217                                   "${UTF8PROC_STATIC_LIB}"
2218                                   INTERFACE_COMPILER_DEFINITIONS
2219                                   "UTF8PROC_STATIC"
2220                                   INTERFACE_INCLUDE_DIRECTORIES
2221                                   "${UTF8PROC_PREFIX}/include")
2222
2223  add_dependencies(toolchain utf8proc_ep)
2224  add_dependencies(utf8proc::utf8proc utf8proc_ep)
2225
2226  list(APPEND ARROW_BUNDLED_STATIC_LIBS utf8proc::utf8proc)
2227endmacro()
2228
2229if(ARROW_WITH_UTF8PROC)
2230  resolve_dependency(utf8proc)
2231
2232  add_definitions(-DARROW_WITH_UTF8PROC)
2233
2234  # TODO: Don't use global definitions but rather
2235  # target_compile_definitions or target_link_libraries
2236  get_target_property(UTF8PROC_COMPILER_DEFINITIONS utf8proc::utf8proc
2237                      INTERFACE_COMPILER_DEFINITIONS)
2238  if(UTF8PROC_COMPILER_DEFINITIONS)
2239    add_definitions(-D${UTF8PROC_COMPILER_DEFINITIONS})
2240  endif()
2241
2242  # TODO: Don't use global includes but rather
2243  # target_include_directories or target_link_libraries
2244  get_target_property(UTF8PROC_INCLUDE_DIR utf8proc::utf8proc
2245                      INTERFACE_INCLUDE_DIRECTORIES)
2246  include_directories(SYSTEM ${UTF8PROC_INCLUDE_DIR})
2247endif()
2248
2249macro(build_cares)
2250  message(STATUS "Building c-ares from source")
2251  set(CARES_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/cares_ep-install")
2252  set(CARES_INCLUDE_DIR "${CARES_PREFIX}/include")
2253
2254  # If you set -DCARES_SHARED=ON then the build system names the library
2255  # libcares_static.a
2256  set(
2257    CARES_STATIC_LIB
2258    "${CARES_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}cares${CMAKE_STATIC_LIBRARY_SUFFIX}"
2259    )
2260
2261  set(CARES_CMAKE_ARGS
2262      "${EP_COMMON_CMAKE_ARGS}"
2263      -DCARES_STATIC=ON
2264      -DCARES_SHARED=OFF
2265      -DCMAKE_INSTALL_LIBDIR=lib
2266      "-DCMAKE_INSTALL_PREFIX=${CARES_PREFIX}")
2267
2268  externalproject_add(cares_ep
2269                      ${EP_LOG_OPTIONS}
2270                      URL ${CARES_SOURCE_URL}
2271                      CMAKE_ARGS ${CARES_CMAKE_ARGS}
2272                      BUILD_BYPRODUCTS "${CARES_STATIC_LIB}")
2273
2274  file(MAKE_DIRECTORY ${CARES_INCLUDE_DIR})
2275
2276  add_dependencies(toolchain cares_ep)
2277  add_library(c-ares::cares STATIC IMPORTED)
2278  set_target_properties(c-ares::cares
2279                        PROPERTIES IMPORTED_LOCATION "${CARES_STATIC_LIB}"
2280                                   INTERFACE_INCLUDE_DIRECTORIES "${CARES_INCLUDE_DIR}")
2281  add_dependencies(c-ares::cares cares_ep)
2282
2283  if(APPLE)
2284    # libresolv must be linked from c-ares version 1.16.1
2285    find_library(LIBRESOLV_LIBRARY NAMES resolv libresolv REQUIRED)
2286    set_target_properties(c-ares::cares
2287                          PROPERTIES INTERFACE_LINK_LIBRARIES "${LIBRESOLV_LIBRARY}")
2288  endif()
2289
2290  set(CARES_VENDORED TRUE)
2291
2292  list(APPEND ARROW_BUNDLED_STATIC_LIBS c-ares::cares)
2293endmacro()
2294
2295if(ARROW_WITH_GRPC)
2296  if(c-ares_SOURCE STREQUAL "AUTO")
2297    find_package(c-ares QUIET CONFIG)
2298    if(c-ares_FOUND)
2299      set(CARES_INCLUDE_DIR ${c-ares_INCLUDE_DIR})
2300    else()
2301      build_cares()
2302    endif()
2303  elseif(c-ares_SOURCE STREQUAL "BUNDLED")
2304    build_cares()
2305  elseif(c-ares_SOURCE STREQUAL "SYSTEM")
2306    find_package(c-ares REQUIRED CONFIG)
2307    set(CARES_INCLUDE_DIR ${c-ares_INCLUDE_DIR})
2308  endif()
2309
2310  # TODO: Don't use global includes but rather target_include_directories
2311  include_directories(SYSTEM ${CARES_INCLUDE_DIR})
2312endif()
2313
2314# ----------------------------------------------------------------------
2315# Dependencies for Arrow Flight RPC
2316
2317macro(build_grpc)
2318  message(STATUS "Building gRPC from source")
2319
2320  # First need to build Abseil
2321  set(ABSL_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/absl_ep-install")
2322  set(ABSL_CMAKE_ARGS
2323      "${EP_COMMON_CMAKE_ARGS}"
2324      -DABSL_RUN_TESTS=OFF
2325      -DCMAKE_CXX_STANDARD=11
2326      -DCMAKE_INSTALL_LIBDIR=lib
2327      "-DCMAKE_INSTALL_PREFIX=${ABSL_PREFIX}")
2328  set(ABSL_BUILD_BYPRODUCTS)
2329  set(ABSL_LIBRARIES)
2330
2331  # Abseil libraries gRPC depends on
2332  set(_ABSL_LIBS
2333      bad_optional_access
2334      base
2335      cord
2336      graphcycles_internal
2337      int128
2338      malloc_internal
2339      raw_logging_internal
2340      spinlock_wait
2341      stacktrace
2342      status
2343      statusor
2344      str_format_internal
2345      strings
2346      strings_internal
2347      symbolize
2348      # symbolize depends on debugging_internal
2349      debugging_internal
2350      # debugging_internal depends on demangle_internal
2351      demangle_internal
2352      synchronization
2353      throw_delegate
2354      time
2355      time_zone)
2356
2357  foreach(_ABSL_LIB ${_ABSL_LIBS})
2358    set(
2359      _ABSL_STATIC_LIBRARY
2360      "${ABSL_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}absl_${_ABSL_LIB}${CMAKE_STATIC_LIBRARY_SUFFIX}"
2361      )
2362    add_library(absl::${_ABSL_LIB} STATIC IMPORTED)
2363    set_target_properties(absl::${_ABSL_LIB}
2364                          PROPERTIES IMPORTED_LOCATION ${_ABSL_STATIC_LIBRARY})
2365    list(APPEND ABSL_BUILD_BYPRODUCTS ${_ABSL_STATIC_LIBRARY})
2366    list(APPEND ABSL_LIBRARIES absl::${_ABSL_LIB})
2367  endforeach()
2368
2369  externalproject_add(absl_ep
2370                      ${EP_LOG_OPTIONS}
2371                      URL ${ABSL_SOURCE_URL}
2372                      CMAKE_ARGS ${ABSL_CMAKE_ARGS}
2373                      BUILD_BYPRODUCTS ${ABSL_BUILD_BYPRODUCTS})
2374
2375  set(GRPC_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/grpc_ep-prefix/src/grpc_ep-build")
2376  set(GRPC_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/grpc_ep-install")
2377  set(GRPC_HOME "${GRPC_PREFIX}")
2378  set(GRPC_INCLUDE_DIR "${GRPC_PREFIX}/include")
2379
2380  set(
2381    GRPC_STATIC_LIBRARY_GPR
2382    "${GRPC_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}gpr${CMAKE_STATIC_LIBRARY_SUFFIX}")
2383  set(
2384    GRPC_STATIC_LIBRARY_GRPC
2385    "${GRPC_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}grpc${CMAKE_STATIC_LIBRARY_SUFFIX}")
2386  set(
2387    GRPC_STATIC_LIBRARY_GRPCPP
2388    "${GRPC_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}grpc++${CMAKE_STATIC_LIBRARY_SUFFIX}"
2389    )
2390  set(
2391    GRPC_STATIC_LIBRARY_ADDRESS_SORTING
2392    "${GRPC_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}address_sorting${CMAKE_STATIC_LIBRARY_SUFFIX}"
2393    )
2394  set(
2395    GRPC_STATIC_LIBRARY_UPB
2396    "${GRPC_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}upb${CMAKE_STATIC_LIBRARY_SUFFIX}")
2397  set(GRPC_CPP_PLUGIN "${GRPC_PREFIX}/bin/grpc_cpp_plugin${CMAKE_EXECUTABLE_SUFFIX}")
2398
2399  set(GRPC_CMAKE_PREFIX)
2400
2401  add_custom_target(grpc_dependencies)
2402
2403  add_dependencies(grpc_dependencies absl_ep)
2404  if(CARES_VENDORED)
2405    add_dependencies(grpc_dependencies cares_ep)
2406  endif()
2407
2408  if(GFLAGS_VENDORED)
2409    add_dependencies(grpc_dependencies gflags_ep)
2410  endif()
2411
2412  if(RE2_VENDORED)
2413    add_dependencies(grpc_dependencies re2_ep)
2414  endif()
2415
2416  add_dependencies(grpc_dependencies ${ARROW_PROTOBUF_LIBPROTOBUF} c-ares::cares
2417                   ZLIB::ZLIB)
2418
2419  get_target_property(GRPC_PROTOBUF_INCLUDE_DIR ${ARROW_PROTOBUF_LIBPROTOBUF}
2420                      INTERFACE_INCLUDE_DIRECTORIES)
2421  get_filename_component(GRPC_PB_ROOT "${GRPC_PROTOBUF_INCLUDE_DIR}" DIRECTORY)
2422  get_target_property(GRPC_Protobuf_PROTOC_LIBRARY ${ARROW_PROTOBUF_LIBPROTOC}
2423                      IMPORTED_LOCATION)
2424  get_target_property(GRPC_CARES_INCLUDE_DIR c-ares::cares INTERFACE_INCLUDE_DIRECTORIES)
2425  get_filename_component(GRPC_CARES_ROOT "${GRPC_CARES_INCLUDE_DIR}" DIRECTORY)
2426  get_target_property(GRPC_GFLAGS_INCLUDE_DIR ${GFLAGS_LIBRARIES}
2427                      INTERFACE_INCLUDE_DIRECTORIES)
2428  get_filename_component(GRPC_GFLAGS_ROOT "${GRPC_GFLAGS_INCLUDE_DIR}" DIRECTORY)
2429  get_target_property(GRPC_RE2_INCLUDE_DIR re2::re2 INTERFACE_INCLUDE_DIRECTORIES)
2430  get_filename_component(GRPC_RE2_ROOT "${GRPC_RE2_INCLUDE_DIR}" DIRECTORY)
2431
2432  set(GRPC_CMAKE_PREFIX "${GRPC_CMAKE_PREFIX};${GRPC_PB_ROOT}")
2433  set(GRPC_CMAKE_PREFIX "${GRPC_CMAKE_PREFIX};${GRPC_GFLAGS_ROOT}")
2434  set(GRPC_CMAKE_PREFIX "${GRPC_CMAKE_PREFIX};${GRPC_CARES_ROOT}")
2435  set(GRPC_CMAKE_PREFIX "${GRPC_CMAKE_PREFIX};${GRPC_RE2_ROOT}")
2436
2437  # ZLIB is never vendored
2438  set(GRPC_CMAKE_PREFIX "${GRPC_CMAKE_PREFIX};${ZLIB_ROOT}")
2439  set(GRPC_CMAKE_PREFIX "${GRPC_CMAKE_PREFIX};${ABSL_PREFIX}")
2440
2441  if(RAPIDJSON_VENDORED)
2442    add_dependencies(grpc_dependencies rapidjson_ep)
2443  endif()
2444
2445  # Yuck, see https://stackoverflow.com/a/45433229/776560
2446  string(REPLACE ";" "|" GRPC_PREFIX_PATH_ALT_SEP "${GRPC_CMAKE_PREFIX}")
2447
2448  set(GRPC_CMAKE_ARGS
2449      "${EP_COMMON_CMAKE_ARGS}"
2450      -DCMAKE_PREFIX_PATH='${GRPC_PREFIX_PATH_ALT_SEP}'
2451      -DgRPC_ABSL_PROVIDER=package
2452      -DgRPC_BUILD_CSHARP_EXT=OFF
2453      -DgRPC_BUILD_GRPC_CSHARP_PLUGIN=OFF
2454      -DgRPC_BUILD_GRPC_NODE_PLUGIN=OFF
2455      -DgRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN=OFF
2456      -DgRPC_BUILD_GRPC_PHP_PLUGIN=OFF
2457      -DgRPC_BUILD_GRPC_PYTHON_PLUGIN=OFF
2458      -DgRPC_BUILD_GRPC_RUBY_PLUGIN=OFF
2459      -DgRPC_BUILD_TESTS=OFF
2460      -DgRPC_CARES_PROVIDER=package
2461      -DgRPC_GFLAGS_PROVIDER=package
2462      -DgRPC_MSVC_STATIC_RUNTIME=${ARROW_USE_STATIC_CRT}
2463      -DgRPC_PROTOBUF_PROVIDER=package
2464      -DgRPC_RE2_PROVIDER=package
2465      -DgRPC_SSL_PROVIDER=package
2466      -DgRPC_ZLIB_PROVIDER=package
2467      -DCMAKE_INSTALL_PREFIX=${GRPC_PREFIX}
2468      -DCMAKE_INSTALL_LIBDIR=lib
2469      -DBUILD_SHARED_LIBS=OFF)
2470  if(PROTOBUF_VENDORED)
2471    list(APPEND GRPC_CMAKE_ARGS -DgRPC_PROTOBUF_PACKAGE_TYPE=CONFIG)
2472  endif()
2473  if(OPENSSL_ROOT_DIR)
2474    list(APPEND GRPC_CMAKE_ARGS -DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR})
2475  endif()
2476
2477  # XXX the gRPC git checkout is huge and takes a long time
2478  # Ideally, we should be able to use the tarballs, but they don't contain
2479  # vendored dependencies such as c-ares...
2480  externalproject_add(grpc_ep
2481                      URL ${GRPC_SOURCE_URL}
2482                      LIST_SEPARATOR |
2483                      BUILD_BYPRODUCTS ${GRPC_STATIC_LIBRARY_GPR}
2484                                       ${GRPC_STATIC_LIBRARY_GRPC}
2485                                       ${GRPC_STATIC_LIBRARY_GRPCPP}
2486                                       ${GRPC_STATIC_LIBRARY_ADDRESS_SORTING}
2487                                       ${GRPC_STATIC_LIBRARY_UPB}
2488                                       ${GRPC_CPP_PLUGIN}
2489                      CMAKE_ARGS ${GRPC_CMAKE_ARGS} ${EP_LOG_OPTIONS}
2490                      DEPENDS ${grpc_dependencies})
2491
2492  # Work around https://gitlab.kitware.com/cmake/cmake/issues/15052
2493  file(MAKE_DIRECTORY ${GRPC_INCLUDE_DIR})
2494
2495  add_library(gRPC::upb STATIC IMPORTED)
2496  set_target_properties(gRPC::upb
2497                        PROPERTIES IMPORTED_LOCATION "${GRPC_STATIC_LIBRARY_UPB}"
2498                                   INTERFACE_INCLUDE_DIRECTORIES "${GRPC_INCLUDE_DIR}")
2499
2500  add_library(gRPC::gpr STATIC IMPORTED)
2501  set_target_properties(gRPC::gpr
2502                        PROPERTIES IMPORTED_LOCATION "${GRPC_STATIC_LIBRARY_GPR}"
2503                                   INTERFACE_INCLUDE_DIRECTORIES "${GRPC_INCLUDE_DIR}")
2504
2505  add_library(gRPC::grpc STATIC IMPORTED)
2506  set_target_properties(gRPC::grpc
2507                        PROPERTIES IMPORTED_LOCATION "${GRPC_STATIC_LIBRARY_GRPC}"
2508                                   INTERFACE_INCLUDE_DIRECTORIES "${GRPC_INCLUDE_DIR}")
2509
2510  add_library(gRPC::address_sorting STATIC IMPORTED)
2511  set_target_properties(gRPC::address_sorting
2512                        PROPERTIES IMPORTED_LOCATION
2513                                   "${GRPC_STATIC_LIBRARY_ADDRESS_SORTING}"
2514                                   INTERFACE_INCLUDE_DIRECTORIES "${GRPC_INCLUDE_DIR}")
2515
2516  add_library(gRPC::grpc++ STATIC IMPORTED)
2517  set_target_properties(
2518    gRPC::grpc++
2519    PROPERTIES IMPORTED_LOCATION
2520               "${GRPC_STATIC_LIBRARY_GRPCPP}"
2521               INTERFACE_LINK_LIBRARIES
2522               "gRPC::grpc;gRPC::gpr;gRPC::upb;gRPC::address_sorting;${ABSL_LIBRARIES}"
2523               INTERFACE_INCLUDE_DIRECTORIES
2524               "${GRPC_INCLUDE_DIR}")
2525
2526  add_executable(gRPC::grpc_cpp_plugin IMPORTED)
2527  set_target_properties(gRPC::grpc_cpp_plugin
2528                        PROPERTIES IMPORTED_LOCATION ${GRPC_CPP_PLUGIN})
2529
2530  add_dependencies(grpc_ep grpc_dependencies)
2531  add_dependencies(toolchain grpc_ep)
2532  add_dependencies(gRPC::grpc++ grpc_ep)
2533  add_dependencies(gRPC::grpc_cpp_plugin grpc_ep)
2534  set(GRPC_VENDORED TRUE)
2535
2536  # ar -M rejects with the "libgrpc++.a" filename because "+" is a line
2537  # continuation character in these scripts, so we have to create a copy of the
2538  # static lib that we will bundle later
2539
2540  set(
2541    GRPC_STATIC_LIBRARY_GRPCPP_FOR_AR
2542    "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}grpcpp${CMAKE_STATIC_LIBRARY_SUFFIX}"
2543    )
2544  add_custom_command(OUTPUT ${GRPC_STATIC_LIBRARY_GRPCPP_FOR_AR}
2545                     COMMAND ${CMAKE_COMMAND}
2546                             -E
2547                             copy
2548                             $<TARGET_FILE:gRPC::grpc++>
2549                             ${GRPC_STATIC_LIBRARY_GRPCPP_FOR_AR}
2550                     DEPENDS grpc_ep)
2551  add_library(gRPC::grpcpp_for_bundling STATIC IMPORTED)
2552  set_target_properties(gRPC::grpcpp_for_bundling
2553                        PROPERTIES IMPORTED_LOCATION
2554                                   "${GRPC_STATIC_LIBRARY_GRPCPP_FOR_AR}")
2555
2556  set_source_files_properties("${GRPC_STATIC_LIBRARY_GRPCPP_FOR_AR}" PROPERTIES GENERATED
2557                              TRUE)
2558  add_custom_target(grpc_copy_grpc++ ALL DEPENDS "${GRPC_STATIC_LIBRARY_GRPCPP_FOR_AR}")
2559  add_dependencies(gRPC::grpcpp_for_bundling grpc_copy_grpc++)
2560
2561  list(APPEND ARROW_BUNDLED_STATIC_LIBS
2562              ${ABSL_LIBRARIES}
2563              gRPC::upb
2564              gRPC::gpr
2565              gRPC::grpc
2566              gRPC::address_sorting
2567              gRPC::grpcpp_for_bundling)
2568endmacro()
2569
2570if(ARROW_WITH_GRPC)
2571  set(ARROW_GRPC_REQUIRED_VERSION "1.17.0")
2572  resolve_dependency(gRPC
2573                     HAVE_ALT
2574                     TRUE
2575                     REQUIRED_VERSION
2576                     ${ARROW_GRPC_REQUIRED_VERSION})
2577
2578  if(TARGET gRPC::address_sorting)
2579    set(GRPC_HAS_ADDRESS_SORTING TRUE)
2580  else()
2581    set(GRPC_HAS_ADDRESS_SORTING FALSE)
2582  endif()
2583
2584  # TODO: Don't use global includes but rather target_include_directories
2585  get_target_property(GRPC_INCLUDE_DIR gRPC::grpc INTERFACE_INCLUDE_DIRECTORIES)
2586  include_directories(SYSTEM ${GRPC_INCLUDE_DIR})
2587
2588  if(GRPC_VENDORED)
2589    set(GRPCPP_PP_INCLUDE TRUE)
2590  else()
2591    # grpc++ headers may reside in ${GRPC_INCLUDE_DIR}/grpc++ or ${GRPC_INCLUDE_DIR}/grpcpp
2592    # depending on the gRPC version.
2593    if(EXISTS "${GRPC_INCLUDE_DIR}/grpcpp/impl/codegen/config_protobuf.h")
2594      set(GRPCPP_PP_INCLUDE TRUE)
2595    elseif(EXISTS "${GRPC_INCLUDE_DIR}/grpc++/impl/codegen/config_protobuf.h")
2596      set(GRPCPP_PP_INCLUDE FALSE)
2597    else()
2598      message(FATAL_ERROR "Cannot find grpc++ headers in ${GRPC_INCLUDE_DIR}")
2599    endif()
2600  endif()
2601endif()
2602
2603#
2604# HDFS thirdparty setup
2605
2606if(DEFINED ENV{HADOOP_HOME})
2607  set(HADOOP_HOME $ENV{HADOOP_HOME})
2608  if(NOT EXISTS "${HADOOP_HOME}/include/hdfs.h")
2609    message(STATUS "Did not find hdfs.h in expected location, using vendored one")
2610    set(HADOOP_HOME "${THIRDPARTY_DIR}/hadoop")
2611  endif()
2612else()
2613  set(HADOOP_HOME "${THIRDPARTY_DIR}/hadoop")
2614endif()
2615
2616set(HDFS_H_PATH "${HADOOP_HOME}/include/hdfs.h")
2617if(NOT EXISTS ${HDFS_H_PATH})
2618  message(FATAL_ERROR "Did not find hdfs.h at ${HDFS_H_PATH}")
2619endif()
2620message(STATUS "Found hdfs.h at: " ${HDFS_H_PATH})
2621
2622include_directories(SYSTEM "${HADOOP_HOME}/include")
2623
2624# ----------------------------------------------------------------------
2625# Apache ORC
2626
2627macro(build_orc)
2628  message("Building Apache ORC from source")
2629  set(ORC_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/orc_ep-install")
2630  set(ORC_HOME "${ORC_PREFIX}")
2631  set(ORC_INCLUDE_DIR "${ORC_PREFIX}/include")
2632  set(ORC_STATIC_LIB
2633      "${ORC_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}orc${CMAKE_STATIC_LIBRARY_SUFFIX}")
2634
2635  get_target_property(ORC_PROTOBUF_INCLUDE_DIR ${ARROW_PROTOBUF_LIBPROTOBUF}
2636                      INTERFACE_INCLUDE_DIRECTORIES)
2637  get_filename_component(ORC_PB_ROOT "${ORC_PROTOBUF_INCLUDE_DIR}" DIRECTORY)
2638  get_target_property(ORC_PROTOBUF_LIBRARY ${ARROW_PROTOBUF_LIBPROTOBUF}
2639                      IMPORTED_LOCATION)
2640
2641  get_target_property(ORC_SNAPPY_INCLUDE_DIR Snappy::snappy INTERFACE_INCLUDE_DIRECTORIES)
2642  get_filename_component(ORC_SNAPPY_ROOT "${ORC_SNAPPY_INCLUDE_DIR}" DIRECTORY)
2643
2644  get_target_property(ORC_LZ4_ROOT LZ4::lz4 INTERFACE_INCLUDE_DIRECTORIES)
2645  get_filename_component(ORC_LZ4_ROOT "${ORC_LZ4_ROOT}" DIRECTORY)
2646
2647  # Weirdly passing in PROTOBUF_LIBRARY for PROTOC_LIBRARY still results in ORC finding
2648  # the protoc library.
2649  set(ORC_CMAKE_ARGS
2650      ${EP_COMMON_CMAKE_ARGS}
2651      "-DCMAKE_INSTALL_PREFIX=${ORC_PREFIX}"
2652      -DCMAKE_CXX_FLAGS=${EP_CXX_FLAGS}
2653      -DSTOP_BUILD_ON_WARNING=OFF
2654      -DBUILD_LIBHDFSPP=OFF
2655      -DBUILD_JAVA=OFF
2656      -DBUILD_TOOLS=OFF
2657      -DBUILD_CPP_TESTS=OFF
2658      -DINSTALL_VENDORED_LIBS=OFF
2659      "-DSNAPPY_HOME=${ORC_SNAPPY_ROOT}"
2660      "-DSNAPPY_INCLUDE_DIR=${ORC_SNAPPY_INCLUDE_DIR}"
2661      "-DPROTOBUF_HOME=${ORC_PB_ROOT}"
2662      "-DPROTOBUF_INCLUDE_DIR=${ORC_PROTOBUF_INCLUDE_DIR}"
2663      "-DPROTOBUF_LIBRARY=${ORC_PROTOBUF_LIBRARY}"
2664      "-DPROTOC_LIBRARY=${ORC_PROTOBUF_LIBRARY}"
2665      "-DLZ4_HOME=${LZ4_HOME}"
2666      "-DZSTD_HOME=${ZSTD_HOME}")
2667  if(ZLIB_ROOT)
2668    set(ORC_CMAKE_ARGS ${ORC_CMAKE_ARGS} "-DZLIB_HOME=${ZLIB_ROOT}")
2669  endif()
2670
2671  # Work around CMake bug
2672  file(MAKE_DIRECTORY ${ORC_INCLUDE_DIR})
2673
2674  externalproject_add(orc_ep
2675                      URL ${ORC_SOURCE_URL}
2676                      BUILD_BYPRODUCTS ${ORC_STATIC_LIB}
2677                      CMAKE_ARGS ${ORC_CMAKE_ARGS} ${EP_LOG_OPTIONS})
2678
2679  add_dependencies(toolchain orc_ep)
2680
2681  set(ORC_VENDORED 1)
2682  add_dependencies(orc_ep ZLIB::ZLIB)
2683  add_dependencies(orc_ep LZ4::lz4)
2684  add_dependencies(orc_ep Snappy::snappy)
2685  add_dependencies(orc_ep ${ARROW_PROTOBUF_LIBPROTOBUF})
2686
2687  add_library(orc::liborc STATIC IMPORTED)
2688  set_target_properties(orc::liborc
2689                        PROPERTIES IMPORTED_LOCATION "${ORC_STATIC_LIB}"
2690                                   INTERFACE_INCLUDE_DIRECTORIES "${ORC_INCLUDE_DIR}")
2691
2692  add_dependencies(toolchain orc_ep)
2693  add_dependencies(orc::liborc orc_ep)
2694
2695  list(APPEND ARROW_BUNDLED_STATIC_LIBS orc::liborc)
2696endmacro()
2697
2698if(ARROW_ORC)
2699  resolve_dependency(ORC)
2700  include_directories(SYSTEM ${ORC_INCLUDE_DIR})
2701  message(STATUS "Found ORC static library: ${ORC_STATIC_LIB}")
2702  message(STATUS "Found ORC headers: ${ORC_INCLUDE_DIR}")
2703endif()
2704
2705# ----------------------------------------------------------------------
2706# AWS SDK for C++
2707
2708macro(build_awssdk)
2709  message("Building AWS C++ SDK from source")
2710  if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
2711     AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9")
2712    message(FATAL_ERROR "AWS C++ SDK requires gcc >= 4.9")
2713  endif()
2714  set(AWSSDK_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/awssdk_ep-install")
2715  set(AWSSDK_INCLUDE_DIR "${AWSSDK_PREFIX}/include")
2716  set(AWSSDK_LIB_DIR "lib")
2717
2718  if(WIN32)
2719    # On Windows, need to match build types
2720    set(AWSSDK_BUILD_TYPE ${CMAKE_BUILD_TYPE})
2721  else()
2722    # Otherwise, always build in release mode.
2723    # Especially with gcc, debug builds can fail with "asm constraint" errors:
2724    # https://github.com/TileDB-Inc/TileDB/issues/1351
2725    set(AWSSDK_BUILD_TYPE release)
2726  endif()
2727
2728  set(AWSSDK_COMMON_CMAKE_ARGS
2729      ${EP_COMMON_CMAKE_ARGS}
2730      -DBUILD_SHARED_LIBS=OFF
2731      -DCMAKE_BUILD_TYPE=${AWSSDK_BUILD_TYPE}
2732      -DCMAKE_INSTALL_LIBDIR=${AWSSDK_LIB_DIR}
2733      -DENABLE_TESTING=OFF
2734      -DENABLE_UNITY_BUILD=ON
2735      "-DCMAKE_INSTALL_PREFIX=${AWSSDK_PREFIX}"
2736      "-DCMAKE_PREFIX_PATH=${AWSSDK_PREFIX}")
2737
2738  set(
2739    AWSSDK_CMAKE_ARGS
2740    ${AWSSDK_COMMON_CMAKE_ARGS} -DBUILD_DEPS=OFF
2741    -DBUILD_ONLY=config\\$<SEMICOLON>s3\\$<SEMICOLON>transfer\\$<SEMICOLON>identity-management\\$<SEMICOLON>sts
2742    -DMINIMIZE_SIZE=ON)
2743  if(UNIX AND TARGET zlib_ep)
2744    list(APPEND AWSSDK_CMAKE_ARGS -DZLIB_INCLUDE_DIR=${ZLIB_INCLUDE_DIRS}
2745                -DZLIB_LIBRARY=${ZLIB_LIBRARIES})
2746  endif()
2747
2748  file(MAKE_DIRECTORY ${AWSSDK_INCLUDE_DIR})
2749
2750  # AWS C++ SDK related libraries to link statically
2751  set(_AWSSDK_LIBS
2752      aws-cpp-sdk-identity-management
2753      aws-cpp-sdk-sts
2754      aws-cpp-sdk-cognito-identity
2755      aws-cpp-sdk-s3
2756      aws-cpp-sdk-core
2757      aws-c-event-stream
2758      aws-checksums
2759      aws-c-common)
2760  set(AWSSDK_LIBRARIES)
2761  foreach(_AWSSDK_LIB ${_AWSSDK_LIBS})
2762    # aws-c-common -> AWS-C-COMMON
2763    string(TOUPPER ${_AWSSDK_LIB} _AWSSDK_LIB_UPPER)
2764    # AWS-C-COMMON -> AWS_C_COMMON
2765    string(REPLACE "-" "_" _AWSSDK_LIB_NAME_PREFIX ${_AWSSDK_LIB_UPPER})
2766    set(
2767      _AWSSDK_STATIC_LIBRARY
2768      "${AWSSDK_PREFIX}/${AWSSDK_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${_AWSSDK_LIB}${CMAKE_STATIC_LIBRARY_SUFFIX}"
2769      )
2770    if(${_AWSSDK_LIB} MATCHES "^aws-cpp-sdk-")
2771      set(_AWSSDK_TARGET_NAME ${_AWSSDK_LIB})
2772    else()
2773      set(_AWSSDK_TARGET_NAME AWS::${_AWSSDK_LIB})
2774    endif()
2775    add_library(${_AWSSDK_TARGET_NAME} STATIC IMPORTED)
2776    set_target_properties(
2777      ${_AWSSDK_TARGET_NAME}
2778      PROPERTIES IMPORTED_LOCATION ${_AWSSDK_STATIC_LIBRARY} INTERFACE_INCLUDE_DIRECTORIES
2779                 "${AWSSDK_INCLUDE_DIR}")
2780    set("${_AWSSDK_LIB_NAME_PREFIX}_STATIC_LIBRARY" ${_AWSSDK_STATIC_LIBRARY})
2781    list(APPEND AWSSDK_LIBRARIES ${_AWSSDK_TARGET_NAME})
2782  endforeach()
2783
2784  externalproject_add(aws_c_common_ep
2785                      ${EP_LOG_OPTIONS}
2786                      URL ${AWS_C_COMMON_SOURCE_URL}
2787                      CMAKE_ARGS ${AWSSDK_COMMON_CMAKE_ARGS}
2788                      BUILD_BYPRODUCTS ${AWS_C_COMMON_STATIC_LIBRARY})
2789  add_dependencies(AWS::aws-c-common aws_c_common_ep)
2790
2791  externalproject_add(aws_checksums_ep
2792                      ${EP_LOG_OPTIONS}
2793                      URL ${AWS_CHECKSUMS_SOURCE_URL}
2794                      CMAKE_ARGS ${AWSSDK_COMMON_CMAKE_ARGS}
2795                      BUILD_BYPRODUCTS ${AWS_CHECKSUMS_STATIC_LIBRARY}
2796                      DEPENDS aws_c_common_ep)
2797  add_dependencies(AWS::aws-checksums aws_checksums_ep)
2798
2799  externalproject_add(aws_c_event_stream_ep
2800                      ${EP_LOG_OPTIONS}
2801                      URL ${AWS_C_EVENT_STREAM_SOURCE_URL}
2802                      CMAKE_ARGS ${AWSSDK_COMMON_CMAKE_ARGS}
2803                      BUILD_BYPRODUCTS ${AWS_C_EVENT_STREAM_STATIC_LIBRARY}
2804                      DEPENDS aws_checksums_ep)
2805  add_dependencies(AWS::aws-c-event-stream aws_c_event_stream_ep)
2806
2807  externalproject_add(awssdk_ep
2808                      ${EP_LOG_OPTIONS}
2809                      URL ${AWSSDK_SOURCE_URL}
2810                      CMAKE_ARGS ${AWSSDK_CMAKE_ARGS}
2811                      BUILD_BYPRODUCTS ${AWS_CPP_SDK_COGNITO_IDENTITY_STATIC_LIBRARY}
2812                                       ${AWS_CPP_SDK_CORE_STATIC_LIBRARY}
2813                                       ${AWS_CPP_SDK_IDENTITY_MANAGEMENT_STATIC_LIBRARY}
2814                                       ${AWS_CPP_SDK_S3_STATIC_LIBRARY}
2815                                       ${AWS_CPP_SDK_STS_STATIC_LIBRARY}
2816                      DEPENDS aws_c_event_stream_ep)
2817  add_dependencies(toolchain awssdk_ep)
2818  foreach(_AWSSDK_LIB ${_AWSSDK_LIBS})
2819    if(${_AWSSDK_LIB} MATCHES "^aws-cpp-sdk-")
2820      add_dependencies(${_AWSSDK_LIB} awssdk_ep)
2821    endif()
2822  endforeach()
2823
2824  set(AWSSDK_VENDORED TRUE)
2825  list(APPEND ARROW_BUNDLED_STATIC_LIBS ${AWSSDK_LIBRARIES})
2826  set(AWSSDK_LINK_LIBRARIES ${AWSSDK_LIBRARIES})
2827  if(UNIX)
2828    # on Linux and macOS curl seems to be required
2829    find_package(CURL REQUIRED)
2830    if(NOT TARGET CURL::libcurl)
2831      # For CMake 3.11 or older
2832      add_library(CURL::libcurl UNKNOWN IMPORTED)
2833      set_target_properties(CURL::libcurl
2834                            PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
2835                                       "${CURL_INCLUDE_DIRS}" IMPORTED_LOCATION
2836                                       "${CURL_LIBRARIES}")
2837    endif()
2838    set_property(TARGET aws-cpp-sdk-core
2839                 APPEND
2840                 PROPERTY INTERFACE_LINK_LIBRARIES CURL::libcurl)
2841    set_property(TARGET CURL::libcurl
2842                 APPEND
2843                 PROPERTY INTERFACE_LINK_LIBRARIES OpenSSL::SSL)
2844    if(TARGET zlib_ep)
2845      set_property(TARGET aws-cpp-sdk-core
2846                   APPEND
2847                   PROPERTY INTERFACE_LINK_LIBRARIES ZLIB::ZLIB)
2848      add_dependencies(awssdk_ep zlib_ep)
2849    endif()
2850  endif()
2851
2852  # AWSSDK is static-only build
2853endmacro()
2854
2855if(ARROW_S3)
2856  # See https://aws.amazon.com/blogs/developer/developer-experience-of-the-aws-sdk-for-c-now-simplified-by-cmake/
2857
2858  # Workaround to force AWS CMake configuration to look for shared libraries
2859  if(DEFINED ENV{CONDA_PREFIX})
2860    if(DEFINED BUILD_SHARED_LIBS)
2861      set(BUILD_SHARED_LIBS_WAS_SET TRUE)
2862      set(BUILD_SHARED_LIBS_VALUE ${BUILD_SHARED_LIBS})
2863    else()
2864      set(BUILD_SHARED_LIBS_WAS_SET FALSE)
2865    endif()
2866    set(BUILD_SHARED_LIBS "ON")
2867  endif()
2868
2869  # Need to customize the find_package() call, so cannot call resolve_dependency()
2870  if(AWSSDK_SOURCE STREQUAL "AUTO")
2871    find_package(AWSSDK
2872                 COMPONENTS config
2873                            s3
2874                            transfer
2875                            identity-management
2876                            sts)
2877    if(NOT AWSSDK_FOUND)
2878      build_awssdk()
2879    endif()
2880  elseif(AWSSDK_SOURCE STREQUAL "BUNDLED")
2881    build_awssdk()
2882  elseif(AWSSDK_SOURCE STREQUAL "SYSTEM")
2883    find_package(AWSSDK REQUIRED
2884                 COMPONENTS config
2885                            s3
2886                            transfer
2887                            identity-management
2888                            sts)
2889  endif()
2890
2891  # Restore previous value of BUILD_SHARED_LIBS
2892  if(DEFINED ENV{CONDA_PREFIX})
2893    if(BUILD_SHARED_LIBS_WAS_SET)
2894      set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_VALUE})
2895    else()
2896      unset(BUILD_SHARED_LIBS)
2897    endif()
2898  endif()
2899
2900  include_directories(SYSTEM ${AWSSDK_INCLUDE_DIR})
2901  message(STATUS "Found AWS SDK headers: ${AWSSDK_INCLUDE_DIR}")
2902  message(STATUS "Found AWS SDK libraries: ${AWSSDK_LINK_LIBRARIES}")
2903
2904  if(APPLE)
2905    # CoreFoundation's path is hardcoded in the CMake files provided by
2906    # aws-sdk-cpp to use the MacOSX SDK provided by XCode which makes
2907    # XCode a hard dependency. Command Line Tools is often used instead
2908    # of the full XCode suite, so let the linker to find it.
2909    set_target_properties(AWS::aws-c-common
2910                          PROPERTIES INTERFACE_LINK_LIBRARIES
2911                                     "-pthread;pthread;-framework CoreFoundation")
2912  endif()
2913endif()
2914
2915message(STATUS "All bundled static libraries: ${ARROW_BUNDLED_STATIC_LIBS}")
2916
2917# Write out the package configurations.
2918
2919configure_file("src/arrow/util/config.h.cmake" "src/arrow/util/config.h" ESCAPE_QUOTES)
2920install(FILES "${ARROW_BINARY_DIR}/src/arrow/util/config.h"
2921        DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/arrow/util")
2922