From 5478ce2cf9f2a36b3493b1dccd7b4487e17dc2a0 Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Wed, 27 Nov 2024 16:39:35 -0800 Subject: [PATCH] Fix crash when building with _GLIBCXX_USE_CXX11_ABI=0 (#686) **Issue:** A user had been building aws-crt-cpp with `CXXFLAGS=-D_GLIBCXX_USE_CXX11_ABI=0`, and that worked fine until the recent change where we started hiding symbols by default (PR https://github.com/awslabs/aws-crt-cpp/pull/666) With symbols hidden by default, and `_GLIBCXX_USE_CXX11_ABI=0`, tests would crash in the destructor of `Aws::Crt::String` (which is `std::string` with a custom allocator). **Description of changes:** Don't hide symbols when building for the ancient glibcxx ABI. I don't 100% understand why this fixes the issue, but the situation is esoteric enough that it doesn't seem worth spending more days on this problem. **Background** See: https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html GCC had to introduce a new ABI for C++11 which removed the copy-on-write optimization for strings, which is forbidden in C++11 and later (new ABI uses a small-string optimization instead). But GCC let users manually set `_GLIBCXX_USE_CXX11_ABI=0` so they could opt back into the old ABI and continue working with libraries compiled for C++03. I don't think GCC intended devs to continue using this 10 years later, but some people are, because the old copy-on-write optimization has less memory usage. --- .github/workflows/ci.yml | 10 +++++++++- CMakeLists.txt | 16 +++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37879946f..6b7a4bf16 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ env: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true - + jobs: linux-compat-use-openssl: runs-on: ubuntu-22.04 # latest @@ -143,6 +143,14 @@ jobs: aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build -p ${{ env.PACKAGE_NAME }} --compiler=${{ matrix.compiler }} --cmake-extra=-DBUILD_SHARED_LIBS=ON + linux-glibcxx-ancient-abi: + runs-on: ubuntu-24.04 # latest + steps: + - name: Build ${{ env.PACKAGE_NAME }} + run: | + aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh + ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build -p ${{ env.PACKAGE_NAME }} --compiler=gcc-11 --cmake-extra=-DBUILD_SHARED_LIBS=ON --cmake-extra=-DCMAKE_CXX_FLAGS=-D_GLIBCXX_USE_CXX11_ABI=0 + linux-openssl-static: runs-on: ubuntu-22.04 # latest steps: diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f062caa6..4127d0714 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,9 +298,19 @@ set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD ${CMAKE_CXX_STANDARD}) # Hide symbols by default -# Except for ancient GCC, because it leads to crashes in shared-lib builds -# see: https://github.com/awslabs/aws-crt-cpp/pull/675 -if(NOT (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0")) +# Except where it causes problems, and the situation is weird enough that it's not worth investigating further. +# +# We've seen people set _GLIBCXX_USE_CXX11_ABI=0 which forces GCC to use it's pre-C++11 string implementation, +# which leads to crashes on shared-lib builds. Search every variant of CXX_FLAGS to see if it's set. +string(FIND "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${CMAKE_CXX_FLAGS_MINSIZEREL}" + "-D_GLIBCXX_USE_CXX11_ABI=0" found_ancient_abi_flag) +if(found_ancient_abi_flag GREATER -1) + message(WARNING "_GLIBCXX_USE_CXX11_ABI=0 is set. Making all symbols visible to prevent weird crashes") +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0") + # Ancient GCC leads to crashes in shared-lib builds + # see: https://github.com/awslabs/aws-crt-cpp/pull/675 + message(WARNING "Ancient compiler (${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}). Making all symbols visible to prevent weird crashes") +else() set_target_properties(${PROJECT_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN ON) endif()