Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,10 @@ endif()

include(SetupCxxFlags)

# GH-51267: resolve the datetime backend (C++20 std::chrono vs the vendored
# datetime fallback) with toolchain feature detection.
include(CheckStdChrono)

if(${CMAKE_CXX_FLAGS_DEBUG} MATCHES "-Og")
# GH-47475: xxhash fails inlining when -Og is used.
# See: https://github.com/Cyan4973/xxHash/issues/943
Expand Down
97 changes: 97 additions & 0 deletions cpp/cmake_modules/CheckStdChrono.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

# Resolve the ARROW_USE_STD_CHRONO option (AUTO, ON or OFF) into a boolean.
#
# GH-51267 tracks removing the vendored datetime fallback once all supported
# toolchains provide working C++20 chrono timezone support. Until then:
# - AUTO keeps the historical platform default: std::chrono is used on Windows
# toolchains whose standard library provides working C++20 chrono timezone
# support, and the vendored datetime fallback is used everywhere else.
# - ON opts into std::chrono unconditionally, failing the configure step when
# the toolchain does not provide working C++20 chrono timezone support.
# - OFF always uses the vendored datetime fallback.
#
# The resolved value is consumed via arrow/util/config.h (ARROW_USE_STD_CHRONO)
# by arrow/util/chrono_internal.h and to decide whether the vendored datetime
# implementation is built.

# When Arrow is consumed as a CMake subproject, ARROW_USE_STD_CHRONO is not
# defined; skip detection and let arrow/util/chrono_internal.h fall back to its
# default backend selection (vendored datetime fallback).
if(DEFINED ARROW_USE_STD_CHRONO)
if(NOT "${ARROW_USE_STD_CHRONO}" MATCHES "^(AUTO|ON|OFF)$")
message(FATAL_ERROR "ARROW_USE_STD_CHRONO must be one of AUTO, ON or OFF "
"(got \"${ARROW_USE_STD_CHRONO}\")")
endif()

set(_ARROW_STD_CHRONO_TEST_SOURCE
"
#include <chrono>
#if !defined(__cpp_lib_chrono) || __cpp_lib_chrono < 201907L
# error \"C++20 chrono timezone support (__cpp_lib_chrono >= 201907L) is unavailable\"
#endif
int main() { return 0; }
Comment on lines +44 to +48
")

function(_arrow_check_std_chrono_support out_var)
# Arrow pins the project-wide standard to C++20 (SetupCxxFlags), so
# try_compile already compiles the probe with /std:c++20. Passing the
# switch a second time through CMAKE_REQUIRED_FLAGS made the probe fail
# spuriously under CMake 4 + MSVC, which silently downgraded Windows
# AUTO builds to the vendored backend whose tzdb lookups then fail at
# runtime. The compiler output is surfaced on failure so a probe
# regression is diagnosable from CI directly.
try_compile(${out_var}
SOURCE_FROM_VAR "arrow_std_chrono_probe.cxx"
_ARROW_STD_CHRONO_TEST_SOURCE
OUTPUT_VARIABLE _chrono_probe_output)
if(NOT ${out_var})
message(STATUS "C++20 chrono probe failed with:\n${_chrono_probe_output}")
endif()
endfunction()

if("${ARROW_USE_STD_CHRONO}" STREQUAL "AUTO")
if(WIN32)
_arrow_check_std_chrono_support(ARROW_HAVE_STD_CHRONO)
if(ARROW_HAVE_STD_CHRONO)
set(ARROW_USE_STD_CHRONO ON)
else()
message(STATUS "C++20 chrono timezone support unavailable,"
" using vendored datetime fallback")
set(ARROW_USE_STD_CHRONO OFF)
endif()
else()
# Non-Windows toolchains keep the vendored fallback until the minimum
# toolchain prerequisites in GH-51267 are met. Toolchains with validated
# support can opt into std::chrono with -DARROW_USE_STD_CHRONO=ON.
set(ARROW_USE_STD_CHRONO OFF)
endif()
elseif(ARROW_USE_STD_CHRONO)
_arrow_check_std_chrono_support(ARROW_HAVE_STD_CHRONO)
if(NOT ARROW_HAVE_STD_CHRONO)
message(FATAL_ERROR "ARROW_USE_STD_CHRONO=ON requires working C++20 chrono "
"timezone support (__cpp_lib_chrono >= 201907L), which "
"the current toolchain does not provide")
endif()
endif()

message(STATUS "Using C++20 std::chrono datetime backend: ${ARROW_USE_STD_CHRONO}")

endif()

unset(_ARROW_STD_CHRONO_TEST_SOURCE)
8 changes: 8 additions & 0 deletions cpp/cmake_modules/DefineOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,14 @@ takes precedence over ccache if a storage backend is configured" ON)

define_option(ARROW_WITH_MUSL "Whether the system libc is musl or not" OFF)

define_option_string(ARROW_USE_STD_CHRONO
"Use C++20 std::chrono instead of the vendored datetime library;\
AUTO keeps the current platform default (GH-51267)"
"AUTO"
"AUTO"
"ON"
"OFF")

define_option(ARROW_ENABLE_THREADING "Enable threading in Arrow core" ON)

#----------------------------------------------------------------------
Expand Down
30 changes: 30 additions & 0 deletions cpp/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,36 @@ needs_zlib = get_option('zlib').enabled()
needs_zstd = get_option('zstd').enabled()
needs_utilities = get_option('utilities').enabled()

# GH-51267: resolve the datetime backend (C++20 std::chrono vs the vendored
# datetime fallback) with toolchain feature detection. This mirrors the
# ARROW_USE_STD_CHRONO CMake option.
std_chrono_probe_src = '''
#include <chrono>
#if !defined(__cpp_lib_chrono) || __cpp_lib_chrono < 201907L
#error "C++20 chrono timezone support (__cpp_lib_chrono >= 201907L) is unavailable"
#endif
int main() { return 0; }
'''
have_std_chrono = cpp_compiler.links(
std_chrono_probe_src,
name: 'C++20 chrono timezone support',
)
std_chrono_opt = get_option('use_std_chrono')
if std_chrono_opt.enabled()
if not have_std_chrono
error('use_std_chrono=enabled requires working C++20 chrono timezone '
+ 'support, which the current toolchain does not provide')
endif
needs_std_chrono = true
elif std_chrono_opt.disabled()
needs_std_chrono = false
else
# auto: keep the historical platform default (std::chrono on Windows
# toolchains with timezone support, vendored fallback elsewhere) until the
# minimum-toolchain prerequisites in GH-51267 are met.
needs_std_chrono = host_machine.system() == 'windows' and have_std_chrono
endif

if needs_flight or needs_substrait
protobuf_dep = dependency('protobuf')
protoc = find_program('protoc')
Expand Down
8 changes: 8 additions & 0 deletions cpp/meson.options
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,14 @@ option(
type: 'feature',
description: 'Build the Arrow googletest unit tests',
)
option(
'use_std_chrono',
type: 'feature',
value: 'auto',
description: '''
Use C++20 std::chrono instead of the vendored datetime library;
auto keeps the current platform default (GH-51267)''',
)
option(
'utf8proc',
type: 'feature',
Expand Down
27 changes: 26 additions & 1 deletion cpp/src/arrow/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,21 @@ string(REPLACE "${CMAKE_BINARY_DIR}" "<CMAKE_BINARY_DIR>" REDACTED_CXX_FLAGS
cmake_path(GET PROJECT_SOURCE_DIR PARENT_PATH ARROW_PROJECT_SOURCE_DIR)
string(REPLACE "${ARROW_PROJECT_SOURCE_DIR}" "<ARROW_PROJECT_SOURCE_DIR>"
REDACTED_CXX_FLAGS ${REDACTED_CXX_FLAGS})
# GH-51267: emit the resolved datetime backend, but keep the macro undefined
# when the option is unset (Arrow as a subproject with ARROW_DEFINE_OPTIONS=OFF)
# so chrono_internal.h's platform fallback still decides there — #cmakedefine01
# would emit 0 and flip those builds from the std::chrono default to the
# vendored fallback. An explicit OFF must stay 0 so the fallback cannot
# re-enable std::chrono against the user's choice.
if(DEFINED ARROW_USE_STD_CHRONO)
if(ARROW_USE_STD_CHRONO)
set(ARROW_USE_STD_CHRONO_DEFINITION "#define ARROW_USE_STD_CHRONO 1")
else()
set(ARROW_USE_STD_CHRONO_DEFINITION "#define ARROW_USE_STD_CHRONO 0")
endif()
else()
set(ARROW_USE_STD_CHRONO_DEFINITION "/* #undef ARROW_USE_STD_CHRONO */")
endif()
configure_file("util/config.h.cmake" "util/config.h" ESCAPE_QUOTES)
configure_file("util/config_internal.h.cmake" "util/config_internal.h" ESCAPE_QUOTES)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/util/config.h"
Expand Down Expand Up @@ -549,9 +564,19 @@ set(ARROW_VENDORED_SRCS
vendored/uriparser/UriRecompose.c
vendored/uriparser/UriResolve.c
vendored/uriparser/UriShorten.c)
if(APPLE)
if(APPLE AND NOT ARROW_USE_STD_CHRONO)
list(APPEND ARROW_VENDORED_SRCS vendored/datetime/ios.mm)
endif()
if(ARROW_USE_STD_CHRONO AND NOT ARROW_GANDIVA)
# GH-51267: standard-backend binaries use C++20 std::chrono and do not bundle
# the vendored datetime implementation. The remaining direct users of
# arrow/vendored/datetime.h (formatting, parsing, pretty printing) only rely
# on its header-only calendar types — except Gandiva, whose cast_time.cc and
# gdv_function_stubs.cc call the timezone functions defined in
# vendored/datetime.cpp and link arrow_shared/arrow_static, so the TU is
# kept whenever Gandiva is built.
list(REMOVE_ITEM ARROW_VENDORED_SRCS vendored/datetime.cpp)
endif()
set_source_files_properties(vendored/datetime.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION
ON)
arrow_add_object_library(ARROW_VENDORED ${ARROW_VENDORED_SRCS})
Expand Down
26 changes: 21 additions & 5 deletions cpp/src/arrow/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@
#include "arrow/util/config.h"
#include "arrow/util/config_internal.h"
#include "arrow/util/cpu_info.h"
#include "arrow/vendored/datetime.h"
// GH-51267: only the vendored datetime backend bundles the vendored timezone
// implementation; std::chrono builds use the OS timezone database instead.
#if !defined(ARROW_USE_STD_CHRONO) || !ARROW_USE_STD_CHRONO
# include "arrow/vendored/datetime.h"
#endif

namespace arrow {

Expand Down Expand Up @@ -64,7 +68,9 @@ std::string MakeSimdLevelString(QueryFlagFunction&& query_flag) {
}
}

#if !defined(ARROW_USE_STD_CHRONO) || !ARROW_USE_STD_CHRONO
std::optional<std::string> timezone_db_path;
#endif // ARROW_USE_STD_CHRONO

}; // namespace

Expand All @@ -77,11 +83,17 @@ RuntimeInfo GetRuntimeInfo() {
MakeSimdLevelString([&](int64_t flags) { return cpu_info->IsSupported(flags); });
info.detected_simd_level =
MakeSimdLevelString([&](int64_t flags) { return cpu_info->IsDetected(flags); });
#if defined(ARROW_USE_STD_CHRONO) && ARROW_USE_STD_CHRONO
// GH-51267: std::chrono builds always use the OS timezone database.
info.using_os_timezone_db = true;
info.timezone_db_path = std::optional<std::string>();
#else
Comment on lines +86 to +90
info.using_os_timezone_db = USE_OS_TZDB;
#if !USE_OS_TZDB
# if !USE_OS_TZDB
info.timezone_db_path = timezone_db_path;
#else
# else
info.timezone_db_path = std::optional<std::string>();
# endif
#endif
return info;
}
Expand All @@ -91,7 +103,11 @@ RuntimeInfo GetRuntimeInfo() {
Status Initialize(const GlobalOptions& options) noexcept {
ARROW_SUPPRESS_DEPRECATION_WARNING
if (options.timezone_db_path.has_value()) {
#if !USE_OS_TZDB
#if defined(ARROW_USE_STD_CHRONO) && ARROW_USE_STD_CHRONO
return Status::Invalid(
"Arrow was built with C++20 std::chrono and uses the OS timezone database, "
"so a downloaded database cannot be provided at runtime.");
Comment thread
Adarsh-Me marked this conversation as resolved.
Comment on lines +106 to +109
#elif !USE_OS_TZDB
try {
arrow_vendored::date::set_install(options.timezone_db_path.value());
arrow_vendored::date::reload_tzdb();
Expand All @@ -103,7 +119,7 @@ Status Initialize(const GlobalOptions& options) noexcept {
return Status::Invalid(
"Arrow was set to use OS timezone database at compile time, "
"so a downloaded database cannot be provided at runtime.");
#endif // !USE_OS_TZDB
#endif // ARROW_USE_STD_CHRONO / USE_OS_TZDB
}
ARROW_UNSUPPRESS_DEPRECATION_WARNING
return Status::OK();
Expand Down
65 changes: 35 additions & 30 deletions cpp/src/arrow/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,40 @@ else
simdjson_dep = disabler()
endif

# GH-51267: standard-backend builds (use_std_chrono) use C++20 std::chrono and
# do not bundle the vendored datetime implementation. All other builds keep it
# as a fallback.
arrow_vendored_sources = ['vendored/base64.cpp']
if not needs_std_chrono
arrow_vendored_sources += 'vendored/datetime.cpp'
endif
arrow_vendored_sources += [
'vendored/double-conversion/bignum-dtoa.cc',
'vendored/double-conversion/bignum.cc',
'vendored/double-conversion/cached-powers.cc',
'vendored/double-conversion/double-to-string.cc',
'vendored/double-conversion/fast-dtoa.cc',
'vendored/double-conversion/fixed-dtoa.cc',
'vendored/double-conversion/string-to-double.cc',
'vendored/double-conversion/strtod.cc',
'vendored/musl/strptime.c',
'vendored/uriparser/UriCommon.c',
'vendored/uriparser/UriCompare.c',
'vendored/uriparser/UriEscape.c',
'vendored/uriparser/UriFile.c',
'vendored/uriparser/UriIp4.c',
'vendored/uriparser/UriIp4Base.c',
'vendored/uriparser/UriMemory.c',
'vendored/uriparser/UriNormalize.c',
'vendored/uriparser/UriNormalizeBase.c',
'vendored/uriparser/UriParse.c',
'vendored/uriparser/UriParseBase.c',
'vendored/uriparser/UriQuery.c',
'vendored/uriparser/UriRecompose.c',
'vendored/uriparser/UriResolve.c',
'vendored/uriparser/UriShorten.c',
]

arrow_components = {
'arrow_array': {
'sources': [
Expand Down Expand Up @@ -113,36 +147,7 @@ arrow_components = {
'dependencies': [dl_dep],
},
'memory_pool': {'sources': ['memory_pool.cc']},
'vendored': {
'sources': [
'vendored/base64.cpp',
'vendored/datetime.cpp',
'vendored/double-conversion/bignum-dtoa.cc',
'vendored/double-conversion/bignum.cc',
'vendored/double-conversion/cached-powers.cc',
'vendored/double-conversion/double-to-string.cc',
'vendored/double-conversion/fast-dtoa.cc',
'vendored/double-conversion/fixed-dtoa.cc',
'vendored/double-conversion/string-to-double.cc',
'vendored/double-conversion/strtod.cc',
'vendored/musl/strptime.c',
'vendored/uriparser/UriCommon.c',
'vendored/uriparser/UriCompare.c',
'vendored/uriparser/UriEscape.c',
'vendored/uriparser/UriFile.c',
'vendored/uriparser/UriIp4.c',
'vendored/uriparser/UriIp4Base.c',
'vendored/uriparser/UriMemory.c',
'vendored/uriparser/UriNormalize.c',
'vendored/uriparser/UriNormalizeBase.c',
'vendored/uriparser/UriParse.c',
'vendored/uriparser/UriParseBase.c',
'vendored/uriparser/UriQuery.c',
'vendored/uriparser/UriRecompose.c',
'vendored/uriparser/UriResolve.c',
'vendored/uriparser/UriShorten.c',
],
},
'vendored': {'sources': arrow_vendored_sources},
'arrow_base': {
'sources': [
'builder.cc',
Expand Down
5 changes: 4 additions & 1 deletion cpp/src/arrow/public_api_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <string>

#include "arrow/config.h"
#include "arrow/util/config.h"

// Include various "api.h" entrypoints and check they don't leak internal symbols

Expand Down Expand Up @@ -125,7 +126,9 @@ TEST(Misc, BuildInfo) {
// TODO(GH-48593): Remove when libc++ supports std::chrono timezones.
ARROW_SUPPRESS_DEPRECATION_WARNING
TEST(Misc, SetTimezoneConfig) {
#ifndef _WIN32
#if defined(ARROW_USE_STD_CHRONO) && ARROW_USE_STD_CHRONO
GTEST_SKIP() << "std::chrono builds use the OS timezone database (GH-51267)";
#elif !defined(_WIN32)
GTEST_SKIP() << "Can only set the Timezone database on Windows";
#elif !defined(ARROW_FILESYSTEM)
GTEST_SKIP() << "Need filesystem support to test timezone config.";
Expand Down
Loading
Loading