| =================== |
| 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>`. |