I just discovered the #pragma weak
directive in GCC:
6.57.9 Weak Pragmas
For compatibility with SVR4, GCC supports a set of #pragma directives for declaring symbols to be weak, and defining weak aliases.
#pragma weak symbol
This pragma declares symbol to be weak, as if the declaration had the attribute of the same name. The pragma may appear before or after the declaration of symbol. It is not an error for symbol to never be defined at all.
#pragma weak symbol1 = symbol2
This pragma declares symbol1 to be a weak alias of symbol2. It is an error if symbol2 is not defined in the current translation unit.
http://gcc.gnu.org/onlinedocs/gcc/Weak-Pragmas.html
Despite the fact that the GCC developers generally don't like #pragma
and encourage you to use __attribute__
instead for all sorts of things that could be pragmas, I'm inclined to believe #pragma weak
may actually be superior to the attribute-based approach, which looks like:
extern __typeof(old_name) new_name __attribute__(weak, alias("old_name"))
Aside from the ugliness of requiring __typeof
(or requiring you to know the type and spell it out explicitly, even if it's a really complex function type), the biggest issue of the attribute based approach is that "old_name"
must be passed to gcc as a string to be pasted literally into the generated assembly. This is problematic because different systems have different name-mangling characteristics (most popular is prefixing an underscore on all C symbol names, or doing nothing at all), and to pass the correct string to the alias
attribute, you need to know the name mangling convention of the system you're building for, which is really not knowledge that belongs in an application-level library where weak aliases might be useful.
The syntax #pragma weak new_name = old_name
seems to avoid this issue by handling both names at the compiler level, where t can mangle them both appropriately, unless I'm mistaken.
So with all the preliminaries finished, my actual questions are: Am I mistaken about #pragma weak
having this "portability" advantage? and Do all modern compilers on unix-like systems (gcc, pcc, tinycc, icc, llvm/clang, etc.) still support the traditional SVR4 #pragma weak
?
I'm aware of the following similar question, but it does not seem quite the same and the answers to not satisfactorily address my question:
How portable is weak linking? #pragma weak my_symbol
Neither "#pragma weak" nor __attribute__ is part of the C standard, so neither is, strictly speaking, portable. Some C compilers strive to be compatible with most of GCC's extensions to the C standard, others do not.
Generally speaking, if you're already at the level of talking about weak symbols and weak aliases, you probably are past the point where you can write code that is reliably portable across compilers. Even your toolchain will become an issue here (including especially the linker) -- I don't think you can rely on anything without carefully testing.
Edited to add: The original poster commented below asking whether, pragmatically, #pragma is no less portable than __attribute__.
My own experience has been this: it is nice to be able to hide all such things inside of macros or other generated code in order to make portability easier. __attribute__ is easier to conceal inside a portability header file. For example, at least one of the BSD kernels has a cdefs.h that uses __attribute__ inside a macro to centralize the way that weak definitions are done throughout the code base to allow easier changes to new compilers. #pragma is harder to use in that manner. Such a macro can also conceal the difference between various name manglings by using the CPP pasting operator ("##" etc.)
For an example of such usage, see: http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/sys/cdefs.h?rev=1.89.6.1&content-type=text/x-cvsweb-markup
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With