This is an automated email from the ASF dual-hosted git repository.
raulcd pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new 8fa322c3e24 GH-49538: [C++][FlightRPC][ODBC] Use static linkage in
Windows FlightSQL ODBC driver (#49585)
8fa322c3e24 is described below
commit 8fa322c3e24b326859f947b2b699e95feb0303f7
Author: Bryce Mecum <[email protected]>
AuthorDate: Tue Sep 29 00:44:27 2026 -0700
GH-49538: [C++][FlightRPC][ODBC] Use static linkage in Windows FlightSQL
ODBC driver (#49585)
### Rationale for this change
The FlightSQL ODBC driver was previously using dynamic linkage for the
Arrow deps it relies on. This worked but prevented a challenge for code signing
because (I think) we'd have to sign each DLL and signing costs money. We can
use static linkage with a dynamically linked MSVC runtime so we only have one
DLL to sign.
Ref: https://github.com/apache/arrow/issues/49404
### What changes are included in this PR?
Updates to CMake and CI for the build to allow static linkage with dynamic
MSVC runtime (`x64-windows-static-md`).
### Are these changes tested?
Yes.
### Are there any user-facing changes?
No.
* GitHub Issue: #49538
Authored-by: Bryce Mecum <[email protected]>
Signed-off-by: Raúl Cumplido <[email protected]>
---
.github/workflows/cpp_extra.yml | 8 ++-
.github/workflows/package_odbc.yml | 11 ++--
ci/vcpkg/amd64-windows-no-absl-sync-release.cmake | 4 +-
cpp/cmake_modules/FindGTestAlt.cmake | 6 ++
cpp/src/arrow/flight/CMakeLists.txt | 4 +-
cpp/src/arrow/flight/sql/CMakeLists.txt | 5 ++
cpp/src/arrow/flight/sql/odbc/CMakeLists.txt | 44 ++++++++------
.../arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt | 42 +++++++++----
cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt | 69 +++++++++++-----------
.../arrow/flight/sql/odbc/tests/odbc_test_suite.cc | 24 ++++++++
.../arrow/flight/transport/grpc/customize_grpc.h | 38 ++++++++++--
11 files changed, 175 insertions(+), 80 deletions(-)
diff --git a/.github/workflows/cpp_extra.yml b/.github/workflows/cpp_extra.yml
index 046e95292b0..6c12048050f 100644
--- a/.github/workflows/cpp_extra.yml
+++ b/.github/workflows/cpp_extra.yml
@@ -689,8 +689,8 @@ jobs:
contents: read
packages: write
env:
- ARROW_BUILD_SHARED: ON
- ARROW_BUILD_STATIC: OFF
+ ARROW_BUILD_SHARED: OFF
+ ARROW_BUILD_STATIC: ON
ARROW_BUILD_TESTS: ON
ARROW_BUILD_TYPE: release
# Turn Arrow CSV off to disable `find_package(Arrow)` check on MSVC CI.
@@ -706,6 +706,10 @@ jobs:
# Build Arrow with GPR_DISABLE_ABSEIL_SYNC so grpcpp's Mutex ABI
# matches the gRPC rebuilt by the overlay triplet. Remove once fixed
upstream.
ARROW_CXXFLAGS: -DGPR_DISABLE_ABSEIL_SYNC
+ ARROW_DEPENDENCY_USE_SHARED: OFF
+ ARROW_MIMALLOC: OFF
+ ARROW_TEST_LINKAGE: static
+ ARROW_USE_STATIC_CRT: OFF
CMAKE_GENERATOR: Ninja
CMAKE_INSTALL_PREFIX: /usr
VCPKG_BINARY_SOURCES: 'clear;nugettimeout,600;nuget,GitHub,readwrite'
diff --git a/.github/workflows/package_odbc.yml
b/.github/workflows/package_odbc.yml
index cc2aad00aca..8bab30e5b4c 100644
--- a/.github/workflows/package_odbc.yml
+++ b/.github/workflows/package_odbc.yml
@@ -50,21 +50,24 @@ jobs:
permissions:
packages: write
env: &odbc_msvc_env
- ARROW_BUILD_SHARED: ON
- ARROW_BUILD_STATIC: OFF
+ ARROW_BUILD_SHARED: OFF
+ ARROW_BUILD_STATIC: ON
ARROW_BUILD_TESTS: OFF
ARROW_BUILD_TYPE: release
- # Turn Arrow CSV off to disable `find_package(Arrow)` check on MSVC CI.
+ # Turn Arrow CSV off to disable `find_package(Arrow)` check on MSVC CI.
# GH-49050 TODO: enable `find_package(Arrow)` check on MSVC CI.
ARROW_CSV: OFF
ARROW_DEPENDENCY_SOURCE: VCPKG
+ ARROW_DEPENDENCY_USE_SHARED: OFF
ARROW_FLIGHT_SQL_ODBC: ON
ARROW_FLIGHT_SQL_ODBC_INSTALLER: ON
ARROW_HOME: /usr
+ ARROW_MIMALLOC: OFF
+ ARROW_USE_STATIC_CRT: OFF
CMAKE_GENERATOR: Ninja
CMAKE_INSTALL_PREFIX: /usr
VCPKG_BINARY_SOURCES: 'clear;nugettimeout,600;nuget,GitHub,readwrite'
- VCPKG_DEFAULT_TRIPLET: x64-windows
+ VCPKG_DEFAULT_TRIPLET: x64-windows-static-md
steps:
- name: Checkout Arrow
uses: actions/checkout@v7
diff --git a/ci/vcpkg/amd64-windows-no-absl-sync-release.cmake
b/ci/vcpkg/amd64-windows-no-absl-sync-release.cmake
index 97c73e31464..436650842ad 100644
--- a/ci/vcpkg/amd64-windows-no-absl-sync-release.cmake
+++ b/ci/vcpkg/amd64-windows-no-absl-sync-release.cmake
@@ -17,10 +17,10 @@
# GH-49465: rebuild gRPC with native sync instead of absl::Mutex to avoid the
# Windows exit hang. See the ODBC Windows job in cpp_extra.yml
-# Dynamic CRT/linkage and release-only to match that job.
+# Static library linkage, dynamic CRT (/MD), release-only to match that job.
set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE dynamic)
-set(VCPKG_LIBRARY_LINKAGE dynamic)
+set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_BUILD_TYPE release)
set(VCPKG_C_FLAGS "/DGPR_DISABLE_ABSEIL_SYNC")
diff --git a/cpp/cmake_modules/FindGTestAlt.cmake
b/cpp/cmake_modules/FindGTestAlt.cmake
index d1873d138e6..766fbfc9422 100644
--- a/cpp/cmake_modules/FindGTestAlt.cmake
+++ b/cpp/cmake_modules/FindGTestAlt.cmake
@@ -38,7 +38,12 @@ find_package(GTest ${find_package_args})
set(GTestAlt_FOUND ${GTest_FOUND})
if(GTestAlt_FOUND AND GTestAlt_NEED_CXX_STANDARD_CHECK)
set(KEEP_CMAKE_TRY_COMPILE_TARGET_TYPE ${CMAKE_TRY_COMPILE_TARGET_TYPE})
+ set(KEEP_CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_TRY_COMPILE_CONFIGURATION})
set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
+ # Match the parent build when dependencies are available for only one
configuration.
+ if(NOT CMAKE_TRY_COMPILE_CONFIGURATION)
+ set(CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_BUILD_TYPE})
+ endif()
set(GTestAlt_CXX_STANDARD_TEST_SOURCE
"${CMAKE_CURRENT_BINARY_DIR}/gtest_cxx_standard_test.cc")
file(WRITE ${GTestAlt_CXX_STANDARD_TEST_SOURCE}
@@ -56,6 +61,7 @@ TEST(CXX_STANDARD, MatcherStringView) {
LINK_LIBRARIES GTest::gtest_main
OUTPUT_VARIABLE GTestAlt_CXX_STANDARD_OUTPUT)
set(CMAKE_TRY_COMPILE_TARGET_TYPE ${KEEP_CMAKE_TRY_COMPILE_TARGET_TYPE})
+ set(CMAKE_TRY_COMPILE_CONFIGURATION ${KEEP_CMAKE_TRY_COMPILE_CONFIGURATION})
if(NOT GTestAlt_CXX_STANDARD_AVAILABLE)
message(STATUS "GTest can't be used with C++${CMAKE_CXX_STANDARD}.")
message(STATUS "Use -DGTest_SOURCE=BUNDLED.")
diff --git a/cpp/src/arrow/flight/CMakeLists.txt
b/cpp/src/arrow/flight/CMakeLists.txt
index 8974c9581f7..91afab15702 100644
--- a/cpp/src/arrow/flight/CMakeLists.txt
+++ b/cpp/src/arrow/flight/CMakeLists.txt
@@ -123,9 +123,9 @@ function(arrow_set_generated_proto_files_properties)
set(GENERATED_FILES ${ARGN})
set_source_files_properties(${GENERATED_FILES} PROPERTIES GENERATED TRUE)
if(MSVC)
- # Suppress missing dll-interface warning
+ # Suppress warnings caused by Protobuf (dll-interface)
set_source_files_properties(${GENERATED_FILES}
- PROPERTIES COMPILE_OPTIONS "/wd4251"
+ PROPERTIES COMPILE_OPTIONS "/wd4251;/wd4275"
SKIP_UNITY_BUILD_INCLUSION TRUE)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# Disable -Wmissing-declarations
diff --git a/cpp/src/arrow/flight/sql/CMakeLists.txt
b/cpp/src/arrow/flight/sql/CMakeLists.txt
index 2299bdfe0a3..6e01672248d 100644
--- a/cpp/src/arrow/flight/sql/CMakeLists.txt
+++ b/cpp/src/arrow/flight/sql/CMakeLists.txt
@@ -99,6 +99,10 @@ if(MSVC)
endif()
foreach(LIB_TARGET ${ARROW_FLIGHT_SQL_LIBRARIES})
target_compile_definitions(${LIB_TARGET} PRIVATE ARROW_FLIGHT_SQL_EXPORTING)
+ if(MSVC)
+ # Suppress warnings caused by Protobuf (dll-interface)
+ target_compile_options(${LIB_TARGET} PRIVATE "/wd4275")
+ endif()
endforeach()
if(ARROW_FLIGHT_TEST_LINKAGE STREQUAL "static" AND ARROW_BUILD_STATIC)
@@ -177,6 +181,7 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
ARROW_FLIGHT_SQL_STATIC)
endforeach()
endif()
+
endif()
if(ARROW_FLIGHT_SQL_ODBC)
diff --git a/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt
b/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt
index 181d855fde4..178d144bac3 100644
--- a/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt
+++ b/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt
@@ -59,28 +59,41 @@ if(WIN32)
list(APPEND ARROW_FLIGHT_SQL_ODBC_SRCS odbc.def install/versioninfo.rc)
endif()
-# On Windows, dynmaic build for ODBC is supported.
-# On unix systems, static build for ODBC is supported, all libraries are
linked statically on unix.
-set(ARROW_FLIGHT_SQL_ODBC_DEPENDENCIES "")
+# Initialize install interface libs (only set in Windows static build)
set(ARROW_FLIGHT_SQL_ODBC_SHARED_INSTALL_INTERFACE_LIBS "")
set(ARROW_FLIGHT_SQL_ODBC_STATIC_INSTALL_INTERFACE_LIBS "")
set(ARROW_FLIGHT_SQL_ODBC_SHARED_PRIVATE_LINK_LIBS "")
+
if(WIN32)
- set(ARROW_FLIGHT_SQL_ODBC_DEPENDENCIES arrow_flight_sql)
- set(ARROW_FLIGHT_SQL_ODBC_SHARED_LINK_LIBS arrow_flight_sql_shared
arrow_odbc_spi_impl)
- set(ARROW_FLIGHT_SQL_ODBC_STATIC_LINK_LIBS arrow_flight_sql_static)
- list(APPEND ARROW_FLIGHT_SQL_ODBC_SHARED_INSTALL_INTERFACE_LIBS
- ArrowFlight::arrow_flight_sql_shared)
- list(APPEND ARROW_FLIGHT_SQL_ODBC_STATIC_INSTALL_INTERFACE_LIBS
- ArrowFlight::arrow_flight_sql_static)
+ if(ARROW_BUILD_STATIC)
+ # Static Arrow deps on Windows — self-contained ODBC DLL
+ set(ARROW_FLIGHT_SQL_ODBC_SHARED_LINK_LIBS arrow_flight_sql_static
+ arrow_odbc_spi_impl)
+ set(ARROW_FLIGHT_SQL_ODBC_STATIC_LINK_LIBS arrow_flight_sql_static)
+ list(APPEND ARROW_FLIGHT_SQL_ODBC_SHARED_INSTALL_INTERFACE_LIBS
+ ArrowFlight::arrow_flight_sql_static)
+ list(APPEND ARROW_FLIGHT_SQL_ODBC_STATIC_INSTALL_INTERFACE_LIBS
+ ArrowFlight::arrow_flight_sql_static)
+ else()
+ set(ARROW_FLIGHT_SQL_ODBC_SHARED_LINK_LIBS arrow_flight_sql_shared
+ arrow_odbc_spi_impl)
+ set(ARROW_FLIGHT_SQL_ODBC_STATIC_LINK_LIBS arrow_flight_sql_static)
+ list(APPEND ARROW_FLIGHT_SQL_ODBC_SHARED_INSTALL_INTERFACE_LIBS
+ ArrowFlight::arrow_flight_sql_shared)
+ list(APPEND ARROW_FLIGHT_SQL_ODBC_STATIC_INSTALL_INTERFACE_LIBS
+ ArrowFlight::arrow_flight_sql_static)
+ endif()
list(APPEND ARROW_FLIGHT_SQL_ODBC_SHARED_PRIVATE_LINK_LIBS ODBC::ODBC
${ODBCINST})
else()
- # Unix
+ # Unix/macOS: driver dynamically links arrow_flight_sql so the driver and
test
+ # binary share the same grpc/arrow_flight runtime.
set(ARROW_FLIGHT_SQL_ODBC_SHARED_LINK_LIBS arrow_odbc_spi_impl)
set(ARROW_FLIGHT_SQL_ODBC_STATIC_LINK_LIBS ODBC::ODBC ${ODBCINST})
endif()
add_arrow_lib(arrow_flight_sql_odbc
+ BUILD_SHARED
+ ON
CMAKE_PACKAGE_NAME
ArrowFlightSqlOdbc
PKG_CONFIG_NAME
@@ -91,8 +104,6 @@ add_arrow_lib(arrow_flight_sql_odbc
${ARROW_FLIGHT_SQL_ODBC_SRCS}
DEFINITIONS
UNICODE
- DEPENDENCIES
- ${ARROW_FLIGHT_SQL_ODBC_DEPENDENCIES}
SHARED_LINK_FLAGS
${ARROW_VERSION_SCRIPT_FLAGS} # Defined in
cpp/arrow/CMakeLists.txt
SHARED_LINK_LIBS
@@ -149,15 +160,10 @@ if(ARROW_FLIGHT_SQL_ODBC_INSTALLER)
set(CPACK_PACKAGE_CONTACT "[email protected]")
if(WIN32)
- # Install ODBC and its Arrow dependencies
install(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
DESTINATION bin
COMPONENT ArrowFlightSQLODBC)
- install(TARGETS arrow_shared
- arrow_compute_shared
- arrow_flight_shared
- arrow_flight_sql_shared
- arrow_flight_sql_odbc_shared
+ install(TARGETS arrow_flight_sql_odbc_shared
RUNTIME_DEPENDENCIES
PRE_EXCLUDE_REGEXES
"api-ms-.*"
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt
index a455ddadd23..4d990b3e89a 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt
@@ -133,12 +133,21 @@ endif()
if(WIN32)
find_package(ODBC REQUIRED)
target_include_directories(arrow_odbc_spi_impl PUBLIC ${ODBC_INCLUDE_DIR})
- target_link_libraries(arrow_odbc_spi_impl
- PUBLIC arrow_flight_sql_shared
- arrow_compute_shared
- Boost::locale
- arrow::simdjson
- ${ODBCINST})
+ if(ARROW_BUILD_STATIC)
+ target_link_libraries(arrow_odbc_spi_impl
+ PUBLIC arrow_flight_sql_static
+ arrow_compute_static
+ Boost::locale
+ arrow::simdjson
+ ${ODBCINST})
+ else()
+ target_link_libraries(arrow_odbc_spi_impl
+ PUBLIC arrow_flight_sql_shared
+ arrow_compute_shared
+ Boost::locale
+ arrow::simdjson
+ ${ODBCINST})
+ endif()
else()
# Unix
target_include_directories(arrow_odbc_spi_impl SYSTEM BEFORE PUBLIC
${ODBC_INCLUDE_DIR})
@@ -166,11 +175,19 @@ target_link_libraries(arrow_odbc_spi_impl_cli
arrow_odbc_spi_impl)
# On Windows, dynamic linking ODBC is supported.
# On unix systems, static linking ODBC is supported, thus the library linking
is static.
-if(WIN32)
- set(ODBC_SPI_IMPL_TEST_LINK_LIBS arrow_flight_testing_shared)
+# Use STATIC_LINK_LIBS when Flight tests require static linkage to avoid
mixing static/shared Arrow
+if(WIN32 AND ARROW_FLIGHT_TEST_LINKAGE STREQUAL "static")
+ set(ODBC_SPI_IMPL_TEST_STATIC_LIBS arrow_odbc_spi_impl
arrow_flight_testing_static
+ ${ARROW_TEST_STATIC_LINK_LIBS})
+ set(ODBC_SPI_IMPL_TEST_EXTRA_LIBS "")
+elseif(WIN32)
+ set(ODBC_SPI_IMPL_TEST_STATIC_LIBS "")
+ set(ODBC_SPI_IMPL_TEST_EXTRA_LIBS arrow_odbc_spi_impl
arrow_flight_testing_shared)
else()
- # unix
- set(ODBC_SPI_IMPL_TEST_LINK_LIBS arrow_flight_testing_static)
+ # Unix - always static
+ set(ODBC_SPI_IMPL_TEST_STATIC_LIBS arrow_odbc_spi_impl
arrow_flight_testing_static
+ ${ARROW_TEST_STATIC_LINK_LIBS})
+ set(ODBC_SPI_IMPL_TEST_EXTRA_LIBS "")
endif()
add_arrow_test(odbc_spi_impl_test
@@ -190,5 +207,6 @@ add_arrow_test(odbc_spi_impl_test
record_batch_transformer_test.cc
util_test.cc
EXTRA_LINK_LIBS
- arrow_odbc_spi_impl
- ${ODBC_SPI_IMPL_TEST_LINK_LIBS})
+ ${ODBC_SPI_IMPL_TEST_EXTRA_LIBS}
+ STATIC_LINK_LIBS
+ ${ODBC_SPI_IMPL_TEST_STATIC_LIBS})
diff --git a/cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt
b/cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt
index 0f45bfd0c81..81f8ec891be 100644
--- a/cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt
+++ b/cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt
@@ -42,38 +42,35 @@ set(ARROW_FLIGHT_SQL_ODBC_TEST_SRCS
# GH-46889: move protobuf_test_util to a more common location
../../../../engine/substrait/protobuf_test_util.cc)
-# GH-49651 Link ODBC tests statically on Linux and dynamically on macOS/Windows
-if(WIN32 OR APPLE)
- set(ARROW_FLIGHT_SQL_ODBC_TEST_LINK_LIBS arrow_flight_sql_odbc_shared
- ${ARROW_TEST_SHARED_LINK_LIBS})
-else()
- # GH-49651 Link ODBC tests statically on Linux to fix segfault
- set(ARROW_FLIGHT_SQL_ODBC_TEST_LINK_LIBS arrow_flight_sql_odbc_static
- ${ARROW_TEST_STATIC_LINK_LIBS})
-endif()
-
-# On macOS, link `ODBCINST` first to ensure iodbc take precedence over unixodbc
+# On macOS, link `ODBCINST` first to ensure iodbc takes precedence over
unixodbc.
set(ARROW_FLIGHT_SQL_ODBC_TEST_LIBS ${ODBCINST} ${ODBC_LIBRARIES}
${SQLite3_LIBRARIES})
-# On Windows, dynamic linking ODBC is supported, tests link libraries
dynamically.
-# On unix systems, static linking ODBC is supported, thus tests link libraries
statically.
-set(ARROW_FLIGHT_SQL_ODBC_TEST_EXTRA_LINK_LIBS "")
-set(ARROW_FLIGHT_SQL_ODBC_TEST_STATIC_LINK_LIBS "")
-if(WIN32)
- # arrow_odbc_spi_impl is required on Windows due to dynamic linking
- list(APPEND ARROW_FLIGHT_SQL_ODBC_TEST_EXTRA_LINK_LIBS arrow_odbc_spi_impl
- ${ARROW_FLIGHT_SQL_ODBC_TEST_LIBS})
+# STATIC_LINK_LIBS replaces add_arrow_test's default Arrow test libraries,
while
+# EXTRA_LINK_LIBS supplements them.
+if(WIN32 AND ARROW_FLIGHT_TEST_LINKAGE STREQUAL "shared")
+ set(ARROW_FLIGHT_SQL_ODBC_TEST_LINK_MODE EXTRA_LINK_LIBS)
+ set(ARROW_FLIGHT_SQL_ODBC_TEST_LINK_LIBS arrow_odbc_spi_impl
+ ${ARROW_FLIGHT_SQL_ODBC_TEST_LIBS})
+elseif(WIN32)
+ set(ARROW_FLIGHT_SQL_ODBC_TEST_LINK_MODE STATIC_LINK_LIBS)
+ set(ARROW_FLIGHT_SQL_ODBC_TEST_LINK_LIBS
+ arrow_odbc_spi_impl ${ARROW_FLIGHT_SQL_ODBC_TEST_LIBS}
arrow_flight_sql_odbc_static
+ ${ARROW_TEST_STATIC_LINK_LIBS})
+elseif(APPLE)
+ # GH-49651: Link the ODBC driver dynamically on macOS.
+ set(ARROW_FLIGHT_SQL_ODBC_TEST_LINK_MODE STATIC_LINK_LIBS)
+ set(ARROW_FLIGHT_SQL_ODBC_TEST_LINK_LIBS
+ ${ARROW_FLIGHT_SQL_ODBC_TEST_LIBS} arrow_flight_sql_odbc_shared
+ ${ARROW_TEST_SHARED_LINK_LIBS})
else()
- # Unix
- list(APPEND ARROW_FLIGHT_SQL_ODBC_TEST_STATIC_LINK_LIBS
- ${ARROW_FLIGHT_SQL_ODBC_TEST_LIBS}
${ARROW_FLIGHT_SQL_ODBC_TEST_LINK_LIBS})
-
- if(NOT APPLE)
- # Links static dependencies on Linux to support ARROW_TEST_LINKAGE=static
- list(APPEND ARROW_FLIGHT_SQL_ODBC_TEST_STATIC_LINK_LIBS arrow_odbc_spi_impl
- ${ARROW_PROTOBUF_LIBPROTOBUF})
- endif()
-
+ # GH-49651: Link the ODBC driver statically on Linux to avoid a segfault.
+ set(ARROW_FLIGHT_SQL_ODBC_TEST_LINK_MODE STATIC_LINK_LIBS)
+ set(ARROW_FLIGHT_SQL_ODBC_TEST_LINK_LIBS
+ ${ARROW_FLIGHT_SQL_ODBC_TEST_LIBS}
+ arrow_flight_sql_odbc_static
+ ${ARROW_TEST_STATIC_LINK_LIBS}
+ arrow_odbc_spi_impl
+ ${ARROW_PROTOBUF_LIBPROTOBUF})
endif()
add_arrow_test(flight_sql_odbc_test
@@ -82,13 +79,19 @@ add_arrow_test(flight_sql_odbc_test
${ARROW_FLIGHT_SQL_MOCK_SERVER_SRCS}
DEFINITIONS
UNICODE
- EXTRA_LINK_LIBS
- ${ARROW_FLIGHT_SQL_ODBC_TEST_EXTRA_LINK_LIBS}
- STATIC_LINK_LIBS
- ${ARROW_FLIGHT_SQL_ODBC_TEST_STATIC_LINK_LIBS})
+ ${ARROW_FLIGHT_SQL_ODBC_TEST_LINK_MODE}
+ ${ARROW_FLIGHT_SQL_ODBC_TEST_LINK_LIBS})
find_package(ODBC REQUIRED)
target_link_libraries(arrow-flight-sql-odbc-test PRIVATE ODBC::ODBC)
+if(WIN32)
+ # GH-49538: Dynamically pass the filename of the driver DLL so
PinDriverModule
+ # in odbc_test_suite.cc can hold a handle to it.
+ target_compile_definitions(arrow-flight-sql-odbc-test
+ PRIVATE
"ARROW_FLIGHT_SQL_ODBC_DLL_FILE_NAME=L\"$<TARGET_FILE_NAME:arrow_flight_sql_odbc_shared>\""
+ )
+endif()
+
# Disable unity build due to sqlite_sql_info.cc conflict with sql.h and
sqlext.h headers.
set_target_properties(arrow-flight-sql-odbc-test PROPERTIES UNITY_BUILD OFF)
diff --git a/cpp/src/arrow/flight/sql/odbc/tests/odbc_test_suite.cc
b/cpp/src/arrow/flight/sql/odbc/tests/odbc_test_suite.cc
index 3125c18b92a..79a8ed9f88c 100644
--- a/cpp/src/arrow/flight/sql/odbc/tests/odbc_test_suite.cc
+++ b/cpp/src/arrow/flight/sql/odbc/tests/odbc_test_suite.cc
@@ -29,6 +29,22 @@
namespace arrow::flight::sql::odbc {
+#ifdef _WIN32
+namespace {
+
+// GH-49538: Hold a handle to the driver for the entire duration of the test
+// suite to avoid a segfault on teardown. This most likely due to having two
+// statically linked copies of gRPC in the test program (one from the driver
and
+// one from the mock server).
+void PinDriverModule() {
+ HMODULE unused = nullptr;
+ GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN,
ARROW_FLIGHT_SQL_ODBC_DLL_FILE_NAME,
+ &unused);
+}
+
+} // namespace
+#endif // _WIN32
+
class MockServerEnvironment : public ::testing::Environment {
public:
void SetUp() override {
@@ -137,6 +153,14 @@ void ODBCTestBase::ConnectWithString(std::string
connect_str, SQLHDBC& conn_hand
static_cast<SQLSMALLINT>(connect_str0.size()),
out_str,
kOdbcBufferSize, &out_str_len,
SQL_DRIVER_NOPROMPT))
<< GetOdbcErrorMessage(SQL_HANDLE_DBC, conn_handle);
+
+// GH-49538: Hold a handle to the driver for the entire duration of the test
+// suite to avoid a segfault on teardown. This most likely due to having two
+// statically linked copies of gRPC in the test program (one from the driver
and
+// one from the mock server).
+#ifdef _WIN32
+ PinDriverModule();
+#endif
}
void ODBCTestBase::Disconnect(SQLHENV& env_handle, SQLHDBC& conn_handle) {
diff --git a/cpp/src/arrow/flight/transport/grpc/customize_grpc.h
b/cpp/src/arrow/flight/transport/grpc/customize_grpc.h
index 7836f7c161d..4a64e4e0721 100644
--- a/cpp/src/arrow/flight/transport/grpc/customize_grpc.h
+++ b/cpp/src/arrow/flight/transport/grpc/customize_grpc.h
@@ -20,16 +20,42 @@
#include <limits>
#include <memory>
+#if __has_include(<absl/synchronization/mutex.h>)
+
// HACK: Workaround absl::Mutex ABI incompatibility by making sure the
// non-debug version of Abseil is included
// (https://github.com/conda-forge/abseil-cpp-feedstock/issues/104,
// https://github.com/abseil/abseil-cpp/issues/1624)
-
-#if __has_include(<absl/synchronization/mutex.h>)
-
-# ifndef NDEBUG
-# define ARROW_NO_NDEBUG
-# define NDEBUG
+//
+// Abseil picks where Mutex::Dtor lives based on NDEBUG:
+//
+// mutex.h: #if defined(NDEBUG) && !ABSL_HAVE_THREAD_SANITIZER &&
+// !ABSL_BUILD_DLL -> inline, emitted into this TU
+// mutex.cc: #if !defined(NDEBUG) || ABSL_HAVE_THREAD_SANITIZER ||
+// ABSL_BUILD_DLL -> strong, out-of-line
+//
+// Defining NDEBUG here makes this TU emit its own inline Mutex::Dtor. Whether
+// that helps or hurts depends on how the Abseil we link against was built:
+//
+// - Abseil built *with* NDEBUG (the conda case above): it inlined Dtor away
+// and never exported it, so a debug TU that expects the out-of-line symbol
+// gets an undefined reference. Emitting our own copy fixes that.
+//
+// - Abseil built *without* NDEBUG (a Debug vcpkg/system build): it has the
+// strong out-of-line Dtor. Emitting our own copy is then a duplicate
+// definition, which a *static* Abseil turns into LNK2005 (GH-49585). With a
+// shared Abseil it is harmless, since the definitions live in separate
+// images.
+//
+// So restrict the hack to the cases where it cannot produce a duplicate:
+// anything that is not MSVC-linking-static-Abseil. On MSVC, Abseil's CMake
puts
+// ABSL_CONSUME_DLL in the INTERFACE compile definitions of its targets, so its
+// presence tells us we are consuming the DLL rather than the static library.
+# if !defined(_MSC_VER) || defined(ABSL_CONSUME_DLL)
+# ifndef NDEBUG
+# define ARROW_NO_NDEBUG
+# define NDEBUG
+# endif
# endif
# include <absl/synchronization/mutex.h>