[ https://issues.apache.org/jira/browse/STDCXX-1031?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12673756#action_12673756 ]
Martin Sebor commented on STDCXX-1031: -------------------------------------- The patch below modifies the {{\_RWSTD_EXPORT}} macro to enable the gcc attribute. It compiles mostly cleanly, with just a few (13 when building the library) instances of the ??warning: type attributes ignored after type is already defined.?? {code:title=stdcxx-1031.diff} Index: include/rw/_defs.h =================================================================== --- include/rw/_defs.h (revision 744578) +++ include/rw/_defs.h (working copy) @@ -466,27 +466,22 @@ _RW::__rw_new_capacity<T>(from, what) #endif // HP aCC -// set up MSVC DLL export/import directives -// _DLL - defined by the compiler when either -MD or -MDd is used -// RWDLL - defined for all Rogue Wave(R) products built as shared libs -// _RWSHARED - defined for libstd built/used as a shared lib -#if defined (_MSC_VER) && (defined (RWDLL) || defined (_RWSHARED)) - -# ifdef _RWSTD_LIB_SRC -# define _RWSTD_EXPORT __declspec (dllexport) -# else -# define _RWSTD_EXPORT __declspec (dllimport) -# endif // _RWSTD_LIB_SRC - -# define _RWSTD_CLASS_EXPORT _RWSTD_EXPORT -# define _RWSTD_MEMBER_EXPORT /* empty */ -#else - // disable MSVC hacks +// shared librarty export (and possibly import for Windows) +// directive defaults (i.e., disabled unless defined in +// each compiler's config-*.h) +#ifndef _RWSTD_EXPORT # define _RWSTD_EXPORT /* empty */ +#endif + +#ifndef _RWSTD_CLASS_EXPORT # define _RWSTD_CLASS_EXPORT /* empty */ +#endif + +#ifndef _RWSTD_MEMBER_EXPORT # define _RWSTD_MEMBER_EXPORT /* empty */ -#endif // _MSC_VER +#endif + #ifdef _RWSTD_NO_BOOL # define bool int # define false 0 Index: include/rw/_config-gcc.h =================================================================== --- include/rw/_config-gcc.h (revision 744578) +++ include/rw/_config-gcc.h (working copy) @@ -130,6 +130,18 @@ #undef _RWSTD_NO_DEPRECATED_LIBC_IN_STD + +/*** ELF ******************************************************************/ +#ifdef __ELF__ + // all ELF platforms (e.g., Linux or Solaris) +# if 4 <= __GNUG__ + // make use of the visibility attribute as recommended +# define _RWSTD_EXPORT __attribute__ ((visibility ("default"))) +# define _RWSTD_CLASS_EXPORT _RWSTD_EXPORT +# define _RWSTD_MEMBER_EXPORT /* empty */ +# endif // gcc 4 and better +#endif // __ELF__ + /*** CygWin ***************************************************************/ #ifdef __CYGWIN__ // use our own C++ libc headers Index: include/rw/_config-icc.h =================================================================== --- include/rw/_config-icc.h (revision 744578) +++ include/rw/_config-icc.h (working copy) @@ -25,7 +25,7 @@ * implied. See the License for the specific language governing * permissions and limitations under the License. * - * Copyright 1994-2006 Rogue Wave Software. + * Copyright 1994-2006 Rogue Wave Software, Inc. * **************************************************************************/ @@ -63,6 +63,23 @@ # define _RWSTD_NO_OUTLINED_USE_FACET_SPECIALIZATIONS # endif // _RWSHARED +// Windows DLL export/import directives +// _DLL - defined by the compiler when either -MD or -MDd is used +// RWDLL - defined for all Rogue Wave(R) products built as shared libs +// _RWSHARED - defined for libstd built/used as a shared library +# if defined (RWDLL) || defined (_RWSHARED) + +# ifdef _RWSTD_LIB_SRC +# define _RWSTD_EXPORT __declspec (dllexport) +# else +# define _RWSTD_EXPORT __declspec (dllimport) +# endif // _RWSTD_LIB_SRC + +# define _RWSTD_CLASS_EXPORT _RWSTD_EXPORT +# define _RWSTD_MEMBER_EXPORT /* empty */ +# endif // RWDLL || _RWSHARED + + // disable "function was declared "deprecated" # pragma warning (disable: 1786) Index: include/rw/_config-msvc.h =================================================================== --- include/rw/_config-msvc.h (revision 744578) +++ include/rw/_config-msvc.h (working copy) @@ -90,3 +90,19 @@ // MSVC __declspec(noreturn) indicates that a function doesn't return // see: http://msdn.microsoft.com/en-us/library/aa235362(VS.60).aspx #define _RWSTD_NORETURN __declspec (noreturn) + +// MSVC DLL export/import directives +// _DLL - defined by the compiler when either -MD or -MDd is used +// RWDLL - defined for all Rogue Wave(R) products built as shared libs +// _RWSHARED - defined for libstd built/used as a shared library +#if defined (RWDLL) || defined (_RWSHARED) + +# ifdef _RWSTD_LIB_SRC +# define _RWSTD_EXPORT __declspec (dllexport) +# else +# define _RWSTD_EXPORT __declspec (dllimport) +# endif // _RWSTD_LIB_SRC + +# define _RWSTD_CLASS_EXPORT _RWSTD_EXPORT +# define _RWSTD_MEMBER_EXPORT /* empty */ +#endif // RWDLL || _RWSHARED {code} Unfortunately, however, after applying the patch and using the {{-fvisibility=hidden}} option on the command line most non-trivial programs fail to link with errors like: {noformat} gcc codecvt.o -o codecvt -pthread -fvisibility=hidden -L$BUILDDIR/lib -Wl,-R$BUILDDIR/lib -lstd15D -lsupc++ -lm codecvt.o: In function `main': $TOPDIR/examples/manual/codecvt.cpp:40: undefined reference to `std::string::string(char const*, std::allocator<char> const&)' $TOPDIR/examples/manual/codecvt.cpp:41: undefined reference to `std::string::size() const' $TOPDIR/examples/manual/codecvt.cpp:69: undefined reference to `std::string::operator[](unsigned long)' $TOPDIR/examples/manual/codecvt.cpp:69: undefined reference to `std::string::c_str() const' $TOPDIR/examples/manual/codecvt.cpp:88: undefined reference to `std::string::~string()' {noformat} It turns out that this is (most likely) due to the absence of {{extern template}} declarations of exported templates in translation units containing explicit instantiations of other library templates exported from the library. For example, the absence of {{extern template ... class std::string}} in {{[ti_num_get.cpp | http://svn.apache.org/viewvc/stdcxx/branches/4.2.x/src/ti_num_get.cpp?revision=658425&view=markup]}} is a result of not expanding the {{\_RWSTD_INSTANTIATE_3}} macro in {{[<string> | http://svn.apache.org/viewvc/stdcxx/branches/4.2.x/include/string?revision=683995&view=markup]}}: {code:title=<string>} 1618 _RWSTD_NAMESPACE (std) { 1619 1620 #if _RWSTD_INSTANTIATE (_BASIC_STRING, _CHAR) 1621 1622 _RWSTD_INSTANTIATE_3 (class _RWSTD_TI_EXPORT 1623 basic_string<char, char_traits<char>, 1624 allocator<char> >); 1625 1626 #endif // _RWSTD_INSTANTIATE (_BASIC_STRING, _CHAR) {code} A small test case that reproduces this behavior follows: {noformat} $ cat t.cpp \ && g++ -c -DSRC1 -fPIC -fvisibility=hidden t.cpp -ot1.o \ && g++ -c -DSRC2 -fPIC -fvisibility=hidden t.cpp -ot2.o \ && g++ -shared t1.o t2.o -olibt.so \ && g++ t.cpp -L. -lt || objdump -C -t t1.o t2.o libt.so | egrep "(A\(\)|t1|t2|libt)" #ifdef __GNUG__ # define EXPORT __attribute__ ((visibility ("default"))) #elif defined __HP_aCC || defined _MSC_VER # define EXPORT __declspec (dllexport) #else # define EXPORT /* empty */ #endif template <class T> struct A { A (); }; template <class T> A<T>::A () { } template <class T> struct B { A<T> a; B () { } }; #ifdef __pic__ # ifdef SRC1 template struct EXPORT A<int>; # elif defined SRC2 // extern template struct A<int>; // NEEDED template struct EXPORT B<int>; # endif #else // not __pic__ extern template struct EXPORT A<int>; extern template struct EXPORT B<int>; int main () { A<int> a; } #endif // __pic__ /tmp/ccCF48Qh.o: In function `main': t.cpp:(.text+0xd): undefined reference to `A<int>::A()' collect2: ld returned 1 exit status t1.o: file format elf64-x86-64 0000000000000000 w F .text._ZN1AIiEC2Ev 000000000000000a A<int>::A() 0000000000000000 w F .text._ZN1AIiEC1Ev 000000000000000a A<int>::A() t2.o: file format elf64-x86-64 0000000000000000 w F .text._ZN1AIiEC1Ev 000000000000000a .hidden A<int>::A() libt.so: file format elf64-x86-64 000000000000062e l F .text 000000000000000a .hidden A<int>::A() 0000000000000624 w F .text 000000000000000a A<int>::A() {noformat} > [gcc 4.0] make use of gcc 4.1 -fvisibility option > ------------------------------------------------- > > Key: STDCXX-1031 > URL: https://issues.apache.org/jira/browse/STDCXX-1031 > Project: C++ Standard Library > Issue Type: Improvement > Components: Build and Installation > Affects Versions: 4.2.1 > Environment: gcc 4.0 and better on ELF targets > Reporter: Martin Sebor > Assignee: Martin Sebor > Fix For: 4.2.2 > > > The gcc 4.1 {{[-fvisibility | > http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Code-Gen-Options.html#index-fvisibility-1636]}} > option is said to > {quote} > ??...very substantially improve linking and load times of shared object > libraries, produce more optimized code, provide near-perfect API export and > prevent symbol clashes. It is *strongly* recommended that you use this in any > shared objects you distribute.?? > {quote} > In order for stdcxx users to benefit as described in the gcc manual we should > make use of the {{-fvisibility=hidden}} option in conjunction with > {{[\_\_attribute\_\_((visibility("default"))) | > http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Function-Attributes.html#index-g_t_0040code_007bvisibility_007d-attribute-1830]}} > on exported interfaces as the gcc manual recommends. > Besides adding the {{-fvisibility=hidden}} option to the command line when > building shared libraries with gcc, the implementation involves defining the > {{_RWSTD_EXPORT}} macro for gcc as follows: > {code} > #define _RWSTD_EXPORT __attribute__ ((visibility ("default"))) > {code} > Note that since gcc requires the {{\_\_attribute\_\_}} decoration only on > function declarations and issues a warning when it appears on definitions so > the {{_RWSTD_EXPORT}} macro must not be used on definitions. -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online.