This is an automated email from the ASF dual-hosted git repository.

lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git


The following commit(s) were added to refs/heads/main by this push:
     new d973e724b feat(c): require C++20 as the baseline (#4610)
d973e724b is described below

commit d973e724b2e8208d387e0f6084be4bbcceb9122e
Author: David Li <[email protected]>
AuthorDate: Thu Jul 30 18:35:14 2026 -0700

    feat(c): require C++20 as the baseline (#4610)
    
    Because of Ubuntu 22.04, which ships only GCC 11, we can use C++20
    language features but not all of the STL (in particular, format is not
    available - that requires GCC 13+).
---
 c/CMakeLists.txt                                   |   2 +-
 c/cmake_modules/AdbcDefines.cmake                  |   2 +-
 c/cmake_modules/BuildUtils.cmake                   |  10 +-
 c/driver/common/CMakeLists.txt                     |   2 +-
 c/driver/flightsql/CMakeLists.txt                  |   2 +-
 c/driver/framework/CMakeLists.txt                  |   2 +-
 c/driver/postgresql/CMakeLists.txt                 |   4 +-
 c/driver/sqlite/CMakeLists.txt                     |   2 +-
 c/driver_manager/CMakeLists.txt                    |   4 +-
 c/driver_manager/adbc_driver_manager.cc            |  94 +++++++++++++++++++
 .../adbc_driver_manager_driver_loading.cc          |   8 +-
 c/driver_manager/adbc_driver_manager_test.cc       |   6 +-
 c/driver_manager/current_arch.h                    | 101 +--------------------
 c/integration/duckdb/CMakeLists.txt                |   2 +-
 c/validation/CMakeLists.txt                        |   4 +-
 .../src/Makevars.in => ci/r_makevars_cxx20         |  18 ++--
 compose.yaml                                       |   1 +
 docs/source/cpp/recipe/quickstart.cc               |   4 +-
 docs/source/cpp/recipe_driver/driver_example.cc    |   4 +-
 go/adbc/drivermgr/adbc_driver_manager.cc           |  94 +++++++++++++++++++
 .../adbc_driver_manager_driver_loading.cc          |   8 +-
 go/adbc/drivermgr/current_arch.h                   | 101 +--------------------
 r/adbcdrivermanager/src/Makevars                   |   2 +-
 r/adbcdrivermanager/src/Makevars.win               |   2 +-
 r/adbcdrivermanager/src/radbc.cc                   |   7 +-
 r/adbcpostgresql/src/Makevars.in                   |   2 +-
 r/adbcpostgresql/src/Makevars.ucrt                 |   2 +-
 r/adbcpostgresql/src/Makevars.win                  |   2 +-
 r/adbcsqlite/src/Makevars.in                       |   2 +-
 29 files changed, 245 insertions(+), 249 deletions(-)

diff --git a/c/CMakeLists.txt b/c/CMakeLists.txt
index 89c31cd25..76c2a1410 100644
--- a/c/CMakeLists.txt
+++ b/c/CMakeLists.txt
@@ -23,7 +23,7 @@ project(adbc
         VERSION "${ADBC_BASE_VERSION}"
         LANGUAGES C CXX)
 set(CMAKE_C_STANDARD 99)
-set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD 20)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 include(AdbcDefines)
 include(BuildUtils)
diff --git a/c/cmake_modules/AdbcDefines.cmake 
b/c/cmake_modules/AdbcDefines.cmake
index 12b593759..df8230af2 100644
--- a/c/cmake_modules/AdbcDefines.cmake
+++ b/c/cmake_modules/AdbcDefines.cmake
@@ -172,7 +172,7 @@ if(ADBC_BUILD_TESTS)
   if(NOT GTest_FOUND)
     message(STATUS "Building googletest from source")
     # Required for GoogleTest
-    set(CMAKE_CXX_STANDARD 17)
+    set(CMAKE_CXX_STANDARD 20)
     include(FetchContent)
     fetchcontent_declare(googletest
                          URL 
https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
diff --git a/c/cmake_modules/BuildUtils.cmake b/c/cmake_modules/BuildUtils.cmake
index d7f4c2040..b76184b0e 100644
--- a/c/cmake_modules/BuildUtils.cmake
+++ b/c/cmake_modules/BuildUtils.cmake
@@ -183,7 +183,7 @@ function(ADD_ARROW_LIB LIB_NAME)
                                   ${ARG_STATIC_LINK_LIBS})
     adbc_configure_target(${LIB_NAME}_objlib)
     # https://github.com/apache/arrow-adbc/issues/81
-    target_compile_features(${LIB_NAME}_objlib PRIVATE cxx_std_11)
+    target_compile_features(${LIB_NAME}_objlib PRIVATE cxx_std_20)
   else()
     # Prepare arguments for separate compilation of static and shared libs 
below
     # TODO: add PCH directives
@@ -199,7 +199,7 @@ function(ADD_ARROW_LIB LIB_NAME)
 
   if(BUILD_SHARED)
     add_library(${LIB_NAME}_shared SHARED ${LIB_DEPS})
-    target_compile_features(${LIB_NAME}_shared PRIVATE cxx_std_17)
+    target_compile_features(${LIB_NAME}_shared PRIVATE cxx_std_20)
     set_property(TARGET ${LIB_NAME}_shared PROPERTY CXX_STANDARD_REQUIRED ON)
     adbc_configure_target(${LIB_NAME}_shared)
     if(EXTRA_DEPS)
@@ -253,7 +253,7 @@ function(ADD_ARROW_LIB LIB_NAME)
     endif()
 
     # https://github.com/apache/arrow-adbc/issues/81
-    target_compile_features(${LIB_NAME}_shared PRIVATE cxx_std_11)
+    target_compile_features(${LIB_NAME}_shared PRIVATE cxx_std_20)
 
     target_link_libraries(${LIB_NAME}_shared
                           LINK_PUBLIC
@@ -317,7 +317,7 @@ function(ADD_ARROW_LIB LIB_NAME)
 
   if(BUILD_STATIC)
     add_library(${LIB_NAME}_static STATIC ${LIB_DEPS})
-    target_compile_features(${LIB_NAME}_static PRIVATE cxx_std_11)
+    target_compile_features(${LIB_NAME}_static PRIVATE cxx_std_20)
     set_property(TARGET ${LIB_NAME}_static PROPERTY CXX_STANDARD_REQUIRED ON)
     adbc_configure_target(${LIB_NAME}_static)
     if(EXTRA_DEPS)
@@ -352,7 +352,7 @@ function(ADD_ARROW_LIB LIB_NAME)
                                      OUTPUT_NAME ${LIB_NAME_STATIC})
 
     # https://github.com/apache/arrow-adbc/issues/81
-    target_compile_features(${LIB_NAME}_static PRIVATE cxx_std_11)
+    target_compile_features(${LIB_NAME}_static PRIVATE cxx_std_20)
 
     if(ARG_STATIC_INSTALL_INTERFACE_LIBS)
       target_link_libraries(${LIB_NAME}_static LINK_PUBLIC
diff --git a/c/driver/common/CMakeLists.txt b/c/driver/common/CMakeLists.txt
index 07b9a50ad..7275e9473 100644
--- a/c/driver/common/CMakeLists.txt
+++ b/c/driver/common/CMakeLists.txt
@@ -47,7 +47,7 @@ if(ADBC_BUILD_TESTS)
                 utils_test.cc
                 EXTRA_LINK_LIBS
                 adbc_driver_common)
-  target_compile_features(adbc-driver-common-test PRIVATE cxx_std_17)
+  target_compile_features(adbc-driver-common-test PRIVATE cxx_std_20)
   target_include_directories(adbc-driver-common-test
                              PRIVATE "${REPOSITORY_ROOT}/c/include")
   adbc_configure_target(adbc-driver-common-test)
diff --git a/c/driver/flightsql/CMakeLists.txt 
b/c/driver/flightsql/CMakeLists.txt
index 300833410..37c17efee 100644
--- a/c/driver/flightsql/CMakeLists.txt
+++ b/c/driver/flightsql/CMakeLists.txt
@@ -75,7 +75,7 @@ if(ADBC_BUILD_TESTS)
     endif()
   endif()
 
-  target_compile_features(adbc-driver-flightsql-test PRIVATE cxx_std_17)
+  target_compile_features(adbc-driver-flightsql-test PRIVATE cxx_std_20)
   target_include_directories(adbc-driver-flightsql-test SYSTEM
                              PRIVATE ${REPOSITORY_ROOT}/c/ 
${REPOSITORY_ROOT}/c/include/
                                      ${REPOSITORY_ROOT}/c/driver)
diff --git a/c/driver/framework/CMakeLists.txt 
b/c/driver/framework/CMakeLists.txt
index 464f3640c..7c6e9ddac 100644
--- a/c/driver/framework/CMakeLists.txt
+++ b/c/driver/framework/CMakeLists.txt
@@ -50,7 +50,7 @@ if(ADBC_BUILD_TESTS)
                 base_driver_test.cc
                 EXTRA_LINK_LIBS
                 adbc_driver_framework)
-  target_compile_features(adbc-driver-framework-test PRIVATE cxx_std_17)
+  target_compile_features(adbc-driver-framework-test PRIVATE cxx_std_20)
   target_include_directories(adbc-driver-framework-test
                              PRIVATE "${REPOSITORY_ROOT}/c/"
                                      "${REPOSITORY_ROOT}/c/include"
diff --git a/c/driver/postgresql/CMakeLists.txt 
b/c/driver/postgresql/CMakeLists.txt
index b18dab6d4..980c3e80d 100644
--- a/c/driver/postgresql/CMakeLists.txt
+++ b/c/driver/postgresql/CMakeLists.txt
@@ -89,7 +89,7 @@ if(ADBC_BUILD_TESTS)
                 adbc_driver_common
                 adbc_validation
                 ${TEST_LINK_LIBS})
-  target_compile_features(adbc-driver-postgresql-test PRIVATE cxx_std_17)
+  target_compile_features(adbc-driver-postgresql-test PRIVATE cxx_std_20)
   target_compile_definitions(adbc-driver-postgresql-test
                              PRIVATE 
ADBC_POSTGRESQL_TESTDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/testdata"
   )
@@ -110,7 +110,7 @@ if(ADBC_BUILD_TESTS)
                 adbc_driver_common
                 adbc_validation
                 ${TEST_LINK_LIBS})
-  target_compile_features(adbc-driver-postgresql-copy-test PRIVATE cxx_std_17)
+  target_compile_features(adbc-driver-postgresql-copy-test PRIVATE cxx_std_20)
   target_include_directories(adbc-driver-postgresql-copy-test SYSTEM
                              PRIVATE ${REPOSITORY_ROOT}/c/
                                      ${REPOSITORY_ROOT}/c/include/
diff --git a/c/driver/sqlite/CMakeLists.txt b/c/driver/sqlite/CMakeLists.txt
index fcaf74488..9147d5d6e 100644
--- a/c/driver/sqlite/CMakeLists.txt
+++ b/c/driver/sqlite/CMakeLists.txt
@@ -110,7 +110,7 @@ if(ADBC_BUILD_TESTS)
                 ${TEST_LINK_LIBS})
   target_compile_definitions(adbc-driver-sqlite-test
                              PRIVATE ${ADBC_SQLITE_COMPILE_DEFINES})
-  target_compile_features(adbc-driver-sqlite-test PRIVATE cxx_std_17)
+  target_compile_features(adbc-driver-sqlite-test PRIVATE cxx_std_20)
   target_include_directories(adbc-driver-sqlite-test SYSTEM
                              PRIVATE ${REPOSITORY_ROOT}/c/ 
${REPOSITORY_ROOT}/c/include/
                                      ${LIBPQ_INCLUDE_DIRS} 
${REPOSITORY_ROOT}/c/driver)
diff --git a/c/driver_manager/CMakeLists.txt b/c/driver_manager/CMakeLists.txt
index 52c3fe46a..b13ad9161 100644
--- a/c/driver_manager/CMakeLists.txt
+++ b/c/driver_manager/CMakeLists.txt
@@ -108,7 +108,7 @@ if(ADBC_BUILD_TESTS)
                 adbc_driver_common
                 adbc_validation
                 ${TEST_LINK_LIBS})
-  target_compile_features(adbc-driver-manager-test PRIVATE cxx_std_17)
+  target_compile_features(adbc-driver-manager-test PRIVATE cxx_std_20)
   add_dependencies(adbc-driver-manager-test adbc_driver_entrypoint
                    adbc_driver_no_entrypoint)
 
@@ -153,7 +153,7 @@ if(ADBC_BUILD_TESTS)
                 EXTRA_LINK_LIBS
                 adbc_validation_util
                 ${TEST_LINK_LIBS})
-  target_compile_features(adbc-version-100-compatibility-test PRIVATE 
cxx_std_17)
+  target_compile_features(adbc-version-100-compatibility-test PRIVATE 
cxx_std_20)
   target_include_directories(adbc-version-100-compatibility-test SYSTEM
                              PRIVATE ${REPOSITORY_ROOT}/c/ 
${REPOSITORY_ROOT}/c/include/
                                      ${LIBPQ_INCLUDE_DIRS} 
${REPOSITORY_ROOT}/c/driver)
diff --git a/c/driver_manager/adbc_driver_manager.cc 
b/c/driver_manager/adbc_driver_manager.cc
index b3acca942..1a9fe7f36 100644
--- a/c/driver_manager/adbc_driver_manager.cc
+++ b/c/driver_manager/adbc_driver_manager.cc
@@ -104,6 +104,100 @@ std::string CheckNonPrintableLibraryName(const 
std::string& name) {
   return error_message;
 }
 
+const std::string& InternalAdbcCurrentArch() {
+#if defined(_WIN32)
+  static const std::string platform = "windows";
+#elif defined(__APPLE__)
+  static const std::string platform = "macos";
+#elif defined(__FreeBSD__)
+  static const std::string platform = "freebsd";
+#elif defined(__OpenBSD__)
+  static const std::string platform = "openbsd";
+#elif defined(__linux__)
+  static const std::string platform = "linux";
+#else
+  static const std::string platform = "unknown";
+#endif
+
+#if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) || 
defined(_M_AMD64)
+  static const std::string arch = "amd64";
+#elif defined(__aarch64__) || defined(_M_ARM64) || defined(__ARM_ARCH_ISA_A64)
+#ifdef ADBC_LITTLE_ENDIAN
+  static const std::string arch = "arm64";
+#else
+  static const std::string arch = "arm64be";
+#endif
+#elif defined(__i386__) || defined(_M_IX86) || defined(_M_X86)
+  static const std::string arch = "x86";
+#elif defined(__arm__) || defined(_M_ARM)
+#ifdef ADBC_LITTLE_ENDIAN
+  static const std::string arch = "arm";
+#else
+  static const std::string arch = "armbe";
+#endif
+#elif defined(__riscv) || defined(_M_RISCV)
+#if defined(__riscv_xlen) && __riscv_xlen == 64
+  static const std::string arch = "riscv64";
+#else
+  static const std::string arch = "riscv";
+#endif
+#elif defined(__ppc64__) || defined(__powerpc64__)
+#ifdef ADBC_LITTLE_ENDIAN
+  static const std::string arch = "powerpc64le";
+#else
+  static const std::string arch = "powerpc64";
+#endif
+#elif defined(__powerpc__) || defined(__ppc__) || defined(_M_PPC)
+  static const std::string arch = "powerpc";
+#elif defined(__s390x__) || defined(_M_S390)
+  static const std::string arch = "s390x";
+#elif defined(__sparc__) || defined(__sparc)
+#if defined(_LP64) || defined(__LP64__)
+  static const std::string arch = "sparc64";
+#else
+  static const std::string arch = "sparc";
+#endif
+#elif defined(__wasm32__)
+  static const std::string arch = "wasm32";
+#elif defined(__wasm64__)
+  static const std::string arch = "wasm64";
+#else
+  static const std::string arch = "unknown";
+#endif
+
+// musl doesn't actually define any preprocessor macro for itself
+// but apparently it doesn't define __USE_GNU inside of features.h
+// while gcc DOES define that.
+// see 
https://stackoverflow.com/questions/58177815/how-to-actually-detect-musl-libc
+#if defined(_WIN32) || defined(__APPLE__) || defined(__FreeBSD__)
+#else
+#if !defined(_GNU_SOURCE)
+#define _GNU_SOURCE
+#include <features.h>  // NOLINT [build/include]
+#ifndef __USE_GNU
+#define __MUSL__
+#endif
+#undef _GNU_SOURCE /* don't contaminate other includes unnecessarily */
+#else
+#include <features.h>  // NOLINT [build/include]
+#ifndef __USE_GNU
+#define __MUSL__
+#endif
+#endif
+#endif
+
+#if defined(__MINGW32__) || defined(__MINGW64__)
+  static const std::string target = "_mingw";
+#elif defined(__MUSL__)
+  static const std::string target = "_musl";
+#else
+  static const std::string target = "";
+#endif
+
+  static const std::string result = platform + "_" + arch + target;
+  return result;
+}
+
 // Platform-specific helpers
 
 #if defined(_WIN32)
diff --git a/c/driver_manager/adbc_driver_manager_driver_loading.cc 
b/c/driver_manager/adbc_driver_manager_driver_loading.cc
index 632184b58..c17956057 100644
--- a/c/driver_manager/adbc_driver_manager_driver_loading.cc
+++ b/c/driver_manager/adbc_driver_manager_driver_loading.cc
@@ -195,12 +195,12 @@ AdbcStatusCode LoadDriverManifest(const 
std::filesystem::path& driver_manifest,
 
   auto driver = config.at_path("Driver.shared");
   if (toml::table* platforms = driver.as_table()) {
-    auto view = platforms->at_path(adbc::CurrentArch());
+    auto view = platforms->at_path(InternalAdbcCurrentArch());
     if (!view) {
       std::string message = "Driver path not found in manifest '";
       message += driver_manifest.string();
       message += "' for current architecture '";
-      message += adbc::CurrentArch();
+      message += InternalAdbcCurrentArch();
       message += "'. Architectures found:";
       for (const auto& [key, val] : *platforms) {
         message += " ";
@@ -213,7 +213,7 @@ AdbcStatusCode LoadDriverManifest(const 
std::filesystem::path& driver_manifest,
         std::string message = "Driver path is an empty string in manifest '";
         message += driver_manifest.string();
         message += "' for current architecture '";
-        message += adbc::CurrentArch();
+        message += InternalAdbcCurrentArch();
         message += "'";
         SetError(error, std::move(message));
         return ADBC_STATUS_INVALID_ARGUMENT;
@@ -225,7 +225,7 @@ AdbcStatusCode LoadDriverManifest(const 
std::filesystem::path& driver_manifest,
     std::string message = "Driver path not found in manifest '";
     message += driver_manifest.string();
     message += "' for current architecture '";
-    message += adbc::CurrentArch();
+    message += InternalAdbcCurrentArch();
     message += "'. Value was not a string";
     SetError(error, std::move(message));
     return ADBC_STATUS_INVALID_ARGUMENT;
diff --git a/c/driver_manager/adbc_driver_manager_test.cc 
b/c/driver_manager/adbc_driver_manager_test.cc
index 823b862bb..3417b90c8 100644
--- a/c/driver_manager/adbc_driver_manager_test.cc
+++ b/c/driver_manager/adbc_driver_manager_test.cc
@@ -716,7 +716,7 @@ class DriverManifest : public ::testing::Test {
          toml::table{
              {"shared",
               toml::table{
-                  {adbc::CurrentArch(), driver_path.string()},
+                  {InternalAdbcCurrentArch(), driver_path.string()},
               }},
          }},
     };
@@ -829,7 +829,7 @@ TEST_F(DriverManifest, ConfigEntrypoint) {
                     {"entrypoint", "BadEntrypointSymbolName"},
                     {"shared",
                      toml::table{
-                         {adbc::CurrentArch(), driver_path.string()},
+                         {InternalAdbcCurrentArch(), driver_path.string()},
                      }},
                 });
 
@@ -2166,7 +2166,7 @@ class DriverUriProfileTest : public ConnectionProfiles,
          toml::table{
              {"shared",
               toml::table{
-                  {adbc::CurrentArch(), driver_path.string()},
+                  {InternalAdbcCurrentArch(), driver_path.string()},
               }},
          }},
     };
diff --git a/c/driver_manager/current_arch.h b/c/driver_manager/current_arch.h
index e6b475ec0..6c3009425 100644
--- a/c/driver_manager/current_arch.h
+++ b/c/driver_manager/current_arch.h
@@ -19,6 +19,8 @@
 
 #include <string>
 
+#include "arrow-adbc/adbc.h"
+
 #if defined(_WIN32)
 #define ADBC_LITTLE_ENDIAN 1
 #else
@@ -40,100 +42,5 @@
 #endif
 #endif
 
-namespace adbc {
-
-inline const std::string& CurrentArch() {
-#if defined(_WIN32)
-  static const std::string platform = "windows";
-#elif defined(__APPLE__)
-  static const std::string platform = "macos";
-#elif defined(__FreeBSD__)
-  static const std::string platform = "freebsd";
-#elif defined(__OpenBSD__)
-  static const std::string platform = "openbsd";
-#elif defined(__linux__)
-  static const std::string platform = "linux";
-#else
-  static const std::string platform = "unknown";
-#endif
-
-#if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) || 
defined(_M_AMD64)
-  static const std::string arch = "amd64";
-#elif defined(__aarch64__) || defined(_M_ARM64) || defined(__ARM_ARCH_ISA_A64)
-#ifdef ADBC_LITTLE_ENDIAN
-  static const std::string arch = "arm64";
-#else
-  static const std::string arch = "arm64be";
-#endif
-#elif defined(__i386__) || defined(_M_IX86) || defined(_M_X86)
-  static const std::string arch = "x86";
-#elif defined(__arm__) || defined(_M_ARM)
-#ifdef ADBC_LITTLE_ENDIAN
-  static const std::string arch = "arm";
-#else
-  static const std::string arch = "armbe";
-#endif
-#elif defined(__riscv) || defined(_M_RISCV)
-#if defined(__riscv_xlen) && __riscv_xlen == 64
-  static const std::string arch = "riscv64";
-#else
-  static const std::string arch = "riscv";
-#endif
-#elif defined(__ppc64__) || defined(__powerpc64__)
-#ifdef ADBC_LITTLE_ENDIAN
-  static const std::string arch = "powerpc64le";
-#else
-  static const std::string arch = "powerpc64";
-#endif
-#elif defined(__powerpc__) || defined(__ppc__) || defined(_M_PPC)
-  static const std::string arch = "powerpc";
-#elif defined(__s390x__) || defined(_M_S390)
-  static const std::string arch = "s390x";
-#elif defined(__sparc__) || defined(__sparc)
-#if defined(_LP64) || defined(__LP64__)
-  static const std::string arch = "sparc64";
-#else
-  static const std::string arch = "sparc";
-#endif
-#elif defined(__wasm32__)
-  static const std::string arch = "wasm32";
-#elif defined(__wasm64__)
-  static const std::string arch = "wasm64";
-#else
-  static const std::string arch = "unknown";
-#endif
-
-// musl doesn't actually define any preprocessor macro for itself
-// but apparently it doesn't define __USE_GNU inside of features.h
-// while gcc DOES define that.
-// see 
https://stackoverflow.com/questions/58177815/how-to-actually-detect-musl-libc
-#if defined(_WIN32) || defined(__APPLE__) || defined(__FreeBSD__)
-#else
-#if !defined(_GNU_SOURCE)
-#define _GNU_SOURCE
-#include <features.h>  // NOLINT [build/include]
-#ifndef __USE_GNU
-#define __MUSL__
-#endif
-#undef _GNU_SOURCE /* don't contaminate other includes unnecessarily */
-#else
-#include <features.h>  // NOLINT [build/include]
-#ifndef __USE_GNU
-#define __MUSL__
-#endif
-#endif
-#endif
-
-#if defined(__MINGW32__) || defined(__MINGW64__)
-  static const std::string target = "_mingw";
-#elif defined(__MUSL__)
-  static const std::string target = "_musl";
-#else
-  static const std::string target = "";
-#endif
-
-  static const std::string result = platform + "_" + arch + target;
-  return result;
-}
-
-}  // namespace adbc
+ADBC_EXPORT
+const std::string& InternalAdbcCurrentArch();
diff --git a/c/integration/duckdb/CMakeLists.txt 
b/c/integration/duckdb/CMakeLists.txt
index 1db2575d6..d4b3db0c0 100644
--- a/c/integration/duckdb/CMakeLists.txt
+++ b/c/integration/duckdb/CMakeLists.txt
@@ -65,7 +65,7 @@ if(ADBC_BUILD_TESTS)
                 adbc_validation
                 duckdb)
   add_dependencies(adbc-integration-duckdb-test duckdb)
-  target_compile_features(adbc-integration-duckdb-test PRIVATE cxx_std_17)
+  target_compile_features(adbc-integration-duckdb-test PRIVATE cxx_std_20)
   target_include_directories(adbc-integration-duckdb-test SYSTEM
                              PRIVATE ${REPOSITORY_ROOT}/c/ 
${REPOSITORY_ROOT}/c/include/
                                      ${REPOSITORY_ROOT}/c/driver)
diff --git a/c/validation/CMakeLists.txt b/c/validation/CMakeLists.txt
index 02362259f..8f6d98907 100644
--- a/c/validation/CMakeLists.txt
+++ b/c/validation/CMakeLists.txt
@@ -17,7 +17,7 @@
 
 add_library(adbc_validation_util STATIC adbc_validation_util.cc)
 adbc_configure_target(adbc_validation_util)
-target_compile_features(adbc_validation_util PRIVATE cxx_std_17)
+target_compile_features(adbc_validation_util PRIVATE cxx_std_20)
 target_include_directories(adbc_validation_util SYSTEM
                            PRIVATE "${REPOSITORY_ROOT}/c/include/"
                                    "${REPOSITORY_ROOT}/c/driver/")
@@ -28,7 +28,7 @@ add_library(adbc_validation OBJECT
             adbc_validation.cc adbc_validation_connection.cc 
adbc_validation_database.cc
             adbc_validation_statement.cc)
 adbc_configure_target(adbc_validation)
-target_compile_features(adbc_validation PRIVATE cxx_std_17)
+target_compile_features(adbc_validation PRIVATE cxx_std_20)
 target_include_directories(adbc_validation SYSTEM PRIVATE 
"${REPOSITORY_ROOT}/c/include/"
                                                           
"${REPOSITORY_ROOT}/c/driver/")
 target_link_libraries(adbc_validation PUBLIC adbc_driver_common 
adbc_validation_util
diff --git a/r/adbcsqlite/src/Makevars.in b/ci/r_makevars_cxx20
similarity index 65%
copy from r/adbcsqlite/src/Makevars.in
copy to ci/r_makevars_cxx20
index 675ff8cd2..2d030a449 100644
--- a/r/adbcsqlite/src/Makevars.in
+++ b/ci/r_makevars_cxx20
@@ -15,15 +15,9 @@
 # specific language governing permissions and limitations
 # under the License.
 
-CXX_STD = CXX17
-PKG_CPPFLAGS=-I../src/c -I../src/c/include -I../src/c/vendor/ 
-I../src/c/vendor/fmt/include @cppflags@ -DADBC_EXPORT="" -DFMT_HEADER_ONLY=1
-PKG_LIBS=@libs@
-
-OBJECTS = init.o \
-    c/driver/common/utils.o \
-    c/driver/framework/objects.o \
-    c/driver/framework/utility.o \
-    c/driver/sqlite/sqlite.o \
-    c/driver/sqlite/statement_reader.o \
-    c/vendor/nanoarrow/nanoarrow.o \
-    @objects@
+# conda-forge's R package doesn't define C++20 compiler settings, even though
+# its compiler supports C++20; define the flags to get the docs build to work
+CXX20 = $(CXX17)
+CXX20FLAGS = $(CXX17FLAGS)
+CXX20PICFLAGS = $(CXX17PICFLAGS)
+CXX20STD = -std=gnu++20
diff --git a/compose.yaml b/compose.yaml
index 4b67f755a..4a978f560 100644
--- a/compose.yaml
+++ b/compose.yaml
@@ -100,6 +100,7 @@ services:
       ADBC_USE_ASAN: "0"
       ADBC_USE_UBSAN: "0"
       CGO_ENABLED: "1"
+      R_MAKEVARS_USER: "/adbc/ci/r_makevars_cxx20"
     command: |
       /bin/bash -c 'git config --global --add safe.directory /adbc && source 
/opt/conda/etc/profile.d/conda.sh && mamba create -y -n adbc -c conda-forge go 
--file /adbc/ci/conda_env_cpp.txt --file /adbc/ci/conda_env_docs.txt --file 
/adbc/ci/conda_env_java.txt --file /adbc/ci/conda_env_python.txt && conda 
activate adbc && /adbc/ci/scripts/cpp_build.sh /adbc /adbc/build && 
/adbc/ci/scripts/go_build.sh /adbc /adbc/build && 
/adbc/ci/scripts/python_build.sh /adbc /adbc/build && /adbc/ci/scrip [...]
 
diff --git a/docs/source/cpp/recipe/quickstart.cc 
b/docs/source/cpp/recipe/quickstart.cc
index 36a5e19d6..0148094d6 100644
--- a/docs/source/cpp/recipe/quickstart.cc
+++ b/docs/source/cpp/recipe/quickstart.cc
@@ -18,7 +18,7 @@
 // RECIPE STARTS HERE
 
 /// Here we'll briefly tour basic features of ADBC with the SQLite
-/// driver in C++17.
+/// driver in C++20.
 
 /// Installation
 /// ============
@@ -27,7 +27,7 @@
 /// the repository, build the sample, and follow along.
 ///
 /// We'll assume you're using conda-forge_ for dependencies.  CMake, a
-/// C++17 compiler, and the ADBC libraries are required.  They can be
+/// C++20 compiler, and the ADBC libraries are required.  They can be
 /// installed as follows:
 ///
 /// .. code-block:: shell
diff --git a/docs/source/cpp/recipe_driver/driver_example.cc 
b/docs/source/cpp/recipe_driver/driver_example.cc
index 5b4685ba8..bba7d280a 100644
--- a/docs/source/cpp/recipe_driver/driver_example.cc
+++ b/docs/source/cpp/recipe_driver/driver_example.cc
@@ -36,7 +36,7 @@
 /// the repository, build the sample, and follow along.
 ///
 /// We'll assume you're using conda-forge_ for dependencies.  CMake, a
-/// C++17 compiler, and the ADBC libraries are required.  They can be
+/// C++20 compiler, and the ADBC libraries are required.  They can be
 /// installed as follows:
 ///
 /// .. code-block:: shell
@@ -193,7 +193,7 @@ class DriverExampleDatabase : public 
adbc::driver::Database<DriverExampleDatabas
 /// Another role of the connection is to provide metadata about tables, 
columns,
 /// statistics, and other catalog-like information a caller might want to know 
before
 /// issuing a query. The driver framework base classes provide helpers to 
implement these
-/// functions such that you can mostly implement them in terms of the C++17 
standard
+/// functions such that you can mostly implement them in terms of the C++20 
standard
 /// library (as opposed to building the C-level arrays yourself).
 
 class DriverExampleConnection : public 
adbc::driver::Connection<DriverExampleConnection> {
diff --git a/go/adbc/drivermgr/adbc_driver_manager.cc 
b/go/adbc/drivermgr/adbc_driver_manager.cc
index b3acca942..1a9fe7f36 100644
--- a/go/adbc/drivermgr/adbc_driver_manager.cc
+++ b/go/adbc/drivermgr/adbc_driver_manager.cc
@@ -104,6 +104,100 @@ std::string CheckNonPrintableLibraryName(const 
std::string& name) {
   return error_message;
 }
 
+const std::string& InternalAdbcCurrentArch() {
+#if defined(_WIN32)
+  static const std::string platform = "windows";
+#elif defined(__APPLE__)
+  static const std::string platform = "macos";
+#elif defined(__FreeBSD__)
+  static const std::string platform = "freebsd";
+#elif defined(__OpenBSD__)
+  static const std::string platform = "openbsd";
+#elif defined(__linux__)
+  static const std::string platform = "linux";
+#else
+  static const std::string platform = "unknown";
+#endif
+
+#if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) || 
defined(_M_AMD64)
+  static const std::string arch = "amd64";
+#elif defined(__aarch64__) || defined(_M_ARM64) || defined(__ARM_ARCH_ISA_A64)
+#ifdef ADBC_LITTLE_ENDIAN
+  static const std::string arch = "arm64";
+#else
+  static const std::string arch = "arm64be";
+#endif
+#elif defined(__i386__) || defined(_M_IX86) || defined(_M_X86)
+  static const std::string arch = "x86";
+#elif defined(__arm__) || defined(_M_ARM)
+#ifdef ADBC_LITTLE_ENDIAN
+  static const std::string arch = "arm";
+#else
+  static const std::string arch = "armbe";
+#endif
+#elif defined(__riscv) || defined(_M_RISCV)
+#if defined(__riscv_xlen) && __riscv_xlen == 64
+  static const std::string arch = "riscv64";
+#else
+  static const std::string arch = "riscv";
+#endif
+#elif defined(__ppc64__) || defined(__powerpc64__)
+#ifdef ADBC_LITTLE_ENDIAN
+  static const std::string arch = "powerpc64le";
+#else
+  static const std::string arch = "powerpc64";
+#endif
+#elif defined(__powerpc__) || defined(__ppc__) || defined(_M_PPC)
+  static const std::string arch = "powerpc";
+#elif defined(__s390x__) || defined(_M_S390)
+  static const std::string arch = "s390x";
+#elif defined(__sparc__) || defined(__sparc)
+#if defined(_LP64) || defined(__LP64__)
+  static const std::string arch = "sparc64";
+#else
+  static const std::string arch = "sparc";
+#endif
+#elif defined(__wasm32__)
+  static const std::string arch = "wasm32";
+#elif defined(__wasm64__)
+  static const std::string arch = "wasm64";
+#else
+  static const std::string arch = "unknown";
+#endif
+
+// musl doesn't actually define any preprocessor macro for itself
+// but apparently it doesn't define __USE_GNU inside of features.h
+// while gcc DOES define that.
+// see 
https://stackoverflow.com/questions/58177815/how-to-actually-detect-musl-libc
+#if defined(_WIN32) || defined(__APPLE__) || defined(__FreeBSD__)
+#else
+#if !defined(_GNU_SOURCE)
+#define _GNU_SOURCE
+#include <features.h>  // NOLINT [build/include]
+#ifndef __USE_GNU
+#define __MUSL__
+#endif
+#undef _GNU_SOURCE /* don't contaminate other includes unnecessarily */
+#else
+#include <features.h>  // NOLINT [build/include]
+#ifndef __USE_GNU
+#define __MUSL__
+#endif
+#endif
+#endif
+
+#if defined(__MINGW32__) || defined(__MINGW64__)
+  static const std::string target = "_mingw";
+#elif defined(__MUSL__)
+  static const std::string target = "_musl";
+#else
+  static const std::string target = "";
+#endif
+
+  static const std::string result = platform + "_" + arch + target;
+  return result;
+}
+
 // Platform-specific helpers
 
 #if defined(_WIN32)
diff --git a/go/adbc/drivermgr/adbc_driver_manager_driver_loading.cc 
b/go/adbc/drivermgr/adbc_driver_manager_driver_loading.cc
index 632184b58..c17956057 100644
--- a/go/adbc/drivermgr/adbc_driver_manager_driver_loading.cc
+++ b/go/adbc/drivermgr/adbc_driver_manager_driver_loading.cc
@@ -195,12 +195,12 @@ AdbcStatusCode LoadDriverManifest(const 
std::filesystem::path& driver_manifest,
 
   auto driver = config.at_path("Driver.shared");
   if (toml::table* platforms = driver.as_table()) {
-    auto view = platforms->at_path(adbc::CurrentArch());
+    auto view = platforms->at_path(InternalAdbcCurrentArch());
     if (!view) {
       std::string message = "Driver path not found in manifest '";
       message += driver_manifest.string();
       message += "' for current architecture '";
-      message += adbc::CurrentArch();
+      message += InternalAdbcCurrentArch();
       message += "'. Architectures found:";
       for (const auto& [key, val] : *platforms) {
         message += " ";
@@ -213,7 +213,7 @@ AdbcStatusCode LoadDriverManifest(const 
std::filesystem::path& driver_manifest,
         std::string message = "Driver path is an empty string in manifest '";
         message += driver_manifest.string();
         message += "' for current architecture '";
-        message += adbc::CurrentArch();
+        message += InternalAdbcCurrentArch();
         message += "'";
         SetError(error, std::move(message));
         return ADBC_STATUS_INVALID_ARGUMENT;
@@ -225,7 +225,7 @@ AdbcStatusCode LoadDriverManifest(const 
std::filesystem::path& driver_manifest,
     std::string message = "Driver path not found in manifest '";
     message += driver_manifest.string();
     message += "' for current architecture '";
-    message += adbc::CurrentArch();
+    message += InternalAdbcCurrentArch();
     message += "'. Value was not a string";
     SetError(error, std::move(message));
     return ADBC_STATUS_INVALID_ARGUMENT;
diff --git a/go/adbc/drivermgr/current_arch.h b/go/adbc/drivermgr/current_arch.h
index e6b475ec0..6c3009425 100644
--- a/go/adbc/drivermgr/current_arch.h
+++ b/go/adbc/drivermgr/current_arch.h
@@ -19,6 +19,8 @@
 
 #include <string>
 
+#include "arrow-adbc/adbc.h"
+
 #if defined(_WIN32)
 #define ADBC_LITTLE_ENDIAN 1
 #else
@@ -40,100 +42,5 @@
 #endif
 #endif
 
-namespace adbc {
-
-inline const std::string& CurrentArch() {
-#if defined(_WIN32)
-  static const std::string platform = "windows";
-#elif defined(__APPLE__)
-  static const std::string platform = "macos";
-#elif defined(__FreeBSD__)
-  static const std::string platform = "freebsd";
-#elif defined(__OpenBSD__)
-  static const std::string platform = "openbsd";
-#elif defined(__linux__)
-  static const std::string platform = "linux";
-#else
-  static const std::string platform = "unknown";
-#endif
-
-#if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) || 
defined(_M_AMD64)
-  static const std::string arch = "amd64";
-#elif defined(__aarch64__) || defined(_M_ARM64) || defined(__ARM_ARCH_ISA_A64)
-#ifdef ADBC_LITTLE_ENDIAN
-  static const std::string arch = "arm64";
-#else
-  static const std::string arch = "arm64be";
-#endif
-#elif defined(__i386__) || defined(_M_IX86) || defined(_M_X86)
-  static const std::string arch = "x86";
-#elif defined(__arm__) || defined(_M_ARM)
-#ifdef ADBC_LITTLE_ENDIAN
-  static const std::string arch = "arm";
-#else
-  static const std::string arch = "armbe";
-#endif
-#elif defined(__riscv) || defined(_M_RISCV)
-#if defined(__riscv_xlen) && __riscv_xlen == 64
-  static const std::string arch = "riscv64";
-#else
-  static const std::string arch = "riscv";
-#endif
-#elif defined(__ppc64__) || defined(__powerpc64__)
-#ifdef ADBC_LITTLE_ENDIAN
-  static const std::string arch = "powerpc64le";
-#else
-  static const std::string arch = "powerpc64";
-#endif
-#elif defined(__powerpc__) || defined(__ppc__) || defined(_M_PPC)
-  static const std::string arch = "powerpc";
-#elif defined(__s390x__) || defined(_M_S390)
-  static const std::string arch = "s390x";
-#elif defined(__sparc__) || defined(__sparc)
-#if defined(_LP64) || defined(__LP64__)
-  static const std::string arch = "sparc64";
-#else
-  static const std::string arch = "sparc";
-#endif
-#elif defined(__wasm32__)
-  static const std::string arch = "wasm32";
-#elif defined(__wasm64__)
-  static const std::string arch = "wasm64";
-#else
-  static const std::string arch = "unknown";
-#endif
-
-// musl doesn't actually define any preprocessor macro for itself
-// but apparently it doesn't define __USE_GNU inside of features.h
-// while gcc DOES define that.
-// see 
https://stackoverflow.com/questions/58177815/how-to-actually-detect-musl-libc
-#if defined(_WIN32) || defined(__APPLE__) || defined(__FreeBSD__)
-#else
-#if !defined(_GNU_SOURCE)
-#define _GNU_SOURCE
-#include <features.h>  // NOLINT [build/include]
-#ifndef __USE_GNU
-#define __MUSL__
-#endif
-#undef _GNU_SOURCE /* don't contaminate other includes unnecessarily */
-#else
-#include <features.h>  // NOLINT [build/include]
-#ifndef __USE_GNU
-#define __MUSL__
-#endif
-#endif
-#endif
-
-#if defined(__MINGW32__) || defined(__MINGW64__)
-  static const std::string target = "_mingw";
-#elif defined(__MUSL__)
-  static const std::string target = "_musl";
-#else
-  static const std::string target = "";
-#endif
-
-  static const std::string result = platform + "_" + arch + target;
-  return result;
-}
-
-}  // namespace adbc
+ADBC_EXPORT
+const std::string& InternalAdbcCurrentArch();
diff --git a/r/adbcdrivermanager/src/Makevars b/r/adbcdrivermanager/src/Makevars
index 9fb3d05c2..5476c6e35 100644
--- a/r/adbcdrivermanager/src/Makevars
+++ b/r/adbcdrivermanager/src/Makevars
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-CXX_STD = CXX17
+CXX_STD = CXX20
 CONDA_BUILD ?= "0"
 PKG_CPPFLAGS=-I../src/c/include -I../src/c -I../src/c/vendor -DADBC_EXPORT="" 
-DADBC_CONDA_BUILD=$(CONDA_BUILD)
 
diff --git a/r/adbcdrivermanager/src/Makevars.win 
b/r/adbcdrivermanager/src/Makevars.win
index 908b9439b..6a086d369 100644
--- a/r/adbcdrivermanager/src/Makevars.win
+++ b/r/adbcdrivermanager/src/Makevars.win
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-CXX_STD = CXX17
+CXX_STD = CXX20
 CONDA_BUILD ?= "0"
 PKG_CPPFLAGS=-I../src/c/include -I../src/c -I../src/c/vendor -DADBC_EXPORT="" 
-DADBC_CONDA_BUILD=$(CONDA_BUILD)
 PKG_LIBS=-lshell32 -ladvapi32 -luuid
diff --git a/r/adbcdrivermanager/src/radbc.cc b/r/adbcdrivermanager/src/radbc.cc
index 22565cde6..a81e47cb2 100644
--- a/r/adbcdrivermanager/src/radbc.cc
+++ b/r/adbcdrivermanager/src/radbc.cc
@@ -102,12 +102,11 @@ static void finalize_database_xptr(SEXP database_xptr) {
   adbc_xptr_default_finalize<AdbcDatabase>(database_xptr);
 }
 
-namespace adbc {
-const std::string& CurrentArch();
-}
+// Forward declared from the driver manager; we can't use its internal header 
here
+const std::string& InternalAdbcCurrentArch();
 
 extern "C" SEXP RAdbcCurrentArch(void) {
-  auto current_arch = adbc::CurrentArch();
+  auto current_arch = InternalAdbcCurrentArch();
   return Rf_mkString(current_arch.c_str());
 }
 
diff --git a/r/adbcpostgresql/src/Makevars.in b/r/adbcpostgresql/src/Makevars.in
index 45320aa7d..b35a4dc85 100644
--- a/r/adbcpostgresql/src/Makevars.in
+++ b/r/adbcpostgresql/src/Makevars.in
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-CXX_STD = CXX17
+CXX_STD = CXX20
 PKG_CPPFLAGS=-I../src/c -I../src/c/include -I../src/c/vendor/ 
-I../src/c/vendor/portable-snippets/include/ -I../src/c/vendor/fmt/include 
@cppflags@ -DADBC_EXPORT="" -DFMT_HEADER_ONLY=1
 PKG_LIBS=@libs@
 
diff --git a/r/adbcpostgresql/src/Makevars.ucrt 
b/r/adbcpostgresql/src/Makevars.ucrt
index 3a14f02dc..77ec9c666 100644
--- a/r/adbcpostgresql/src/Makevars.ucrt
+++ b/r/adbcpostgresql/src/Makevars.ucrt
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-CXX_STD = CXX17
+CXX_STD = CXX20
 PKG_CPPFLAGS = -I../src/c -I../src/c/include -I../src/c/vendor/ 
-I../src/c/vendor/portable-snippets/include/ -I../src/c/vendor/fmt/include 
-DADBC_EXPORT="" -D__USE_MINGW_ANSI_STDIO -DFMT_HEADER_ONLY=1
 
 PKG_LIBS = -lpq -lpgcommon -lpgport -lssl -lcrypto -lz -lsecur32 -lws2_32 
-lwldap32 -lcrypt32
diff --git a/r/adbcpostgresql/src/Makevars.win 
b/r/adbcpostgresql/src/Makevars.win
index 077a69ea1..aaba18ecf 100644
--- a/r/adbcpostgresql/src/Makevars.win
+++ b/r/adbcpostgresql/src/Makevars.win
@@ -17,7 +17,7 @@
 
 VERSION = 13.2.0
 RWINLIB = ../windows/libpq-$(VERSION)
-CXX_STD = CXX17
+CXX_STD = CXX20
 PKG_CPPFLAGS = -I$(RWINLIB)/include -I../src/c -I../src/c/include 
-I../src/c/vendor/ -I../src/c/vendor/portable-snippets/include/ 
-I../src/c/vendor/fmt/include -DADBC_EXPORT="" -D__USE_MINGW_ANSI_STDIO 
-DFMT_HEADER_ONLY=1
 PKG_LIBS = -L$(RWINLIB)/lib${R_ARCH}${CRT} \
        -lpq -lpgport -lpgcommon -lssl -lcrypto -lwsock32 -lsecur32 -lws2_32 
-lgdi32 -lcrypt32 -lwldap32
diff --git a/r/adbcsqlite/src/Makevars.in b/r/adbcsqlite/src/Makevars.in
index 675ff8cd2..53a68c0cf 100644
--- a/r/adbcsqlite/src/Makevars.in
+++ b/r/adbcsqlite/src/Makevars.in
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-CXX_STD = CXX17
+CXX_STD = CXX20
 PKG_CPPFLAGS=-I../src/c -I../src/c/include -I../src/c/vendor/ 
-I../src/c/vendor/fmt/include @cppflags@ -DADBC_EXPORT="" -DFMT_HEADER_ONLY=1
 PKG_LIBS=@libs@
 

Reply via email to