ABI versioning macros for libc++.

C++ macros and CMake options that specify the default ABI version of
the library, and can be overridden to pick up new ABI-changing
features.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@250254 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evgeniy Stepanov 2015-10-13 23:48:28 +00:00
parent b3b00818e5
commit 4f01aa8fb8
11 changed files with 85 additions and 12 deletions

View File

@ -58,6 +58,8 @@ set(LIBCXX_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING
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 @@ if (LIBCXX_BUILT_STANDALONE)
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)

View File

@ -65,6 +65,12 @@ macro(config_define_if_not condition def)
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)

17
docs/Abi.rst Normal file
View File

@ -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.

View File

@ -193,6 +193,25 @@ libc++ Feature options
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

View File

@ -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)

View File

@ -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

View File

@ -1185,7 +1185,7 @@ _LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS __basic_string_common<true>)
#pragma warning( pop )
#endif // _LIBCPP_MSVC
#ifdef _LIBCPP_ALTERNATE_STRING_LAYOUT
#ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
template <class _CharT, size_t = sizeof(_CharT)>
struct __padding
@ -1198,7 +1198,7 @@ struct __padding<_CharT, 1>
{
};
#endif // _LIBCPP_ALTERNATE_STRING_LAYOUT
#endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
template<class _CharT, class _Traits, class _Allocator>
class _LIBCPP_TYPE_VIS_ONLY basic_string
@ -1234,7 +1234,7 @@ public:
private:
#ifdef _LIBCPP_ALTERNATE_STRING_LAYOUT
#ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
struct __long
{
@ -1294,7 +1294,7 @@ private:
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 @@ private:
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 @@ private:
{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 @@ private:
{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

View File

@ -129,8 +129,8 @@ set_target_properties(cxx
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)

View File

@ -13,6 +13,7 @@ pythonize_bool(LIBCXX_ENABLE_EXCEPTIONS)
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)

View File

@ -387,6 +387,7 @@ class Configuration(object):
# 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 @@ class Configuration(object):
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)

View File

@ -7,6 +7,8 @@ config.enable_exceptions = "@LIBCXX_ENABLE_EXCEPTIONS@"
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@"