diff --git a/.github/workflows/cpp_extra.yml b/.github/workflows/cpp_extra.yml index e4e51608dbe3..18ffb16c90a3 100644 --- a/.github/workflows/cpp_extra.yml +++ b/.github/workflows/cpp_extra.yml @@ -580,8 +580,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. @@ -597,6 +597,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: shared + 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 a735f25667b4..87872f255f7d 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@v6 diff --git a/ci/vcpkg/amd64-windows-no-absl-sync-release.cmake b/ci/vcpkg/amd64-windows-no-absl-sync-release.cmake index 97c73e31464e..436650842adf 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/src/arrow/flight/CMakeLists.txt b/cpp/src/arrow/flight/CMakeLists.txt index 8974c9581f7c..bac9090e61a4 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 @@ -245,6 +245,15 @@ if(ARROW_BUILD_STATIC AND WIN32) target_compile_definitions(arrow_flight_static PUBLIC ARROW_FLIGHT_STATIC) endif() +# NOTE-49585: Workaround for issue found in GH-49585. See "NOTE-49585" below. +if(WIN32 + AND CMAKE_BUILD_TYPE STREQUAL "Debug" + AND ARROW_FLIGHT_TEST_LINKAGE STREQUAL "static") + foreach(LIB_TARGET ${ARROW_FLIGHT_LIBRARIES}) + target_link_options(${LIB_TARGET} PRIVATE "/FORCE:MULTIPLE") + endforeach() +endif() + foreach(LIB_TARGET ${ARROW_FLIGHT_LIBRARIES}) target_compile_definitions(${LIB_TARGET} PRIVATE ARROW_FLIGHT_EXPORTING) endforeach() @@ -371,6 +380,43 @@ if(ARROW_BUILD_BENCHMARKS) endif(ARROW_BUILD_BENCHMARKS) +# NOTE-49585: Workaround for issue found in GH-49585. When building Flight +# targets with the combination of: +# +# - WIN32 +# - Debug +# - /MD linkage +# +# You get linker errors like this: +# +# absl_synchronization.lib(mutex.cc.obj) : error LNK2005: "private: void __cdecl absl::lts_20250814::Mutex::Dtor(void)" (?Dtor +# @Mutex@lts_20250814@absl@@AEAAXXZ) already defined in arrow_flight_static.lib(grpc_client.obj) [C:\path\to\arrow\cpp\static-debug-build\src\arrow\flight\sql\arrow-flight-sql-test.vcxproj] +# C:\path\to\arrow\cpp\static-debug-build\debug\Debug\arrow-flight-sql-test.exe : +# fatal error LNK1169: one or more multiply defined symbols found [C:\path\to\arrow\cpp\static-debug-build\src\arrow\flight\sql\arrow-flight-sql-test.vcxproj] +# Building Custom Rule C:/path/to/arrow/cpp/src/arrow/flight/CMakeLists.txt +# test_server.cc +# absl_synchronization.lib(mutex.cc.obj) : error LNK2005: "private: void __cdecl absl::lts_20250814::Mutex::Dtor(void)" (?Dtor +# @Mutex@lts_20250814@absl@@AEAAXXZ) already defined in arrow_flight_static.lib(protocol_grpc_internal.obj) [C:\path\to\arrow\cpp\static-debug-build\src\arrow\flight\flight-test-server.vcxproj] +# C:\path\to\arrow\cpp\static-debug-build\debug\Debug\flight-test-server.exe : fatal error +# LNK1169: one or more multiply defined symbols found [C:\path\to\arrow\cpp\static-debug-build\src\arrow\flight\flight-test-server.vcxproj] +# +# If you build in Release mode w/ /MD linkage you don't get these errors. +if(WIN32 + AND CMAKE_BUILD_TYPE STREQUAL "Debug" + AND ARROW_FLIGHT_TEST_LINKAGE STREQUAL "static") + set(FLIGHT_TEST_EXES + arrow-flight-internals-test + arrow-flight-test + flight-test-server + arrow-flight-perf-server + arrow-flight-benchmark) + foreach(test_exe ${FLIGHT_TEST_EXES}) + if(TARGET ${test_exe}) + target_link_options(${test_exe} PRIVATE "/FORCE:MULTIPLE") + endif() + endforeach() +endif() + if(ARROW_FLIGHT_SQL) add_subdirectory(sql) diff --git a/cpp/src/arrow/flight/sql/CMakeLists.txt b/cpp/src/arrow/flight/sql/CMakeLists.txt index 2299bdfe0a3b..6d60481bbfce 100644 --- a/cpp/src/arrow/flight/sql/CMakeLists.txt +++ b/cpp/src/arrow/flight/sql/CMakeLists.txt @@ -93,12 +93,26 @@ if(ARROW_BUILD_STATIC AND WIN32) target_compile_definitions(arrow_flight_sql_static PUBLIC ARROW_FLIGHT_SQL_STATIC) endif() +# NOTE-49585: Workaround for issue found in GH-49585. See "NOTE-49585" in +# ../CMakeLists.txt. +if(WIN32 + AND CMAKE_BUILD_TYPE STREQUAL "Debug" + AND ARROW_FLIGHT_TEST_LINKAGE STREQUAL "static") + foreach(LIB_TARGET ${ARROW_FLIGHT_SQL_LIBRARIES}) + target_link_options(${LIB_TARGET} PRIVATE "/FORCE:MULTIPLE") + endforeach() +endif() + if(MSVC) # Suppress warnings caused by Protobuf (casts) set_source_files_properties(protocol_internal.cc PROPERTIES COMPILE_OPTIONS "/wd4267") 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 +191,18 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES) ARROW_FLIGHT_SQL_STATIC) endforeach() endif() + + # NOTE-49585: Workaround for issue found in GH-49585. See "NOTE-49585" in + # ../CMakeLists.txt. + if(WIN32 + AND CMAKE_BUILD_TYPE STREQUAL "Debug" + AND ARROW_FLIGHT_TEST_LINKAGE STREQUAL "static") + foreach(TEST_TARGET arrow-flight-sql-test flight-sql-test-server flight-sql-test-app) + if(TARGET ${TEST_TARGET}) + target_link_options(${TEST_TARGET} PRIVATE "/FORCE:MULTIPLE") + endif() + 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 8783d2b065d8..f74697b0744f 100644 --- a/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt +++ b/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt @@ -59,23 +59,34 @@ 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() @@ -91,8 +102,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 @@ -106,6 +115,16 @@ add_arrow_lib(arrow_flight_sql_odbc SHARED_PRIVATE_LINK_LIBS ${ARROW_FLIGHT_SQL_ODBC_SHARED_PRIVATE_LINK_LIBS}) +# NOTE-49585: Workaround for issue found in GH-49585. See "NOTE-49585" in +# ../../CMakeLists.txt. +if(WIN32 + AND CMAKE_BUILD_TYPE STREQUAL "Debug" + AND ARROW_FLIGHT_TEST_LINKAGE STREQUAL "static") + foreach(LIB_TARGET ${ARROW_FLIGHT_SQL_ODBC_LIBRARIES}) + target_link_options(${LIB_TARGET} PRIVATE "/FORCE:MULTIPLE") + endforeach() +endif() + foreach(LIB_TARGET ${ARROW_FLIGHT_SQL_ODBC_LIBRARIES}) target_compile_definitions(${LIB_TARGET} PRIVATE ARROW_FLIGHT_SQL_ODBC_EXPORTING) endforeach() @@ -130,15 +149,10 @@ if(ARROW_FLIGHT_SQL_ODBC_INSTALLER) set(CPACK_PACKAGE_CONTACT "dev@arrow.apache.org") 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 5a16c0361f32..ef9c5eb2f6ca 100644 --- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt +++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt @@ -133,9 +133,15 @@ 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 - ${ODBCINST}) + if(ARROW_BUILD_STATIC) + target_link_libraries(arrow_odbc_spi_impl + PUBLIC arrow_flight_sql_static arrow_compute_static + Boost::locale ${ODBCINST}) + else() + target_link_libraries(arrow_odbc_spi_impl + PUBLIC arrow_flight_sql_shared arrow_compute_shared + Boost::locale ${ODBCINST}) + endif() else() # Unix target_include_directories(arrow_odbc_spi_impl SYSTEM BEFORE PUBLIC ${ODBC_INCLUDE_DIR}) @@ -163,11 +169,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 @@ -187,5 +201,19 @@ 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}) + +# NOTE-49585: Workaround for issue found in GH-49585. See "NOTE-49585" in +# ../../../CMakeLists.txt. +if(WIN32 + AND CMAKE_BUILD_TYPE STREQUAL "Debug" + AND ARROW_FLIGHT_TEST_LINKAGE STREQUAL "static") + if(TARGET arrow_odbc_spi_impl_cli) + target_link_options(arrow_odbc_spi_impl_cli PRIVATE "/FORCE:MULTIPLE") + endif() + if(TARGET arrow-odbc-spi-impl-test) + target_link_options(arrow-odbc-spi-impl-test PRIVATE "/FORCE:MULTIPLE") + endif() +endif() diff --git a/cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt b/cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt index 0f45bfd0c811..dd67ebef3506 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt +++ b/cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt @@ -42,8 +42,8 @@ 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) +# GH-49651 Link ODBC tests statically on Linux and dynamically on macOS. +if(APPLE OR (WIN32 AND ARROW_TEST_LINKAGE STREQUAL "shared")) set(ARROW_FLIGHT_SQL_ODBC_TEST_LINK_LIBS arrow_flight_sql_odbc_shared ${ARROW_TEST_SHARED_LINK_LIBS}) else() @@ -56,24 +56,26 @@ endif() 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. +# On Windows with static Arrow, use STATIC_LINK_LIBS to avoid mixing static/shared. +# On Unix/macOS, 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 +if(WIN32 AND ARROW_FLIGHT_TEST_LINKAGE STREQUAL "static") + # Static Windows tests + list(APPEND + ARROW_FLIGHT_SQL_ODBC_TEST_STATIC_LINK_LIBS + arrow_odbc_spi_impl + ${ARROW_FLIGHT_SQL_ODBC_TEST_LIBS} + ${ARROW_FLIGHT_SQL_ODBC_TEST_LINK_LIBS} + ${ARROW_TEST_STATIC_LINK_LIBS}) +elseif(WIN32) + # Dynamic Windows tests list(APPEND ARROW_FLIGHT_SQL_ODBC_TEST_EXTRA_LINK_LIBS arrow_odbc_spi_impl ${ARROW_FLIGHT_SQL_ODBC_TEST_LIBS}) else() - # Unix + # Unix/macOS 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() - endif() add_arrow_test(flight_sql_odbc_test @@ -92,3 +94,11 @@ target_link_libraries(arrow-flight-sql-odbc-test PRIVATE ODBC::ODBC) # 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) + +if(WIN32 + AND CMAKE_BUILD_TYPE STREQUAL "Debug" + AND ARROW_FLIGHT_TEST_LINKAGE STREQUAL "static") + if(TARGET arrow-flight-sql-odbc-test) + target_link_options(arrow-flight-sql-odbc-test PRIVATE "/FORCE:MULTIPLE") + endif() +endif() 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 3125c18b92ac..f3c6ba58c89a 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 @@ -232,7 +232,39 @@ void ODBCTestBase::SetUp() { } void ODBCTestBase::TearDown() { - ASSERT_EQ(SQL_SUCCESS, SQLFreeHandle(SQL_HANDLE_STMT, stmt)); + if (connected) { + ASSERT_EQ(SQL_SUCCESS, SQLFreeHandle(SQL_HANDLE_STMT, stmt)); + } +} + +void ODBCTestBase::TearDownTestSuite() { + if (connected) { + // WORKAROUND GH-49585: Skip Disconnect() to avoid segfault when run through CTest + // + // When tests are run through CTest (but NOT when run directly from cmd.exe), + // SQLFreeHandle(SQL_HANDLE_ENV) crashes during cleanup. The crash occurs only with + // static linkage (ARROW_TEST_LINKAGE=static) and happens while freeing the ODBC + // environment handle, which triggers cleanup of statically-linked gRPC/Flight + // resources. + // + // Root cause appears to be CTest's process management (signal handling, I/O + // redirection, or environment differences) interfering with gRPC cleanup during + // static destruction. + // + // This workaround leaks the ODBC handles but allows tests to complete successfully. + // A proper fix would require ensuring gRPC is kept alive until all ODBC handles are + // freed, or switching to dynamic linkage for tests. + // + // Disconnect(); + connected = false; + } +} + +void FlightSQLODBCRemoteTestBase::CheckForRemoteTest() { + if (arrow::internal::GetEnvVar(kTestConnectStr.data()).ValueOr("").empty()) { + skipping_test = true; + GTEST_SKIP() << "Skipping test: kTestConnectStr not set"; + } } void FlightSQLODBCRemoteTestBase::SetUpTestSuite() {