|
BDE 4.14.0 Production release
|
Macros | |
| #define | BSLS_DEPRECATE_COMPILER_SUPPORT 0 |
| #define | BSLS_DEPRECATE |
| #define | BSLS_DEPRECATE_CAT(X, Y) BSLS_DEPRECATE_CAT_A(X, Y) |
| #define | BSLS_DEPRECATE_CAT_A(X, Y) BSLS_DEPRECATE_CAT_B(X, Y) |
| #define | BSLS_DEPRECATE_CAT_B(X, Y) X ## Y |
Internal implementation machinery for BSLS_DEPRECATE_CAT. | |
| #define | BSLS_DEPRECATE_ISDEFINED(...) BSLS_DEPRECATE_ISDEFINED_A(__VA_ARGS__) |
| #define | BSLS_DEPRECATE_ISDEFINED_A(...) ((__VA_ARGS__ ## 1L) != 0) |
Internal implementation machinery for BSLS_DEPRECATE_ISDEFINED. | |
| #define | BSLS_DEPRECATE_ISNONZERO(...) BSLS_DEPRECATE_ISNONZERO_A(__VA_ARGS__) |
| #define | BSLS_DEPRECATE_ISNONZERO_A(...) (__VA_ARGS__ + 1 != 1) |
Internal implementation machinery for BSLS_DEPRECATE_ISNONZERO. | |
| #define | BSLS_DEPRECATE_MAKE_VER(M, N) ((M) * 1000 + (N)) |
| #define | BSLS_DEPRECATE_ISPASTTHRESHOLD(U, M, N) |
| #define | BSLS_DEPRECATE_ISPASTTHRESHOLD_A(U) BSLS_DEPRECATE_CAT(U, _VERSION_DEPRECATION_THRESHOLD) |
Internal implementation machinery for BSLS_DEPRECATE_ISPASTTHRESHOLD. | |
| #define | BSLS_DEPRECATE_ISRETAINED(U, M, N) BSLS_DEPRECATE_ISRETAINED_A(U, M, N) |
| #define | BSLS_DEPRECATE_ISRETAINED_A(U, M, N) BSLS_DEPRECATE_ISRETAINED_B(U, M, N) |
| #define | BSLS_DEPRECATE_ISRETAINED_B(U, M, N) |
Internal implementation machinery for BSLS_DEPRECATE_ISRETAINED. | |
| #define | BSLS_DEPRECATE_IS_ACTIVE(U, M, N) |
Provide machinery to deprecate interfaces on a per-version basis.
This component defines a suite of macros to control (on a per-version, per-UOR basis) the deprecation of functions, user-defined types, and typedefs, and the conditional compilation of enumerators and preprocessor macros. The bsls_deprecate facility operates by triggering compiler warnings when types or interfaces are used that have been tagged with deprecation macros defined by this component. Unlike previous deprecation facilities based exclusively on the use of #ifndef with global macros (such as BDE_OMIT_DEPRECATED and BDE_OMIT_INTERNAL_DEPRECATED), supported use of the bsls_deprecate facility does not affect a UOR's ABI. It is therefore safe to link applications based on libraries built with different deprecation policies.
UOR owners who wish to mark an interface as deprecated can do so by tagging the declaration of that interface with the BSLS_DEPRECATE macro, wrapped in a #if block to apply BSLS_DEPRECATE only when BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N) evaluates to true for a given version M.N of the specified UOR:
The above application of BSLS_DEPRECATE_IS_ACTIVE indicates that foo is deprecated starting with bde version 3.2. Once the deprecation threshold for bde advances to version 3.2, code calling foo will generate a deprecation warning with compilers that support deprecation attributes. (See {Version Control Macros for Library Authors} for information on defining a deprecation threshold for a UOR.) Note that in the absence of an explicit deprecation threshold (BDE_VERSION_DEPRECATION_THRESHOLD, in this case), code calling foo would begin generating deprecation warnings in the very next minor or major release of bde (3.3 or 4.0, whichever applies).
If an interface has several entities being deprecated at the same time, clients can define a new deprecation macro within that header to avoid repeated use of BSLS_DEPRECATE_IS_ACTIVE:
When an interface is tagged with BSLS_DEPRECATE as shown above, the deprecation is initially not enforced by default. That is, a normal build of code calling the deprecated interface will not emit a deprecation warning.
Downstream developers who wish to make sure that their code uses no deprecated interfaces can do so by defining the symbol BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY in their build system.
NEVER define BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY in a PRODUCTION BUILD CONFIGURATION. If you do so, all libraries that you depend on will be prevented from deprecating more code in future versions.
At some point after an interface has been tagged with BSLS_DEPRECATE, the library owner can make new uses of that interface generate warnings by defining a deprecation threshold for the UOR that contains the deprecated interface (or by adjusting the deprecation threshold for the UOR if it already exists). Defining a deprecation threshold enforces deprecations made in all versions up to and including the threshold. If the version number of the deprecation threshold is greater than or equal to the version number specified in the BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N) macro, then the BSLS_DEPRECATE macro will be enabled and generate a warning.
This is the recommended way to define a deprecation threshold (see Version Control Macros for Library Authors :
Prior to the availability of this component, when a developer wanted to deprecate an API they might either apply an attribute to the API that would generate a warning, or they would use #ifdef to remove deprecated code when it is built with appropriate options. These solutions have a practical shortcoming in a production environment like Bloomberg's, where code changes in lower-level libraries cannot be checked in if they break the build of (higher-level) client libraries. In such a system, well-meaning clients might build their libraries using -Werror (to turn compilation warnings into errors) or with appropriate #ifdefs to ensure their code does not use deprecated APIs, but in so doing they hinder the introduction of any new deprecations. In addition, the use of #ifdef results in ABI compatibility issues, as some clients may build with deprecated code removed, and others may not.
This deprecation facility is based around two concepts that attempt to address these shortcomings:
BSLS_DEPRECATE_* macros are used to trigger compilation warnings on platforms that support deprecation attributes, instead of removing code from the codebase.BSLS_DEPRECATE macro is generally guarded by a version check using BSLS_DEPRECATE_IS_ACTIVE. In an environment where compiler warnings are considered to be build failures, it is possible (and encouraged) to tag a C++ entity with a deprecation macro in one release cycle, and not have that deprecation affect any clients by default until a later release cycle. During the intervening period, clients have an opportunity to proactively check their code for uses of newly-deprecated code.Notice that the cost for maintaining ABI compatibility is that clients cannot check whether they are using deprecated interfaces unless they build their software on certain platforms with warnings activated. For this facility to be effective across an enterprise, it is required that such warning-enabled builds be part of the standard process for checking in code in the enterprise.
This component stipulates two sets of macros. One set of deprecation macros, defined in this component, are used to identify a C++ entity as being deprecated in a given version of a given UOR. A second set of control macros, defined by clients of this component, dictates which deprecation macros are enforced at any point in the code during compilation.
BSLS_DEPRECATE Expands to a particular deprecation attribute with compilers that have such support; otherwise,
BSLS_DEPRECATEexpands to nothing.BSLS_DEPRECATEcan be applied toclassorstructdefinitions, function declarations, andtypedefs.
BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N) These two macros are intended to be placed together in a preprocessorExpands to 1 if deprecations are enforced for the specified version
M.Nof the specifiedUOR, and to 0 otherwise.
#if block in front of a function, type, or typedef declaration, with BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N) controlling whether or not BSLS_DEPRECATE is applied to the declaration. The exact placement of the block should match the requirements of the C++14 [[deprecated]] attribute.Examples:
At present, the underlying compiler intrinsics represented by BSLS_DEPRECATE cannot be applied uniformly to some C++ constructs, most notably variables, enumerators, and preprocessor macros. Fortunately, these constructs can often be removed from a library without otherwise affecting ABI, so !BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N) can be used with a #if directive to entirely remove blocks of code containing those C++ constructs.
Example:
Note the use of the ! operator: deprecated code is compiled only if deprecations are not enforced for the specified UOR version.
Particular care must be taken to ensure that deprecating one or more enumerators does not (inadvertently) change the values of other enumerators in the same enum:
A UOR-specific deprecation threshold can be (and typically should be) specified by the authors of a UOR to govern which of their deprecations are active by default:
<UOR>_VERSION_DEPRECATION_THRESHOLD Example:This macro should be defined in
<uor>scm_versiontag.halongside<UOR>_VERSION_MAJORand<UOR>_VERSION_MINORto indicate the greatest version of the unit of releaseUORfor which deprecations are enforced by default.
BSLS_DEPRECATE_IS_ACTIVE(ABC, M, N) will expand to 1 for all versions M.N of ABC up to and including version 1.2. For M.N later than 1.2 (e.g., 1.3 or 2.0), BSLS_DEPRECATE_IS_ACTIVE(ABC, M, N) will expand to 1 only if the BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY macro is defined by the user (see {Build Control Macros for Clients}).Note that if a deprecation threshold is not explicitly defined for a UOR that defines <UOR>_VERSION_MAJOR and <UOR>_VERSION_MINOR, then BSLS_DEPRECATE_IS_ACTIVE(UOR, M, N) will expand to 1 once the version indicated by <UOR>_VERSION_MAJOR and <UOR>_VERSION_MINOR becomes greater than M.N. For example, BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 4) will expand to 1 in version 1.5 of ABC (or 2.0 if there is no release 1.5) if ABC_VERSION_DEPRECATION_THRESHOLD is not defined. For this reason, it is highly recommended that UOR authors explicitly define a deprecation threshold to avoid unexpected build failures when a new release is issued, especially in environments where warnings are considered fatal.
A second UOR-specific macro is available to the authors of a UOR that must, for whatever reason, continue to use interfaces that are deprecated in their own library:
BB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_<UOR> Example:This macro prevents bsls_deprecate from enforcing deprecations for all versions of
UOR. This macro must be defined in each.cppfile ofUORthat either uses a deprecated interface from the same UOR that has reached the deprecation threshold forUOR, or includes a header file ofUORthat uses such an interface in inline code. This macro must be defined before the first#includeof a header fromUOR.
The following two macros are intended for client use during builds, either to enable all deprecations or to suppress selected deprecations:
BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY This macro should be defined as a
-Dparameter during test builds of components that are intended to be deprecation-clean. When this macro is defined, deprecations will be enforced for all versions of all UORs, except as overridden byBB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_<UOR>(see Version Control Macros for Library Authors orBB_SILENCE_DEPRECATIONS_<UOR>_<M>_<N>(see below). This macro must never appear in source code, and must never be defined for any production or check-in build configuration.
BB_SILENCE_DEPRECATIONS_<UOR>_<M>_<N> Example:This macro should be defined by clients of
UORwho still need to use an interface that was deprecated in versionM.Nafter the deprecation threshold forUORhas reached (or exceeded)M.N. This macro should be defined before the first#includeof a header fromUOR. This macro must never be defined in a header file.
BSLS_DEPRECATE will produce a warning with the following compilers:
Additionally, BSLS_DEPRECATE will produce a warning with any compiler that provides the C++14 deprecated attribute.
Deprecation is a negotiation process between code authors and code consumers to allow old code to be removed from the codebase. This component supports a deprecation model where code moves through four steps from being fully supported, to optionally deprecated, to fully deprecated, and finally to being deleted. At each step, responsibility for moving the process forward is passed back and forth between library authors and library users.
When the owners of a library want to deprecate an interface, they start by adding appropriate deprecation macros, specifying their UOR and the version of their next release. For example, suppose package group abc is currently at version 1.1. If the owners of abc want to deprecate a function abcxyz::SomeUtil::someFunction, they could add the deprecation macros BSLS_DEPRECATE and BSLS_DEPRECATE_IS_ACTIVE(ABC, 1, 2) in front of the declaration of someFunction:
At this point deprecations are not enforced by default for version 1.2 of abc, so the deprecation macro alone will not have any affect on clients. A client building their code normally will trigger no compiler warnings due to this new deprecation:
If the owners of a client library or application want to check that their code uses no deprecated interfaces, they can define the BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY flag in their test build process. A compiler that supports deprecation attributes will then trigger compiler warnings:
WARNING: Clients at Bloomberg must not define BB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY in a production build. This flag should be used for development builds only.
Now the owners have the opportunity to fix their code by removing the dependency on abcxyz::SomeUtil::someFunction.
At some point in the future, possibly on release of abc version 1.3, the owners of abc will make deprecations enforced by default for version 1.2 of abc, by setting the deprecation threshold for abc in their version control headers:
If the owners of grp have cleaned up their code, normal builds will trigger no compiler warnings. However, any new development by any clients will trigger warnings if they add a new use of abcxyz::SomeUtil::someFunction:
But what if the owners of grp will not, or for some reason cannot, clean up their code in the near term? Moving the threshold for abc to version 1.2 will of course trigger warnings when the owners of grp next try to build grppkg_fooutil . In a development context requiring that all production builds remain warning-free, we would be at an impasse: either the owners of grp must clean up their code immediately, or the owners of abc will not be able to enforce deprecations by default for version 1.2.
This impasse can be resolved by allowing the owners of grp to locally silence warnings caused by deprecations for version 1.2 of abc. This is done by adding a definition of BB_SILENCE_DEPRECATIONS_ABC_1_2 to any .cpp files that use abcxyz::SomeUtil::someFunction:
Now the entire codebase can build warning-free again.
Managers can easily detect BB_SILENCE_DEPRECATIONS_<UOR>_<M>_<N> macros in the codebase, and put pressure on teams to remove such remnant uses of deprecated code. When all remnant uses have been removed, then the deprecated function can be deleted entirely:
This section illustrates intended use of this component.
When one piece of code has been superseded by another, we would like to get users to adopt the new code and stop using the old code. Being able to inform clients that they need to clean up existing uses of the old code, and also to prevent new uses of that code, makes it easier to get to the point where old code actually has zero uses and can be deleted. The deprecation macros BSLS_DEPRECATE and BSLS_DEPRECATE_IS_ACTIVE, and their associated control macros, can be used to gradually reduce the number of uses of deprecated code, so that it can be removed eventually.
Suppose we own package group xxx that is currently at version 7.6. One of our components contains a function foo that has been superseded by another function bar.
First, we add a deprecation tag to the declaration of foo, showing that it will be deprecated starting with version 7.7, and update the documentation accordingly:
When we release version 7.7, the added deprecation tag will not immediately affect any of the users of foo. However if any of those users do a test build of their code with -DBB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY, they will see a warning that foo has been deprecated.
Finally, when enough time has passed to allow all users of foo to switch over to using bar, probably on or after the release of xxx version 7.8, we can enforce the deprecation of foo by moving the deprecation threshold for xxx to version 7.7, to indicate that all interfaces deprecated for version 7.7 are disallowed by default:
| #define BSLS_DEPRECATE |
| #define BSLS_DEPRECATE_CAT | ( | X, | |
| Y | |||
| ) | BSLS_DEPRECATE_CAT_A(X, Y) |
Expand to the expansion of the specified X, joined to the expansion of the specified Y.
| #define BSLS_DEPRECATE_CAT_A | ( | X, | |
| Y | |||
| ) | BSLS_DEPRECATE_CAT_B(X, Y) |
| #define BSLS_DEPRECATE_CAT_B | ( | X, | |
| Y | |||
| ) | X ## Y |
| #define BSLS_DEPRECATE_COMPILER_SUPPORT 0 |
| #define BSLS_DEPRECATE_IS_ACTIVE | ( | U, | |
| M, | |||
| N | |||
| ) |
Expand to an expression evaluating to true in a preprocessor context if deprecations are being enforced for the specified version M.N of the specified UOR U, and expand to an expression evaluating to false otherwise. Deprecations will be enforced for version M.N of UOR U if:
BB_SILENCE_DEPRECATIONS_<U>_<M>_<N> has not been defined in this translation unit, andBB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_<U> has not been defined in this translation unit, andBB_WARN_ALL_DEPRECATIONS_FOR_TESTING_ONLY has been defined, orU and that threshold is greater than or equal to version M.N, orU, the versioning package for UOR U defines <U>_VERSION_MAJOR and <U>_VERSION_MINOR, and the version so designated is greater than version M.N. | #define BSLS_DEPRECATE_ISDEFINED | ( | ... | ) | BSLS_DEPRECATE_ISDEFINED_A(__VA_ARGS__) |
Expand to an expression evaluating to true in a preprocessor context if the deprecation control macro symbol supplied as an argument has been #defined as nil, 0, or 1, and expand to an expression evaluating to false otherwise. The behavior is undefined unless this macro is evaluated with a single argument having the form of a deprecation control macro symbol, and that symbol has either not been #defined at all or has been #defined as nil, 0, or 1.
| #define BSLS_DEPRECATE_ISDEFINED_A | ( | ... | ) | ((__VA_ARGS__ ## 1L) != 0) |
| #define BSLS_DEPRECATE_ISNONZERO | ( | ... | ) | BSLS_DEPRECATE_ISNONZERO_A(__VA_ARGS__) |
Expand to an expression evaluating to true in a preprocessor context if the deprecation control macro symbol supplied as an argument has been #defined as an expression that evaluates to a non-zero value, and expand to an expression evaluating to false otherwise. The behavior is undefined unless this macro is evaluated with a single argument having the form of a deprecation control macro symbol, and that symbol has either not been #defined at all, or has been #defined as nil or an arithmetic expression.
| #define BSLS_DEPRECATE_ISNONZERO_A | ( | ... | ) | (__VA_ARGS__ + 1 != 1) |
| #define BSLS_DEPRECATE_ISPASTTHRESHOLD | ( | U, | |
| M, | |||
| N | |||
| ) |
Expand to an expression evaluating to true in a preprocessor context if the specified version M.N of the specified UOR U is past the deprecation threshold for U, and expand to an expression evaluating to false otherwise. Version M.N of U is past the deprecation threshold for U if:
U and that threshold is greater than or equal to version M.N, orU, the versioning package for UOR U defines <U>_VERSION_MAJOR and <U>_VERSION_MINOR, and the version so designated is greater than version M.N. | #define BSLS_DEPRECATE_ISPASTTHRESHOLD_A | ( | U | ) | BSLS_DEPRECATE_CAT(U, _VERSION_DEPRECATION_THRESHOLD) |
| #define BSLS_DEPRECATE_ISRETAINED | ( | U, | |
| M, | |||
| N | |||
| ) | BSLS_DEPRECATE_ISRETAINED_A(U, M, N) |
Expand to an expression evaluating to true in a preprocessor context if deprecations in the specified version M.N of the specified UOR U have been deactivated in this build by defining either the corresponding BB_SILENCE_DEPRECATIONS_<U>_<M>_<N> macro or the corresponding BB_SILENCE_DEPRECATIONS_FOR_BUILDING_UOR_<U> macro, and expand to an expression evaluating to false otherwise.
| #define BSLS_DEPRECATE_ISRETAINED_A | ( | U, | |
| M, | |||
| N | |||
| ) | BSLS_DEPRECATE_ISRETAINED_B(U, M, N) |
| #define BSLS_DEPRECATE_ISRETAINED_B | ( | U, | |
| M, | |||
| N | |||
| ) |
| #define BSLS_DEPRECATE_MAKE_VER | ( | M, | |
| N | |||
| ) | ((M) * 1000 + (N)) |
Expand to an opaque sequence of symbols encoding a UOR version where the specified M is the major version number and the specified N is the minor version number.