| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef ZIRCON_AVAILABILITY_H_ |
| #define ZIRCON_AVAILABILITY_H_ |
| |
| // The macros in this file support implementation of Fuchsia API level-aware |
| // C++ APIs and C++ code that needs to support multiple Fuchsia API levels. |
| // |
| // Values passed to level parameters must be a one of: |
| // * a positive decimal integer literal no greater than the largest current stable API level |
| // * Valid levels are defined in availability_levels.inc. |
| // * Support for older retired API levels as parameters may be removed over time. |
| // * `NEXT` - for code to be included in the next stable API level. |
| // * TODO(https://fxbug.dev/326277078): Add support for NEXT as a parameter. |
| // * `HEAD` - for either of the following: |
| // * In-development code that is not ready to be exposed in an SDK |
| // * Code that should only be in Platform builds. |
| // * `PLATFORM` - for code that must behave differently when building the Fuchsia Platform vs. |
| // when building code that runs on it. This is useful when removing an API element while |
| // continuing to provide runtime support at previous API levels. It should only be used in-tree. |
| |
| // When targeting the Fuchsia platform, `__Fuchsia_API_level__` must always be |
| // specified and valid to ensure proper application of Platform Versioning. |
| // For Clang, which defaults to level 0, the target level should always be |
| // specified with `-ffuchsia-api-level`. |
| #if defined(__Fuchsia__) |
| #if !defined(__Fuchsia_API_level__) || __Fuchsia_API_level__ == 0 |
| // TODO(https://fxbug.dev/327691011): Change to `#error` once the toolchain |
| // build targets a specific API level. |
| #warning `__Fuchsia_API_level__` must be set to a non-zero value. For Clang, use `-ffuchsia-api-level`. |
| #endif // !defined(__Fuchsia_API_level__) || __Fuchsia_API_level__ == 0 |
| #endif // defined(__Fuchsia__) |
| |
| // ============================================================================= |
| // Availability attributes. |
| // ============================================================================= |
| |
| // Only apply availability attributes when they are supported and will be used. |
| // Clang already handles only applying the attribute to the specified platform, |
| // so the __Fuchsia__ condition is at most a minor compile-time optimization |
| // when the macros are encountered in non-Fuchsia builds. |
| #if defined(__clang__) && defined(__Fuchsia__) |
| |
| // When targeting the Fuchsia platform, Clang compares the level(s) specified in |
| // the availability attributes below against the target API level, so it is |
| // important that the level has been specified correctly. Clang does not perform |
| // availability checks if the API level is unspecified or 0. |
| // The above check of `__Fuchsia_API_level__` also ensures a non-zero level has |
| // been specified because Clang uses `-ffuchsia-api-level` for both. |
| |
| // An API that was added to the platform. |
| // |
| // Annotates the API level at which the API was added to the platform. Use |
| // ZX_DEPRECATED_SINCE if the API is later deprecated. |
| // |
| // Example: |
| // |
| // void fdio_spawn(...) ZX_AVAILABLE_SINCE(4); |
| // |
| #define ZX_AVAILABLE_SINCE(level_added) \ |
| __attribute__((availability(fuchsia, strict, introduced = FUCHSIA_API_LEVEL_(level_added)))) |
| |
| // An API that was added the platform and later deprecated. |
| // |
| // Annotates the API level at which the API added the platform and the API |
| // level at which the API was deprecated. |
| // |
| // Deprecated API can still be called by clients. The deprecation annotation |
| // is a warning that the API is likely to be removed in the future. APIs should |
| // be deprecated for at least one API level before being removed. |
| // |
| // Use the `msg` parameter to explain why the API was deprecated and what |
| // clients should do instead of using the API. |
| // |
| // Example: |
| // |
| // void fdio_fork(...) ZX_DEPRECATED_SINCE(1, 4, |
| // "Root cause of security vulnerabilities due to implicit handle " |
| // "transfer. Use fdio_spawn instead."); |
| // |
| #define ZX_DEPRECATED_SINCE(level_added, level_deprecated, msg) \ |
| __attribute__((availability(fuchsia, strict, introduced = FUCHSIA_API_LEVEL_(level_added), \ |
| deprecated = FUCHSIA_API_LEVEL_(level_deprecated), message = msg))) |
| |
| // An API that was added to the platform and later removed. |
| // |
| // Annotates the API level at which the API added the platform, the API |
| // level at which the API was deprecated, and the API level at which the API |
| // was removed. |
| // |
| // Clients can no longer call APIs if they are compiled to target an API |
| // level at, or beyond, the level at which the API was removed. APIs should be |
| // deprecated for at least one API level before being removed. |
| // |
| // Example: |
| // |
| // void fdio_fork(...) ZX_REMOVED_SINCE(1, 4, 8, |
| // "Root cause of security vulnerabilities due to implicit handle " |
| // "transfer. Use fdio_spawn instead."); |
| // |
| #define ZX_REMOVED_SINCE(level_added, level_deprecated, level_removed, msg) \ |
| __attribute__((availability(fuchsia, strict, introduced = FUCHSIA_API_LEVEL_(level_added), \ |
| deprecated = FUCHSIA_API_LEVEL_(level_deprecated), \ |
| obsoleted = FUCHSIA_API_LEVEL_(level_removed), message = msg))) |
| |
| #else // defined(__clang__) && defined(__Fuchsia__) |
| |
| #define ZX_AVAILABLE_SINCE(level_added) |
| #define ZX_DEPRECATED_SINCE(level_added, level_deprecated, msg) |
| #define ZX_REMOVED_SINCE(level_added, level_deprecated, level_removed, msg) |
| |
| #endif // defined(__clang__) && defined(__Fuchsia__) |
| |
| // ============================================================================= |
| // Macros for conditionally compiling code based on the target API level. |
| // Prefer the attribute macros above for declarations. |
| // |
| // Use to guard code that is added and/or removed at specific API levels. |
| // ============================================================================= |
| |
| // The target API level is `level` or greater. |
| #define FUCHSIA_API_LEVEL_AT_LEAST(level) (__Fuchsia_API_level__ >= FUCHSIA_API_LEVEL_(level)) |
| |
| // The target API level is less than `level`. |
| #define FUCHSIA_API_LEVEL_LESS_THAN(level) (__Fuchsia_API_level__ < FUCHSIA_API_LEVEL_(level)) |
| |
| // The target API level is `level` or less. |
| #define FUCHSIA_API_LEVEL_AT_MOST(level) (__Fuchsia_API_level__ <= FUCHSIA_API_LEVEL_(level)) |
| |
| // ============================================================================= |
| // Internal implementation details of the macros above. |
| // ============================================================================= |
| |
| // To avoid mistakenly using a non-existent name or unpublished API level, the levels specified in |
| // the following macros are converted to calls to a macro containing the specified API level in its |
| // name. If the macro does not exist, the build will fail. See https://fxbug.dev/42084512. |
| #define FUCHSIA_API_LEVEL_CAT_INDIRECT_(prefix, level) prefix##level##_ |
| #define FUCHSIA_API_LEVEL_CAT_(prefix, level) FUCHSIA_API_LEVEL_CAT_INDIRECT_(prefix, level) |
| #define FUCHSIA_API_LEVEL_(level) FUCHSIA_API_LEVEL_CAT_(FUCHSIA_INTERNAL_LEVEL_, level)() |
| |
| // The macros referenced by the output of `FUCHSIA_API_LEVEL_()` must be defined for each API level. |
| // They are defined in the following file, which must be included after the macros above because it |
| // may use those macros. |
| #include <zircon/availability_levels.inc> |
| |
| // Obsolete mechanism for determining whether the target API level is HEAD. |
| // Use one of the macros above instead. |
| // Rather than not defining this identifier, which would cause the preprocessor |
| // to silently treat any instances as zero, define it as a string, which will |
| // cause a compiler error if it is used in a preprocessor comparison. |
| #define FUCHSIA_HEAD \ |
| "DEPRECATED: Use one of the FUCHSIA_API_LEVEL_*() macros in availability.h instead." |
| |
| #endif // ZIRCON_AVAILABILITY_H_ |