// bsls_ident.h -*-C++-*- #ifndef INCLUDED_BSLS_IDENT #define INCLUDED_BSLS_IDENT //@PURPOSE: Provide macros for inserting SCM Ids into source files. // //@CLASSES: // //@MACROS: //: BSLS_IDENT(identifier): inset 'identifier' into '.comment' section //: BSLS_IDENT_RCSID(tag, identifier): alternatively, use add 'tag' as static //: BSLS_IDENT_PRAGMA_ONCE: encapsulate '_Pragma("once")' // //@DESCRIPTION: The purpose of this component is to provide macros for // inserting SCM (Source Control Management) Ids into source files. SCM Ids // are useful for identifying source revisions in binaries. Additional // information about SCM Ids may be obtained from the following man pages: // 'man ident' 'man strings' ('strings -a' produces more verbose output) // 'man mcs' (Solaris-only) // // Note that these SCM Ids are only present if the 'BSLS_IDENT_ON' macro is // defined at compilation time. By default, this macro is *not* defined, and // ident strings are *not* added to object files. // // SCM systems may replace Ids with their expanded forms. Note that we will // replace the key symbol '$' with '(DOLLAR)' to avoid any expansion within // this header file's documentation. // // SCM Ids usually take the form "(DOLLAR)Id: (DOLLAR)" which is expanded, // automatically, by the source control system into an identifier which maps to // specific source revision: //.. // '(DOLLAR)Id: bsls_ident.h 141104 2010-09-17 00:30:47Z mgiroux (DOLLAR)' //.. // This specifies that the file was checked in on 2010-09-17 at the specified // time by user 'mgiroux', and can be retrieved from the SCM system using // revision '141104'. // // 'BSLS_IDENT_PRAGMA_ONCE' can optionally be used in headers and encapsulates // a non-standard pragma (_Pragma("once")) supported on a number of platforms // and which indicates that a header should only be included and parsed once. // Use of this macro can help reduce compile times by eliminating extraneous // I/O when headers are included more than once in the same translation unit. // Note that this macro should *not* be used for any header that cannot use // include guards: this is unusual, but can happen for certain low-level // headers. // ///Macro Summary ///------------- // The following are the macros provided by this component. // //: 'BSLS_IDENT(identifier)' //: This macro inserts the specified 'identifier' into the object's //: '.comment' section, if supported on the current platform. //: //: 'BSLS_IDENT_RCSID(tag, identifier)' //: This macro inserts the specified 'identifier' into the object, using //: 'BSLS_IDENT', if possible on the current platform. If 'BSLS_IDENT' is //: not available, the specified 'tag' may be used to declare a static char //: array containing the 'tag'. //: //: 'BSLS_IDENT_PRAGMA_ONCE' //: This macro encapsulates the '_Pragma("once")' functionality if available //: on the current platform. If available, this functions in the same way as //: redundant include guards, avoiding re-opening already-included header //: files. // ///Usage ///----- // Include 'bsls_ident.h' and use the BSLS_IDENT macro. For header files this // should be done directly after the include guards, e.g., bsls_somefile.h: //.. // // bsls_somefile.h -*-C++-*- // #ifndef INCLUDED_BSLS_SOMEFILE // #define INCLUDED_BSLS_SOMEFILE // // #include <bsls_ident.h> // BSLS_IDENT("(DOLLAR)Id: (DOLLAR)") // In real usage, replace '(DOLLAR)' // // with '$' // // // ... // // #endif // INCLUDED_BSLS_SOMEFILE //.. // For cpp files it should be done directly after the comment for the file name // and the language, e.g., bsls_somefile.cpp: //.. // // bsls_ident.t.cpp -*-C++-*- // // #include <bsls_ident.h> // BSLS_IDENT("(DOLLAR)Id: (DOLLAR)") // In real usage, replace '(DOLLAR)' // // with '$' //.. #undef BDE_OMIT_INTERNAL_DEPRECATED #ifdef BDE_FORCE_OMIT_INTERNAL_DEPRECATED #define BDE_OMIT_INTERNAL_DEPRECATED #endif #undef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES #ifdef BDE_FORCE_DONT_ALLOW_TRANSITIVE_INCLUDES #define BDE_DONT_ALLOW_TRANSITIVE_INCLUDES #endif /* ident string intentionally omitted for this header (do not add to binaries) * Its use is expected to be so extensive that the cost outweighs benefit * of including an ident string for every file that includes this header * (present here so that programs like update_rcsid do not accidentally add) */ #if 0 #define BSLS_IDENT_RCSID(tag,str) BSLS_IDENT_RCSID(sysutil_ident_h,"$Id: $") #endif // Enabling BSLS_IDENT by default causes significant bloat - see internal // ticket D29644737. #ifndef BSLS_IDENT_ON #ifndef BSLS_IDENT_OFF #define BSLS_IDENT_OFF #endif // ifndef BSLS_IDENT_OFF #endif // ifndef BSLS_IDENT_ON /* BSLS_IDENT() - insert string into .comment binary segment (if supported)*/ #if defined(__GNUC__) #if !defined(_AIX) /* does not work with AIX as; might work with GNU as (gas) (not tested) */ /* gcc has no pragma equivalent for #ident */ #define _BSLS_IDENT(str) __asm__(#str); #define BSLS_IDENT(str) _BSLS_IDENT(.ident str) #endif #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Sun Studio CC does not support _Pragma() until Sun Studio 12 */ #if (!defined(__cplusplus)) || (__SUNPRO_CC >= 0x590) #define _BSLS_IDENT(str) _Pragma(#str) #define BSLS_IDENT(str) _BSLS_IDENT(ident str) #endif #elif defined(__IBMC__) || defined(__IBMCPP__) #define _BSLS_IDENT(str) _Pragma(#str) #define BSLS_IDENT(str) _BSLS_IDENT(comment (user, str)) #elif defined(_MSC_VER) /* Microsoft Visual Studio Compiler */ /* Microsoft linker ignores __pragma(comment (user, "str")) * http://msdn.microsoft.com/en-us/library/7f0aews7.aspx */ #if 0 /* disable SYSUTIL_IDENT() with Microsoft compiler */ #define _BSLS_IDENT(str) __pragma(comment (user, #str)) #define BSLS_IDENT(str) _BSLS_IDENT(str) #endif #elif defined(__HP_cc) || defined(__HP_aCC) #define _BSLS_IDENT(str) _Pragma(#str) #define BSLS_IDENT(str) _BSLS_IDENT(versionid str) #endif #ifndef BSLS_IDENT #define BSLS_IDENT(str) #endif /* multi-level indirection to force macro expansion before concatenation */ /* (order of concatenation/macro expansion unspecified in ANSI standard) */ #define BSLS_IDENT_JOIN2(x,y) x ## y #define BSLS_IDENT_JOIN(x,y) BSLS_IDENT_JOIN2(x,y) /* BSLS_IDENT_RCSID() - insert ident str (specific to platform/compiler) */ #if defined(__GNUC__) #if !defined(_AIX) #define BSLS_IDENT_RCSID(tag,str) BSLS_IDENT(str) #else /* _AIX */ /* (XXX: look into further if we ever use gcc to build prod tasks on AIX) */ #ifndef lint #define BSLS_IDENT_RCSID(tag,str) \ static char BSLS_IDENT_JOIN(ident_,tag)[] __attribute__((__unused__)) \ = str; #endif #endif #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) #if (!defined(__cplusplus)) || (__SUNPRO_CC >= 0x590) #define BSLS_IDENT_RCSID(tag,str) BSLS_IDENT(str) #else /* Sun Studio CC does not support _Pragma() until Sun Studio 12 */ #ifndef lint #define BSLS_IDENT_RCSID(tag,str) \ static char BSLS_IDENT_JOIN(ident_,tag)[] = str; #endif #endif #elif defined(__IBMC__) || defined(__IBMCPP__) #if ((defined(__IBMC__) && __IBMC__ >= 1010) \ || (defined(__IBMCPP__) && __IBMCPP__ >= 1010)) #define BSLS_IDENT_RCSID(tag,str) BSLS_IDENT(str) #else /* Early versions of IBM xlc did not preserve .comment in binary * executables or pre-linked libraries. Fixed by IBM in following * releases: * xlC v8.0 in May 2008 PTF (8.0.0.19) with -qxflag=new_pragma_comment_user * xlC v9.0 in July 2008 PTF (9.0.0.5) * xlC v10.1 GA * Enabled above only for xlC 10.1 or later, which can be detected reliably * (Use C compiler and printf("%s\n", __xlc__) to see x.x.x.x version, * but strings are not comparable in macros) * Note that using updated linker (bind64) (circa late 2010) is also needed * for the ident strings to be present in pre-linked libs and executables. */ /* various ways to create C string, including const, volatile, more */ /* static char instead of static const char with xlC -qnoro -qnoroconst */ /* xlC might end up optimizing this away, anyway */ #ifndef lint #define BSLS_IDENT_RCSID(tag,str) \ static char BSLS_IDENT_JOIN(ident_,tag)[] = str; #endif #endif #elif defined(_MSC_VER) #define BSLS_IDENT_RCSID(tag,str) BSLS_IDENT(str) #elif defined(__HP_cc) || defined(__HP_aCC) #define BSLS_IDENT_RCSID(tag,str) BSLS_IDENT(str) #else /* others: add conditions above for compilers able to support BSLS_IDENT */ #ifndef lint #define BSLS_IDENT_RCSID(tag,str) \ static char BSLS_IDENT_JOIN(ident_,tag)[] = str; #endif #endif #ifndef BSLS_IDENT_RCSID #define BSLS_IDENT_RCSID(tag,str) #endif /* timestamp compilation with BUILDID, if provided. (occurs once per object) * Use BSLS_IDENT() so only occurs in .comment section if supported. * example usage in a Makefile target: * $(CC) -c -DBUILDID="$(@F) `date +%Y%m%d_%H%M%S`" -o file.o file.c */ #ifdef BUILDID #define _BSLS_IDENT_BUILDID_IMP2(str) BSLS_IDENT(#str) #define _BSLS_IDENT_BUILDID_IMP(str) _BSLS_IDENT_BUILDID_IMP2(str) _BSLS_IDENT_BUILDID_IMP($cc: BUILDID $) #undef _BSLS_IDENT_BUILDID_IMP #undef _BSLS_IDENT_BUILDID_IMP2 #endif #ifdef BSLS_IDENT_OFF #undef BSLS_IDENT #undef BSLS_IDENT_RCSID #define BSLS_IDENT(str) #define BSLS_IDENT_RCSID(tag,str) #endif /* !BSLS_IDENT_OFF */ #if defined(__GNUC__) #define BSLS_IDENT_PRAGMA_ONCE _Pragma("once") #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Sun Studio does not support #pragma once. Instead, it natively detects if * the entire non-comment portion of a file is wrapped by #ifndef, and if so, * optimizes away reopens of the file if the #ifndef condition is false */ #define BSLS_IDENT_PRAGMA_ONCE #elif defined(__IBMC__) || defined(__IBMCPP__) #define BSLS_IDENT_PRAGMA_ONCE _Pragma("once") #elif defined(_MSC_VER) #define BSLS_IDENT_PRAGMA_ONCE __pragma(once) #elif (defined(__HP_cc) && __HP_cc-0 >= 62500) \ || (defined(__HP_aCC) && __HP_aCC-0 >= 62500) /* supported in aCC A.06.25 (had not been fully supported in aCC A.06.20) */ #define BSLS_IDENT_PRAGMA_ONCE _Pragma("once") #else #define BSLS_IDENT_PRAGMA_ONCE #endif BSLS_IDENT_PRAGMA_ONCE /* Technical notes: * * There is a cost to including ident extra information in the binary objects, * which may include disk space usage and runtime memory usage, as well as * side effects such as locality of strings in memory at runtime. * * Some vendors provide a mechanism to include ident strings in a non-loadable * .comment section of the binary so that strings are available for review in * the on-disk binary, but are not loaded into memory at runtime. * (Alternatively, this separate non-loadable section might selectively be * stripped from the binary, saved in a database with the checksum of the * stripped binary, and then the resulting smaller binary moved to production.) * * bsls_ident.h encapsulates ident mechanisms so that includers of this * header need not be concerned with the mechanism applied. The mechanism may * be changed as better methods become available and the includer can obtain * the changes simply by recompiling (without needing to modify all other * source code). * * 'ident' shows only ident-style strings. 'man ident' for more info. * The tokens passed to the pragmas are not necessarily ident-style. * They are still visible with 'strings -a'. * * IBM xlC supports #pragma comment * IBM xlC warns about #pragma ident and errors for #ident * Sun CC supports #pragma ident and #ident * Sun CC silently ignores #pragma comment * GCC supports #ident * GCC warns about unrecognized #pragma ident and #pragma comment * While these can all be worked around by disabling specific warnings/errors, * doing so might mask other warnings/errors. This header allows for * encapsulation of all the conditional logic to use the correct pragma with * each compiler without having to duplicate these conditions in every source * file. * * #ident, #pragma ident, #pragma comment each can take a -single- user-defined * token (no concatenation of string constants or preprocessor macro ## * concatenation) (MS Visual Studio will do string concatenation) * * C99 _Pragma() can expanded in macros and can be used in place of #pragma. * GCC does not implement a #pragma version of gcc #ident preprocessor * directive * * AIX 'strip' removes strings inserted by #pragma comment * Solaris mcs -d removes strings inserted by #ident and #pragma ident * (equivalent to compiling with cc -mr) * mcs -c uniquifies the strings (equivalent to compiling with cc -mc) * ('strip' does not remove these strings) * GNU strip: 'strip -R comment' will remove .comment section * * AIX multiple #pragma comment end up concatenated on a single line, allowing * for pasting together of individual tokens. 'ident' prints each ident-style * string on its own line. Solaris #ident places each token on its own line. * * Sun Studio CC (C++ compiler) < Sun Studio 12 CC do not support _Pragma() * Sun Studio 12 CC supports _Pragma() but clips the first character of string * (This leads to strings being present in .comment section, minus the first * character, and then not showing up when 'ident' is run, but present with * strings -a) (Bug filed with Sun and has been fixed in latest Studio 12). */ #endif // INCLUDED_BSLS_IDENT // ---------------------------------------------------------------------------- // Copyright 2013 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------