Index: CMakeLists.txt =================================================================== --- CMakeLists.txt +++ CMakeLists.txt @@ -58,6 +58,8 @@ option(LIBCXX_INSTALL_HEADERS "Install the libc++ headers." ON) option(LIBCXX_INSTALL_LIBRARY "Install the libc++ library." ON) option(LIBCXX_INSTALL_SUPPORT_HEADERS "Install libc++ support headers." ON) +set(LIBCXX_ABI_VERSION 1 CACHE STRING "ABI version of libc++.") +option(LIBCXX_ABI_UNSTABLE "Unstable ABI of libc++." OFF) # ABI Library options --------------------------------------------------------- set(LIBCXX_CXX_ABI "${LIBCXX_CXX_ABI}" CACHE STRING @@ -298,6 +300,11 @@ endif() # Configuration file flags ===================================================== +if (NOT LIBCXX_ABI_VERSION EQUAL "1") + config_define(${LIBCXX_ABI_VERSION} _LIBCPP_ABI_VERSION) +endif() +config_define_if(LIBCXX_ABI_UNSTABLE _LIBCPP_ABI_UNSTABLE) + config_define_if_not(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE) config_define_if_not(LIBCXX_ENABLE_STDIN _LIBCPP_HAS_NO_STDIN) config_define_if_not(LIBCXX_ENABLE_STDOUT _LIBCPP_HAS_NO_STDOUT) Index: cmake/Modules/HandleLibcxxFlags.cmake =================================================================== --- cmake/Modules/HandleLibcxxFlags.cmake +++ cmake/Modules/HandleLibcxxFlags.cmake @@ -65,6 +65,12 @@ endif() endmacro() +macro(config_define value def) + set(${def} ${value}) + add_definitions(-D${def}=${value}) + set(LIBCXX_NEEDS_SITE_CONFIG ON) +endmacro() + # Add a specified list of flags to both 'LIBCXX_COMPILE_FLAGS' and # 'LIBCXX_LINK_FLAGS'. macro(add_flags) Index: docs/Abi.rst =================================================================== --- /dev/null +++ docs/Abi.rst @@ -0,0 +1,17 @@ + +==================== +Libc++ ABI stability +==================== + +Libc++ aims to preserve stable ABI to avoid subtle bugs when code built to the old ABI +is linked with the code build to the new ABI. At the same time, libc++ allows ABI-breaking +improvements and bugfixes for the scenarios when ABI change is not a issue. + +To support both cases, libc++ allows specifying the ABI version at the +build time. The version is defined with a cmake option +LIBCXX_ABI_VERSION. Another option LIBCXX_ABI_UNSTABLE can be used to +include all present ABI breaking features. These options translate +into C++ macro definitions _LIBCPP_ABI_VERSION, _LIBCPP_ABI_UNSTABLE. + +Any ABI-changing feature is placed under it's own macro, _LIBCPP_ABI_XXX, which is enabled +based on the value of _LIBCPP_ABI_VERSION. _LIBCPP_ABI_UNSTABLE, if set, enables all features at once. Index: docs/BuildingLibcxx.rst =================================================================== --- docs/BuildingLibcxx.rst +++ docs/BuildingLibcxx.rst @@ -193,6 +193,25 @@ Build libc++ with run time type information. + +libc++ Feature options +---------------------- + +The following options allow building libc++ for a different ABI version. + +.. option:: LIBCXX_ABI_VERSION:STRING + + **Default**: ``1`` + + Defines the target ABI version of libc++. + +.. option:: LIBCXX_ABI_UNSTABLE:BOOL + + **Default**: ``OFF`` + + Build the "unstable" ABI version of libc++. Includes all ABI changing features + on top of the current stable version. + .. _LLVM-specific variables: LLVM-specific options Index: include/__config =================================================================== --- include/__config +++ include/__config @@ -23,7 +23,13 @@ #define _LIBCPP_VERSION 3800 +#ifndef _LIBCPP_ABI_VERSION #define _LIBCPP_ABI_VERSION 1 +#endif + +#if defined(_LIBCPP_ABI_UNSTABLE) || _LIBCPP_ABI_VERSION >= 2 +#define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +#endif #define _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_X##_LIBCPP_Y #define _LIBCPP_CONCAT(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) @@ -240,9 +246,12 @@ #if defined(__clang__) -#if defined(__APPLE__) && !defined(__i386__) && !defined(__x86_64__) && \ - !defined(__arm__) -#define _LIBCPP_ALTERNATE_STRING_LAYOUT +// _LIBCPP_ALTERNATE_STRING_LAYOUT is an old name for +// _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT left here for backward compatibility. +#if (defined(__APPLE__) && !defined(__i386__) && !defined(__x86_64__) && \ + !defined(__arm__)) || \ + defined(_LIBCPP_ALTERNATE_STRING_LAYOUT) +#define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT #endif #if __has_feature(cxx_alignas) Index: include/__config_site.in =================================================================== --- include/__config_site.in +++ include/__config_site.in @@ -10,6 +10,8 @@ #ifndef _LIBCPP_CONFIG_SITE #define _LIBCPP_CONFIG_SITE +#cmakedefine _LIBCPP_ABI_VERSION @_LIBCPP_ABI_VERSION@ +#cmakedefine _LIBCPP_ABI_UNSTABLE #cmakedefine _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE #cmakedefine _LIBCPP_HAS_NO_STDIN #cmakedefine _LIBCPP_HAS_NO_STDOUT Index: include/string =================================================================== --- include/string +++ include/string @@ -1185,7 +1185,7 @@ #pragma warning( pop ) #endif // _LIBCPP_MSVC -#ifdef _LIBCPP_ALTERNATE_STRING_LAYOUT +#ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT template struct __padding @@ -1198,7 +1198,7 @@ { }; -#endif // _LIBCPP_ALTERNATE_STRING_LAYOUT +#endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT template class _LIBCPP_TYPE_VIS_ONLY basic_string @@ -1234,7 +1234,7 @@ private: -#ifdef _LIBCPP_ALTERNATE_STRING_LAYOUT +#ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT struct __long { @@ -1294,7 +1294,7 @@ value_type __data_[__min_cap]; }; -#endif // _LIBCPP_ALTERNATE_STRING_LAYOUT +#endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT union __ulx{__long __lx; __short __lxx;}; @@ -1698,7 +1698,7 @@ const allocator_type& __alloc() const _NOEXCEPT {return __r_.second();} -#ifdef _LIBCPP_ALTERNATE_STRING_LAYOUT +#ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT _LIBCPP_INLINE_VISIBILITY void __set_short_size(size_type __s) _NOEXCEPT @@ -1716,7 +1716,7 @@ {return __r_.first().__s.__size_;} # endif -#else // _LIBCPP_ALTERNATE_STRING_LAYOUT +#else // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT _LIBCPP_INLINE_VISIBILITY void __set_short_size(size_type __s) _NOEXCEPT @@ -1734,7 +1734,7 @@ {return __r_.first().__s.__size_ >> 1;} # endif -#endif // _LIBCPP_ALTERNATE_STRING_LAYOUT +#endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT _LIBCPP_INLINE_VISIBILITY void __set_long_size(size_type __s) _NOEXCEPT Index: lib/CMakeLists.txt =================================================================== --- lib/CMakeLists.txt +++ lib/CMakeLists.txt @@ -129,8 +129,8 @@ COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" LINK_FLAGS "${LIBCXX_LINK_FLAGS}" OUTPUT_NAME "c++" - VERSION "1.0" - SOVERSION "1" + VERSION "${LIBCXX_ABI_VERSION}.0" + SOVERSION "${LIBCXX_ABI_VERSION}" ) if (LIBCXX_INSTALL_LIBRARY) Index: test/CMakeLists.txt =================================================================== --- test/CMakeLists.txt +++ test/CMakeLists.txt @@ -13,6 +13,7 @@ pythonize_bool(LIBCXX_ENABLE_RTTI) pythonize_bool(LIBCXX_ENABLE_SHARED) pythonize_bool(LIBCXX_BUILD_32_BITS) +pythonize_bool(LIBCXX_ABI_UNSTABLE) pythonize_bool(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE) pythonize_bool(LIBCXX_ENABLE_STDIN) pythonize_bool(LIBCXX_ENABLE_STDOUT) Index: test/libcxx/test/config.py =================================================================== --- test/libcxx/test/config.py +++ test/libcxx/test/config.py @@ -387,6 +387,7 @@ # Configure feature flags. self.configure_compile_flags_exceptions() self.configure_compile_flags_rtti() + self.configure_compile_flags_abi_version() self.configure_compile_flags_no_global_filesystem_namespace() self.configure_compile_flags_no_stdin() self.configure_compile_flags_no_stdout() @@ -440,6 +441,15 @@ self.config.available_features.add('libcpp-no-rtti') self.cxx.compile_flags += ['-fno-rtti', '-D_LIBCPP_NO_RTTI'] + def configure_compile_flags_abi_version(self): + abi_version = self.get_lit_conf('abi_version', '').strip() + abi_unstable = self.get_lit_bool('abi_unstable') + if abi_version: + self.cxx.compile_flags += ['-D_LIBCPP_ABI_VERSION=' + abi_version] + if abi_unstable: + self.config.available_features.add('libcpp-abi-unstable') + self.cxx.compile_flags += ['-D_LIBCPP_ABI_UNSTABLE'] + def configure_compile_flags_no_global_filesystem_namespace(self): enable_global_filesystem_namespace = self.get_lit_bool( 'enable_global_filesystem_namespace', True) Index: test/lit.site.cfg.in =================================================================== --- test/lit.site.cfg.in +++ test/lit.site.cfg.in @@ -7,6 +7,8 @@ config.enable_rtti = "@LIBCXX_ENABLE_RTTI@" config.enable_shared = "@LIBCXX_ENABLE_SHARED@" config.enable_32bit = "@LIBCXX_BUILD_32_BITS@" +config.abi_version = "@LIBCXX_ABI_VERSION@" +config.abi_unstable = "@LIBCXX_ABI_UNSTABLE@" config.enable_global_filesystem_namespace = "@LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE@" config.enable_stdin = "@LIBCXX_ENABLE_STDIN@" config.enable_stdout = "@LIBCXX_ENABLE_STDOUT@"