forked from OSchip/llvm-project
97 lines
4.1 KiB
ReStructuredText
97 lines
4.1 KiB
ReStructuredText
===================
|
|
Availability Markup
|
|
===================
|
|
|
|
.. contents::
|
|
:local:
|
|
|
|
Overview
|
|
========
|
|
|
|
Libc++ is used as a system library on macOS and iOS (amongst others). In order
|
|
for users to be able to compile a binary that is intended to be deployed to an
|
|
older version of the platform, clang provides the
|
|
`availability attribute <https://clang.llvm.org/docs/AttributeReference.html#availability>`_
|
|
that can be placed on declarations to describe the lifecycle of a symbol in the
|
|
library.
|
|
|
|
Design
|
|
======
|
|
|
|
When a new feature is introduced that requires dylib support, a macro should be
|
|
created in include/__config to mark this feature as unavailable for all the
|
|
systems. For example::
|
|
|
|
// Define availability macros.
|
|
#if defined(_LIBCPP_USE_AVAILABILITY_APPLE)
|
|
# define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS __attribute__((unavailable))
|
|
#else if defined(_LIBCPP_USE_AVAILABILITY_SOME_OTHER_VENDOR)
|
|
# define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS __attribute__((unavailable))
|
|
#else
|
|
# define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
|
|
#endif
|
|
|
|
When the library is updated by the platform vendor, the markup can be updated.
|
|
For example::
|
|
|
|
#define _LIBCPP_AVAILABILITY_SHARED_MUTEX \
|
|
__attribute__((availability(macosx,strict,introduced=10.12))) \
|
|
__attribute__((availability(ios,strict,introduced=10.0))) \
|
|
__attribute__((availability(tvos,strict,introduced=10.0))) \
|
|
__attribute__((availability(watchos,strict,introduced=3.0)))
|
|
|
|
In the source code, the macro can be added on a class if the full class requires
|
|
type info from the library for example::
|
|
|
|
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
|
|
class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
|
|
: public std::logic_error {
|
|
|
|
or on a particular symbol:
|
|
|
|
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE void operator delete(void* __p, std::size_t __sz) _NOEXCEPT;
|
|
|
|
Furthermore, a lit feature should be added to match that availability macro,
|
|
so that tests depending on that feature can be marked to XFAIL if the feature
|
|
is not supported. This way, the test suite will work on platforms that have
|
|
not shipped the feature yet. This can be done by adding the appropriate lit
|
|
feature in test/config.py.
|
|
|
|
|
|
Testing
|
|
=======
|
|
|
|
Some parameters can be passed to lit to run the test-suite and exercise the
|
|
availability.
|
|
|
|
* The `target_triple` parameter controls the deployment target. For example lit
|
|
can be invoked with `--param=target_triple=x86_64-apple-macosx10.12`.
|
|
Default is the current host.
|
|
* The `use_system_cxx_lib` parameter indicates that the test suite is being
|
|
compiled with the intent of being run against the system library for the
|
|
given triple, AND that it is being run against it.
|
|
|
|
Tests can be marked as XFAIL based on multiple features made available by lit.
|
|
If `use_system_cxx_lib` is true, then assuming `target_triple=x86_64-apple-macosx10.12`,
|
|
the following features will be made available:
|
|
|
|
- with_system_cxx_lib=macosx
|
|
- with_system_cxx_lib=macosx10.12
|
|
- with_system_cxx_lib=x86_64-apple-macosx10.12
|
|
|
|
These features are used to XFAIL a test that fails when deployed on (or is
|
|
compiled for) an older system. For example, if the test exhibits a bug in the
|
|
libc on a particular system version, or if the test uses a symbol that is not
|
|
available on an older version of the dylib, it can be marked as XFAIL with
|
|
one of the above features.
|
|
|
|
It is sometimes useful to check that a test fails specifically when compiled
|
|
for a given deployment target. For example, this is the case when testing
|
|
availability markup, where we want to make sure that using the annotated
|
|
facility on a deployment target that doesn't support it will fail at compile
|
|
time, not at runtime. This can be achieved by creating a `.compile.pass.cpp`
|
|
and XFAILing it for the right deployment target. If the test doesn't fail at
|
|
compile-time like it's supposed to, the test will XPASS. Another option is to
|
|
create a `.verify.cpp` test that checks for the right errors, and mark that
|
|
test as requiring `with_system_cxx_lib=<something>`.
|