future GCC 4.3 and modules.h
Hello CLN people, Consider this code snippet: extern "C" void func () {} __asm__("\t.globl " "_GLOBAL__I_" "func"); static struct S { inline S () { } } S; On x86_64, with `g++-4.2 -fPIC -c a.cc', this results in | 0000000000000032 T _GLOBAL__I_func with mainline GCC (what will eventually be 4.3 or some other number), it has | 0000000000000032 t _GLOBAL__I_a.cc (and of course that will be `T' with the appropriate .globl directive). This affects .libs/cl_DF_globals.o and some of the other globals objects, and causes a link failure of the examples due to the CL_REQUIRE undefined references (global constructor keyed to ...). The hack below makes things work with mainline, but still needs to be redone properly, with a configure-time check and so on to not regress on g++ <= 4.2. If you like I can take a stab at writing so; I assume the test should make use of $lt_compiler_pic_CXX and the header file provide different defines based on whether -DPIC was given? (I'm not all that experienced with this stuff, so pointers are greatly appreciated.) Cheers, Ralf Index: include/cln/modules.h =================================================================== RCS file: /home/cvs/cln/include/cln/modules.h,v retrieving revision 1.19 diff -u -r1.19 modules.h --- include/cln/modules.h 7 May 2006 21:05:24 -0000 1.19 +++ include/cln/modules.h 26 May 2007 16:44:38 -0000 @@ -219,7 +219,7 @@ }; \ static _CL_REQUIRE_CLASSNAME(module,__LINE__) \ _CL_REQUIRE_CLASSNAME(module##_requirer,__LINE__); - #else + #elif 0 // gcc-3.0 -fuse-cxa-atexit doesn't have a single per-module destructor // function anymore. Instead, for each object's static constructor it // executes, it pushes the corresponding object's destructor onto a list. @@ -255,9 +255,42 @@ }; \ static _CL_REQUIRE_CLASSNAME(module,__LINE__) \ _CL_REQUIRE_CLASSNAME(module##_requirer,__LINE__); - #endif #define _CL_REQUIRE_CLASSNAME(module,line) __CL_REQUIRE_CLASSNAME(module,line) #define __CL_REQUIRE_CLASSNAME(module,line) cl_module__##module##__##line + #else + #define CL_PROVIDE(module) \ + extern "C" void cl_module__##module##__ctorend (void); \ + CL_GLOBALIZE_JUMP_LABEL(cl_module__##module##__ctorend) \ + CL_GLOBALIZE_CTORDTOR_LABEL( \ + ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ + #module ".cc") \ + static int cl_module__##module##__counter; \ + struct cl_module__##module##__controller { \ + inline cl_module__##module##__controller () \ + { if (cl_module__##module##__counter++) \ + { CL_JUMP_TO(cl_module__##module##__ctorend); } \ + } \ + }; \ + static cl_module__##module##__controller cl_module__##module##__ctordummy; + #define CL_PROVIDE_END(module) \ + struct cl_module__##module##__destroyer { \ + inline cl_module__##module##__destroyer () \ + { CL_OUTPUT_LABEL (ASM_UNDERSCORE_PREFIX "cl_module__" #module "__ctorend"); } \ + }; \ + static cl_module__##module##__destroyer cl_module__##module##__dtordummy; + #define CL_REQUIRE(module) \ + extern "C" void cl_module__##module##__ctor (void) \ + __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ + #module ".cc"); \ + struct _CL_REQUIRE_CLASSNAME(module,__LINE__) { \ + inline _CL_REQUIRE_CLASSNAME(module,__LINE__) () \ + { cl_module__##module##__ctor (); } \ + }; \ + static _CL_REQUIRE_CLASSNAME(module,__LINE__) \ + _CL_REQUIRE_CLASSNAME(module##_requirer,__LINE__); + #define _CL_REQUIRE_CLASSNAME(module,line) __CL_REQUIRE_CLASSNAME(module,line) + #define __CL_REQUIRE_CLASSNAME(module,line) cl_module__##module##__##line +#endif #else #define CL_PROVIDE(module) #define CL_PROVIDE_END(module)
Dear Ralf, Ralf Wildenhues wrote:
Consider this code snippet:
extern "C" void func () {} __asm__("\t.globl " "_GLOBAL__I_" "func"); static struct S { inline S () { } } S;
On x86_64, with `g++-4.2 -fPIC -c a.cc', this results in | 0000000000000032 T _GLOBAL__I_func
with mainline GCC (what will eventually be 4.3 or some other number), it has | 0000000000000032 t _GLOBAL__I_a.cc
(and of course that will be `T' with the appropriate .globl directive).
This affects .libs/cl_DF_globals.o and some of the other globals objects, and causes a link failure of the examples due to the CL_REQUIRE undefined references (global constructor keyed to ...).
The hack below makes things work with mainline, but still needs to be redone properly, with a configure-time check and so on to not regress on g++ <= 4.2. If you like I can take a stab at writing so;
If this becomes necessary for new GCCs I would really appreciate such a patch from you.
I assume the test should make use of $lt_compiler_pic_CXX and the header file provide different defines based on whether -DPIC was given? (I'm not all that experienced with this stuff, so pointers are greatly appreciated.)
I don't know about new GCCs. But if -DPIC matters, then we'll need two defines, yes. We need those symbols, after all. Cheers -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Hello Ralf, On 2007-07-16, you wrote:
Consider this code snippet:
extern "C" void func () {} __asm__("\t.globl " "_GLOBAL__I_" "func"); static struct S { inline S () { } } S;
On x86_64, with `g++-4.2 -fPIC -c a.cc', this results in | 0000000000000032 T _GLOBAL__I_func
with mainline GCC (what will eventually be 4.3 or some other number), it has | 0000000000000032 t _GLOBAL__I_a.cc
(and of course that will be `T' with the appropriate .globl directive).
This affects .libs/cl_DF_globals.o and some of the other globals objects, and causes a link failure of the examples due to the CL_REQUIRE undefined references (global constructor keyed to ...).
The hack below makes things work with mainline, but still needs to be redone properly, with a configure-time check and so on to not regress on g++ <= 4.2. If you like I can take a stab at writing so; I assume the test should make use of $lt_compiler_pic_CXX and the header file provide different defines based on whether -DPIC was given? (I'm not all that experienced with this stuff, so pointers are greatly appreciated.)
Can you write such a patch? I'm a little confused how to do the switch properly. Would it be bad to just combine #ifdef PIC and a test for __GNUC__ and __GNUC_MINOR__ inside modules.h? What is $lt_compiler_pic_CXX? It doesn't seem to exist.
Index: include/cln/modules.h =================================================================== RCS file: /home/cvs/cln/include/cln/modules.h,v retrieving revision 1.19 diff -u -r1.19 modules.h --- include/cln/modules.h 7 May 2006 21:05:24 -0000 1.19 +++ include/cln/modules.h 26 May 2007 16:44:38 -0000 @@ -219,7 +219,7 @@ }; \ static _CL_REQUIRE_CLASSNAME(module,__LINE__) \ _CL_REQUIRE_CLASSNAME(module##_requirer,__LINE__); - #else + #elif 0 // gcc-3.0 -fuse-cxa-atexit doesn't have a single per-module destructor // function anymore. Instead, for each object's static constructor it // executes, it pushes the corresponding object's destructor onto a list. @@ -255,9 +255,42 @@ }; \ static _CL_REQUIRE_CLASSNAME(module,__LINE__) \ _CL_REQUIRE_CLASSNAME(module##_requirer,__LINE__); - #endif #define _CL_REQUIRE_CLASSNAME(module,line) __CL_REQUIRE_CLASSNAME(module,line) #define __CL_REQUIRE_CLASSNAME(module,line) cl_module__##module##__##line + #else + #define CL_PROVIDE(module) \ + extern "C" void cl_module__##module##__ctorend (void); \ + CL_GLOBALIZE_JUMP_LABEL(cl_module__##module##__ctorend) \ + CL_GLOBALIZE_CTORDTOR_LABEL( \ + ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ + #module ".cc") \ + static int cl_module__##module##__counter; \ + struct cl_module__##module##__controller { \ + inline cl_module__##module##__controller () \ + { if (cl_module__##module##__counter++) \ + { CL_JUMP_TO(cl_module__##module##__ctorend); } \ + } \ + }; \ + static cl_module__##module##__controller cl_module__##module##__ctordummy; + #define CL_PROVIDE_END(module) \ + struct cl_module__##module##__destroyer { \ + inline cl_module__##module##__destroyer () \ + { CL_OUTPUT_LABEL (ASM_UNDERSCORE_PREFIX "cl_module__" #module "__ctorend"); } \ + }; \ + static cl_module__##module##__destroyer cl_module__##module##__dtordummy; + #define CL_REQUIRE(module) \ + extern "C" void cl_module__##module##__ctor (void) \ + __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ + #module ".cc"); \ + struct _CL_REQUIRE_CLASSNAME(module,__LINE__) { \ + inline _CL_REQUIRE_CLASSNAME(module,__LINE__) () \ + { cl_module__##module##__ctor (); } \ + }; \ + static _CL_REQUIRE_CLASSNAME(module,__LINE__) \ + _CL_REQUIRE_CLASSNAME(module##_requirer,__LINE__); + #define _CL_REQUIRE_CLASSNAME(module,line) __CL_REQUIRE_CLASSNAME(module,line) + #define __CL_REQUIRE_CLASSNAME(module,line) cl_module__##module##__##line +#endif #else #define CL_PROVIDE(module) #define CL_PROVIDE_END(module)
Cheers -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Hello Richard, Apologies for the long delay, and thanks for the patience. * Richard B. Kreckel wrote on Tue, Dec 04, 2007 at 04:53:37PM CET:
On 2007-07-16, you wrote:
Consider this code snippet:
extern "C" void func () {} __asm__("\t.globl " "_GLOBAL__I_" "func"); static struct S { inline S () { } } S;
On x86_64, with `g++-4.2 -fPIC -c a.cc', this results in | 0000000000000032 T _GLOBAL__I_func
with mainline GCC (what will eventually be 4.3 or some other number), it has | 0000000000000032 t _GLOBAL__I_a.cc
(and of course that will be `T' with the appropriate .globl directive).
This affects .libs/cl_DF_globals.o and some of the other globals objects, and causes a link failure of the examples due to the CL_REQUIRE undefined references (global constructor keyed to ...).
The hack below makes things work with mainline, but still needs to be redone properly, with a configure-time check and so on to not regress on g++ <= 4.2. If you like I can take a stab at writing so; I assume the test should make use of $lt_compiler_pic_CXX and the header file provide different defines based on whether -DPIC was given? (I'm not all that experienced with this stuff, so pointers are greatly appreciated.)
Can you write such a patch? I'm a little confused how to do the switch properly. Would it be bad to just combine #ifdef PIC and a test for __GNUC__ and __GNUC_MINOR__ inside modules.h?
A feature-based test seems nicer to me.
What is $lt_compiler_pic_CXX? It doesn't seem to exist.
Oh sorry, that should've been lt_prog_compiler_pic_CXX, and is set by AC_PROG_LIBTOOL. Here's a proposed patch that seems to do the right thing for me, and otherwise uses the same Autoconf macro style as the other code already in c++-constructors.m4. The macro as of now is fairly CLN-centric in that it hard-codes "cl_module__" and "__firstglobalfun" into the cached value. I tried it with Autoconf 2.59 and HEAD. I will try to build CLN with this, with GCC 4.1.1 and svn HEAD on GNU/Linux x86, but results may take up to a couple of days (so if you're in a hurry you may want to test yourself). Cheers, Ralf 2007-12-16 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> Cater to the fact that g++ 4.3 will use a different naming for the global constructor suffix. * m4/c++-constructors.m4 (CL_GLOBAL_CONSTRUCTORS): Add test for the global constructor suffix, define CL_GLOBAL_CONSTRUCTOR_SUFFIX appropriately. * include/cln/config.h.in: Provide template to be filled in by configure. * include/cln/modules.h (CL_PROVIDE, CL_REQUIRE): Use CL_GLOBAL_CONSTRUCTOR_SUFFIX. Index: include/cln/config.h.in =================================================================== RCS file: /home/cvs/cln/include/cln/config.h.in,v retrieving revision 1.10 diff -u -r1.10 config.h.in --- include/cln/config.h.in 13 Jun 2006 18:31:18 -0000 1.10 +++ include/cln/config.h.in 16 Dec 2007 19:13:38 -0000 @@ -141,6 +141,10 @@ /* Define if a module's global constructor function and global destructor function need to be exported in order to be accessible from other modules. */ #undef CL_NEED_GLOBALIZE_CTORDTOR +/* Define as the suffix of the name of a module's global constructor function */ +#ifndef CL_GLOBAL_CONSTRUCTOR_SUFFIX +#undef CL_GLOBAL_CONSTRUCTOR_SUFFIX +#endif /* CL_CHAR_UNSIGNED */ #ifndef __CHAR_UNSIGNED__ Index: include/cln/modules.h =================================================================== RCS file: /home/cvs/cln/include/cln/modules.h,v retrieving revision 1.20 diff -u -r1.20 modules.h --- include/cln/modules.h 18 Sep 2007 21:56:18 -0000 1.20 +++ include/cln/modules.h 16 Dec 2007 19:13:38 -0000 @@ -231,7 +231,7 @@ CL_GLOBALIZE_JUMP_LABEL(cl_module__##module##__ctorend) \ CL_GLOBALIZE_CTORDTOR_LABEL( \ ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ - "cl_module__" #module "__firstglobalfun") \ + CL_GLOBAL_CONSTRUCTOR_SUFFIX(module)) \ static int cl_module__##module##__counter; \ struct cl_module__##module##__controller { \ inline cl_module__##module##__controller () \ @@ -249,7 +249,7 @@ #define CL_REQUIRE(module) \ extern "C" void cl_module__##module##__ctor (void) \ __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ - "cl_module__" #module "__firstglobalfun"); \ + CL_GLOBAL_CONSTRUCTOR_SUFFIX(module)); \ struct _CL_REQUIRE_CLASSNAME(module,__LINE__) { \ inline _CL_REQUIRE_CLASSNAME(module,__LINE__) () \ { cl_module__##module##__ctor (); } \ Index: m4/c++-constructors.m4 =================================================================== RCS file: /home/cvs/cln/m4/c++-constructors.m4,v retrieving revision 1.1 diff -u -r1.1 c++-constructors.m4 --- m4/c++-constructors.m4 29 Aug 2005 13:18:40 -0000 1.1 +++ m4/c++-constructors.m4 16 Dec 2007 19:13:38 -0000 @@ -95,6 +95,23 @@ if test "$cl_cv_cplusplus_ctorexport" = yes; then AC_DEFINE(CL_NEED_GLOBALIZE_CTORDTOR) fi +AC_CACHE_CHECK([for the global constructor function suffix], +cl_cv_cplusplus_ctorsuffix, [ +cat > conftest.cc << EOF +extern "C" void func () {} +static struct S { + inline S () { } +} S; +EOF +AC_TRY_COMMAND(${CXX-g++} $CXXFLAGS ${lt_prog_compiler_pic_CXX-"-fPIC"} -S conftest.cc) >/dev/null 2>&1 +if grep "${cl_cv_cplusplus_ctorprefix}conftest\.cc" conftest.s >/dev/null; then + cl_cv_cplusplus_ctorsuffix='#module ".cc"' +else + cl_cv_cplusplus_ctorsuffix='"cl_module__" #module "__firstglobalfun"' +fi +rm -f conftest* +]) +AC_DEFINE_UNQUOTED([CL_GLOBAL_CONSTRUCTOR_SUFFIX(module)], [$cl_cv_cplusplus_ctorsuffix]) fi fi ])
* Ralf Wildenhues wrote on Sun, Dec 16, 2007 at 09:12:00PM CET:
I will try to build CLN with this, with GCC 4.1.1 and svn HEAD on GNU/Linux x86,
Tests passed. Cheers, Ralf
2007-12-16 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
Cater to the fact that g++ 4.3 will use a different naming for the global constructor suffix. * m4/c++-constructors.m4 (CL_GLOBAL_CONSTRUCTORS): Add test for the global constructor suffix, define CL_GLOBAL_CONSTRUCTOR_SUFFIX appropriately. * include/cln/config.h.in: Provide template to be filled in by configure. * include/cln/modules.h (CL_PROVIDE, CL_REQUIRE): Use CL_GLOBAL_CONSTRUCTOR_SUFFIX.
Hello Ralf, Ralf Wildenhues wrote:
* Richard B. Kreckel wrote on Tue, Dec 04, 2007 at 04:53:37PM CET:
Consider this code snippet:
extern "C" void func () {} __asm__("\t.globl " "_GLOBAL__I_" "func"); static struct S { inline S () { } } S;
On x86_64, with `g++-4.2 -fPIC -c a.cc', this results in | 0000000000000032 T _GLOBAL__I_func
with mainline GCC (what will eventually be 4.3 or some other number), it has | 0000000000000032 t _GLOBAL__I_a.cc
(and of course that will be `T' with the appropriate .globl directive).
This affects .libs/cl_DF_globals.o and some of the other globals objects, and causes a link failure of the examples due to the CL_REQUIRE undefined references (global constructor keyed to ...).
The hack below makes things work with mainline, but still needs to be redone properly, with a configure-time check and so on to not regress on g++ <= 4.2. If you like I can take a stab at writing so; I assume the test should make use of $lt_compiler_pic_CXX and the header file provide different defines based on whether -DPIC was given? (I'm not all that experienced with this stuff, so pointers are greatly appreciated.) Can you write such a patch? I'm a little confused how to do the switch
On 2007-07-16, you wrote: properly. Would it be bad to just combine #ifdef PIC and a test for __GNUC__ and __GNUC_MINOR__ inside modules.h?
A feature-based test seems nicer to me.
What is $lt_compiler_pic_CXX? It doesn't seem to exist.
Oh sorry, that should've been lt_prog_compiler_pic_CXX, and is set by AC_PROG_LIBTOOL.
Here's a proposed patch that seems to do the right thing for me, and otherwise uses the same Autoconf macro style as the other code already in c++-constructors.m4. The macro as of now is fairly CLN-centric in that it hard-codes "cl_module__" and "__firstglobalfun" into the cached value. I tried it with Autoconf 2.59 and HEAD. I will try to build CLN with this, with GCC 4.1.1 and svn HEAD on GNU/Linux x86, but results may take up to a couple of days (so if you're in a hurry you may want to test yourself).
Cheers, Ralf
2007-12-16 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
Cater to the fact that g++ 4.3 will use a different naming for the global constructor suffix. * m4/c++-constructors.m4 (CL_GLOBAL_CONSTRUCTORS): Add test for the global constructor suffix, define CL_GLOBAL_CONSTRUCTOR_SUFFIX appropriately. * include/cln/config.h.in: Provide template to be filled in by configure. * include/cln/modules.h (CL_PROVIDE, CL_REQUIRE): Use CL_GLOBAL_CONSTRUCTOR_SUFFIX.
Index: include/cln/config.h.in =================================================================== RCS file: /home/cvs/cln/include/cln/config.h.in,v retrieving revision 1.10 diff -u -r1.10 config.h.in --- include/cln/config.h.in 13 Jun 2006 18:31:18 -0000 1.10 +++ include/cln/config.h.in 16 Dec 2007 19:13:38 -0000 @@ -141,6 +141,10 @@ /* Define if a module's global constructor function and global destructor function need to be exported in order to be accessible from other modules. */ #undef CL_NEED_GLOBALIZE_CTORDTOR +/* Define as the suffix of the name of a module's global constructor function */ +#ifndef CL_GLOBAL_CONSTRUCTOR_SUFFIX +#undef CL_GLOBAL_CONSTRUCTOR_SUFFIX +#endif
/* CL_CHAR_UNSIGNED */ #ifndef __CHAR_UNSIGNED__ Index: include/cln/modules.h =================================================================== RCS file: /home/cvs/cln/include/cln/modules.h,v retrieving revision 1.20 diff -u -r1.20 modules.h --- include/cln/modules.h 18 Sep 2007 21:56:18 -0000 1.20 +++ include/cln/modules.h 16 Dec 2007 19:13:38 -0000 @@ -231,7 +231,7 @@ CL_GLOBALIZE_JUMP_LABEL(cl_module__##module##__ctorend) \ CL_GLOBALIZE_CTORDTOR_LABEL( \ ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ - "cl_module__" #module "__firstglobalfun") \ + CL_GLOBAL_CONSTRUCTOR_SUFFIX(module)) \ static int cl_module__##module##__counter; \ struct cl_module__##module##__controller { \ inline cl_module__##module##__controller () \ @@ -249,7 +249,7 @@ #define CL_REQUIRE(module) \ extern "C" void cl_module__##module##__ctor (void) \ __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ - "cl_module__" #module "__firstglobalfun"); \ + CL_GLOBAL_CONSTRUCTOR_SUFFIX(module)); \ struct _CL_REQUIRE_CLASSNAME(module,__LINE__) { \ inline _CL_REQUIRE_CLASSNAME(module,__LINE__) () \ { cl_module__##module##__ctor (); } \ Index: m4/c++-constructors.m4 =================================================================== RCS file: /home/cvs/cln/m4/c++-constructors.m4,v retrieving revision 1.1 diff -u -r1.1 c++-constructors.m4 --- m4/c++-constructors.m4 29 Aug 2005 13:18:40 -0000 1.1 +++ m4/c++-constructors.m4 16 Dec 2007 19:13:38 -0000 @@ -95,6 +95,23 @@ if test "$cl_cv_cplusplus_ctorexport" = yes; then AC_DEFINE(CL_NEED_GLOBALIZE_CTORDTOR) fi +AC_CACHE_CHECK([for the global constructor function suffix], +cl_cv_cplusplus_ctorsuffix, [ +cat > conftest.cc << EOF +extern "C" void func () {} +static struct S { + inline S () { } +} S; +EOF +AC_TRY_COMMAND(${CXX-g++} $CXXFLAGS ${lt_prog_compiler_pic_CXX-"-fPIC"} -S conftest.cc) >/dev/null 2>&1 +if grep "${cl_cv_cplusplus_ctorprefix}conftest\.cc" conftest.s >/dev/null; then + cl_cv_cplusplus_ctorsuffix='#module ".cc"' +else + cl_cv_cplusplus_ctorsuffix='"cl_module__" #module "__firstglobalfun"' +fi +rm -f conftest* +]) +AC_DEFINE_UNQUOTED([CL_GLOBAL_CONSTRUCTOR_SUFFIX(module)], [$cl_cv_cplusplus_ctorsuffix]) fi fi ])
I don't see how your patch can work. With -fPIC, we'll have to write _GLOBAL__I_foo.cc, alright, but without -fPIC, we'll have to stick to _GLOBAL__I_func. Your patch defines the macro CL_GLOBAL_CONSTRUCTOR_SUFFIX(module) but does not distinguish between these two cases. So, if you ./configure --enable-shared --enable-static, as is the default, either the shared or the static library will not work. Somehow, we must distinguish between the two cases, and I don't see how it can be done without some #if defined(PIC) sections. Can you try ./configure --disable-shared && make check, please? Please do remote-beat me if it works and I should have tried. :-/ Cheers -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Hello Richard, * Richard B. Kreckel wrote on Mon, Dec 17, 2007 at 09:09:21AM CET:
I don't see how your patch can work. With -fPIC, we'll have to write _GLOBAL__I_foo.cc, alright, but without -fPIC, we'll have to stick to _GLOBAL__I_func. Your patch defines the macro CL_GLOBAL_CONSTRUCTOR_SUFFIX(module) but does not distinguish between these two cases. So, if you ./configure --enable-shared --enable-static, as is the default, either the shared or the static library will not work. Somehow, we must distinguish between the two cases, and I don't see how it can be done without some #if defined(PIC) sections.
You are of course right on the spot on this one. I did not think of the non-PIC case. Guess it's back to the drawing board.
Can you try ./configure --disable-shared && make check, please?
Will do, and redo the patch. Cheers, Ralf
Hello CLN list, and a Happy New Year,
* Richard B. Kreckel wrote on Mon, Dec 17, 2007 at 09:09:21AM CET:
I don't see how your patch can work. With -fPIC, we'll have to write _GLOBAL__I_foo.cc, alright, but without -fPIC, we'll have to stick to _GLOBAL__I_func. Your patch defines the macro CL_GLOBAL_CONSTRUCTOR_SUFFIX(module) but does not distinguish between these two cases. So, if you ./configure --enable-shared --enable-static, as is the default, either the shared or the static library will not work. Somehow, we must distinguish between the two cases, and I don't see how it can be done without some #if defined(PIC) sections.
Hmm. I don't know how to fix this well: module.h gets installed and used by third-party software (users of CLN). It needs to provide different settings for whether the user will later use the static or the shared version of libcln. This is ugly, because it's generally not known at compile time which library will be used. Unless libcln limits itself to installing just one version of the library, I don't see how this can be solved without requiring that the user of libcln choose at compile time (by a suitable define) whether to use the static or shared library (which is a different question whether the user is currently building PIC or non-PIC code). Cheers, Ralf
Hi Ralf, Ralf Wildenhues wrote:
Hmm. I don't know how to fix this well: module.h gets installed and used by third-party software (users of CLN). It needs to provide different settings for whether the user will later use the static or the shared version of libcln. This is ugly, because it's generally not known at compile time which library will be used.
Unless libcln limits itself to installing just one version of the library, I don't see how this can be solved without requiring that the user of libcln choose at compile time (by a suitable define) whether to use the static or shared library (which is a different question whether the user is currently building PIC or non-PIC code).
Correct. I haven't seen this problem when I originally suggested to introduced some #ifdef PIC in cln/modules.h. I'm beginning to think that it should be possible to solve this in the old software engineering way: introduce another layer of indirection in order to present a unique name for shared and static library to the compiling application and only distinguish between PIC and non-PIC inside the library proper. I'll give it a try and report on it later this day. Cheers -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
I wrote:
I'm beginning to think that it should be possible to solve this in the old software engineering way: introduce another layer of indirection in order to present a unique name for shared and static library to the compiling application and only distinguish between PIC and non-PIC inside the library proper. I'll give it a try and report on it later this day.
So, CL_REQUIRE can't call the global ctors directly, because it doesn't know what the symbol name is. Only CL_PROVIDE and CL_PROVIDE_END do know that. But, it doesn't appear to be possible to introduce another layer of indirection in CL_PROVIDE like the attached patch tries to. It leads to an infinite loop in the global ctors. Right now, I've run out of ideas. -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/> Index: include/cln/config.h.in =================================================================== RCS file: /home/cvs/cln/include/cln/config.h.in,v retrieving revision 1.10 diff -u -r1.10 config.h.in --- include/cln/config.h.in 13 Jun 2006 18:31:18 -0000 1.10 +++ include/cln/config.h.in 4 Jan 2008 22:01:53 -0000 @@ -141,6 +141,13 @@ /* Define if a module's global constructor function and global destructor function need to be exported in order to be accessible from other modules. */ #undef CL_NEED_GLOBALIZE_CTORDTOR +/* Define as the suffix of the name of a module's global constructor function */ +#ifndef CL_GLOBAL_CONSTRUCTOR_SUFFIX_PIC +#undef CL_GLOBAL_CONSTRUCTOR_SUFFIX_PIC +#endif +#ifndef CL_GLOBAL_CONSTRUCTOR_SUFFIX_NOPIC +#undef CL_GLOBAL_CONSTRUCTOR_SUFFIX_NOPIC +#endif /* CL_CHAR_UNSIGNED */ #ifndef __CHAR_UNSIGNED__ Index: include/cln/modules.h =================================================================== RCS file: /home/cvs/cln/include/cln/modules.h,v retrieving revision 1.20 diff -u -r1.20 modules.h --- include/cln/modules.h 18 Sep 2007 21:56:18 -0000 1.20 +++ include/cln/modules.h 4 Jan 2008 22:01:54 -0000 @@ -3,6 +3,9 @@ #ifndef _CL_MODULES_H #define _CL_MODULES_H +// global constructor/destructor naming. +#include "cln/config.h" + // The order of initialization of different compilation units is not // specified in C++. AIX 4 has a linker which apparently does order // the modules according to dependencies, so that low-level modules @@ -56,6 +59,12 @@ // OK, stop reading here, because it's getting obscene. +#if defined(PIC) + #define CL_GLOBAL_CONSTRUCTOR_SUFFIX CL_GLOBAL_CONSTRUCTOR_SUFFIX_PIC +#else + #define CL_GLOBAL_CONSTRUCTOR_SUFFIX CL_GLOBAL_CONSTRUCTOR_SUFFIX_NOPIC +#endif + #if defined(__GNUC__) && defined(__OPTIMIZE__) && !(defined(__hppa__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 8)) && !defined(NO_PROVIDE_REQUIRE) #ifdef ASM_UNDERSCORE #define ASM_UNDERSCORE_PREFIX "_" @@ -227,11 +236,20 @@ // Thus we need to hack the constructors only. #define CL_PROVIDE(module) \ extern "C" void cl_module__##module##__firstglobalfun () {} \ + extern "C" void cl_module__##module##__callctor() \ + __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ + CL_GLOBAL_CONSTRUCTOR_SUFFIX(module)); \ + static struct cl_module__##module##__ctordelegator { \ + inline cl_module__##module##__ctordelegator () { \ + CL_GLOBALIZE_LABEL("cl_module__" #module "__ctordelegator") \ + CL_OUTPUT_LABEL("cl_module__" #module "__ctordelegator"); \ + cl_module__##module##__callctor(); } \ + } cl_module__##module##__ctordelegatordummy; \ extern "C" void cl_module__##module##__ctorend (void); \ CL_GLOBALIZE_JUMP_LABEL(cl_module__##module##__ctorend) \ CL_GLOBALIZE_CTORDTOR_LABEL( \ ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ - "cl_module__" #module "__firstglobalfun") \ + CL_GLOBAL_CONSTRUCTOR_SUFFIX(module)) \ static int cl_module__##module##__counter; \ struct cl_module__##module##__controller { \ inline cl_module__##module##__controller () \ @@ -248,8 +266,7 @@ static cl_module__##module##__destroyer cl_module__##module##__dtordummy; #define CL_REQUIRE(module) \ extern "C" void cl_module__##module##__ctor (void) \ - __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ - "cl_module__" #module "__firstglobalfun"); \ + __asm__ ("cl_module__" #module "__ctordelegator"); \ struct _CL_REQUIRE_CLASSNAME(module,__LINE__) { \ inline _CL_REQUIRE_CLASSNAME(module,__LINE__) () \ { cl_module__##module##__ctor (); } \ Index: m4/c++-constructors.m4 =================================================================== RCS file: /home/cvs/cln/m4/c++-constructors.m4,v retrieving revision 1.1 diff -u -r1.1 c++-constructors.m4 --- m4/c++-constructors.m4 29 Aug 2005 13:18:40 -0000 1.1 +++ m4/c++-constructors.m4 4 Jan 2008 22:01:54 -0000 @@ -95,6 +95,40 @@ if test "$cl_cv_cplusplus_ctorexport" = yes; then AC_DEFINE(CL_NEED_GLOBALIZE_CTORDTOR) fi +AC_CACHE_CHECK([for the global constructor function suffix in shared objects], +cl_cv_cplusplus_ctorsuffix_pic, [ +cat > conftest.cc << EOF +extern "C" void func () {} +static struct S { + inline S () {} +} S; +EOF +AC_TRY_COMMAND(${CXX-g++} $CXXFLAGS ${lt_prog_compiler_pic_CXX-"-fPIC"} -S conftest.cc) >/dev/null 2>&1 +if grep "${cl_cv_cplusplus_ctorprefix}conftest\.cc" conftest.s >/dev/null; then + cl_cv_cplusplus_ctorsuffix_pic='#module ".cc"' +else + cl_cv_cplusplus_ctorsuffix_pic='"cl_module__" #module "__firstglobalfun"' +fi +rm -f conftest* +]) +AC_DEFINE_UNQUOTED([CL_GLOBAL_CONSTRUCTOR_SUFFIX_PIC(module)], [$cl_cv_cplusplus_ctorsuffix_pic]) +AC_CACHE_CHECK([for the global constructor function suffix in static objects], +cl_cv_cplusplus_ctorsuffix_nopic, [ +cat > conftest.cc << EOF +extern "C" void func () {} +static struct S { + inline S () {} +} S; +EOF +AC_TRY_COMMAND(${CXX-g++} $CXXFLAGS -S conftest.cc) >/dev/null 2>&1 +if grep "${cl_cv_cplusplus_ctorprefix}conftest\.cc" conftest.s >/dev/null; then + cl_cv_cplusplus_ctorsuffix_nopic='#module ".cc"' +else + cl_cv_cplusplus_ctorsuffix_nopic='"cl_module__" #module "__firstglobalfun"' +fi +rm -f conftest* +]) +AC_DEFINE_UNQUOTED([CL_GLOBAL_CONSTRUCTOR_SUFFIX_NOPIC(module)], [$cl_cv_cplusplus_ctorsuffix_nopic]) fi fi ])
I wrote:
So, CL_REQUIRE can't call the global ctors directly, because it doesn't know what the symbol name is. Only CL_PROVIDE and CL_PROVIDE_END do know that. But, it doesn't appear to be possible to introduce another layer of indirection in CL_PROVIDE like the attached patch tries to. It leads to an infinite loop in the global ctors. Right now, I've run out of ideas.
Well, it turns out that the infinite recursion was due to the braindead way I implemented that other layer of indirection. A plain C function should do the trick. The attached patch seems to work over here using prerelease GCC 4.3.0-20071130. I would appreciate it if people give it a try and report how it worx 4 them. Cheers -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/> Index: ChangeLog =================================================================== RCS file: /home/cvs/cln/ChangeLog,v retrieving revision 1.194 diff -u -r1.194 ChangeLog --- ChangeLog 18 Dec 2007 23:01:19 -0000 1.194 +++ ChangeLog 6 Jan 2008 01:53:04 -0000 @@ -1,3 +1,16 @@ +2008-01-06 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + Richard B. Kreckel <kreckel@ginac.de> + + Cater to the fact that g++ 4.3 will use a different naming for + the global constructor suffix in shared and static objects. + * m4/c++-constructors.m4 (CL_GLOBAL_CONSTRUCTORS): Add test for + the global constructor suffix, define CL_GLOBAL_CONSTRUCTOR_SUFFIX_PIC + and CL_GLOBAL_CONSTRUCTOR_SUFFIX_NOPIC appropriately. + * include/cln/config.h.in: Provide templates to be filled in by + configure. + * include/cln/modules.h (CL_PROVIDE, CL_REQUIRE): Use + CL_GLOBAL_CONSTRUCTOR_SUFFIX_PIC, CL_GLOBAL_CONSTRUCTOR_SUFFIX_NOPIC. + 2007-12-19 Richard B. Kreckel <kreckel@ginac.de> * m4/general.m4 (CL_CANONICAL_HOST_CPU): Force host_cpu=rs6000 for Index: m4/c++-constructors.m4 =================================================================== RCS file: /home/cvs/cln/m4/c++-constructors.m4,v retrieving revision 1.1 diff -u -r1.1 c++-constructors.m4 --- m4/c++-constructors.m4 29 Aug 2005 13:18:40 -0000 1.1 +++ m4/c++-constructors.m4 6 Jan 2008 01:53:04 -0000 @@ -95,6 +95,40 @@ if test "$cl_cv_cplusplus_ctorexport" = yes; then AC_DEFINE(CL_NEED_GLOBALIZE_CTORDTOR) fi +AC_CACHE_CHECK([for the global constructor function suffix in shared objects], +cl_cv_cplusplus_ctorsuffix_pic, [ +cat > conftest.cc << EOF +extern "C" void func () {} +static struct S { + inline S () {} +} S; +EOF +AC_TRY_COMMAND(${CXX-g++} $CXXFLAGS ${lt_prog_compiler_pic_CXX-"-fPIC"} -S conftest.cc) >/dev/null 2>&1 +if grep "${cl_cv_cplusplus_ctorprefix}conftest\.cc" conftest.s >/dev/null; then + cl_cv_cplusplus_ctorsuffix_pic='#module ".cc"' +else + cl_cv_cplusplus_ctorsuffix_pic='"cl_module__" #module "__firstglobalfun"' +fi +rm -f conftest* +]) +AC_DEFINE_UNQUOTED([CL_GLOBAL_CONSTRUCTOR_SUFFIX_PIC(module)], [$cl_cv_cplusplus_ctorsuffix_pic]) +AC_CACHE_CHECK([for the global constructor function suffix in static objects], +cl_cv_cplusplus_ctorsuffix_nopic, [ +cat > conftest.cc << EOF +extern "C" void func () {} +static struct S { + inline S () {} +} S; +EOF +AC_TRY_COMMAND(${CXX-g++} $CXXFLAGS -S conftest.cc) >/dev/null 2>&1 +if grep "${cl_cv_cplusplus_ctorprefix}conftest\.cc" conftest.s >/dev/null; then + cl_cv_cplusplus_ctorsuffix_nopic='#module ".cc"' +else + cl_cv_cplusplus_ctorsuffix_nopic='"cl_module__" #module "__firstglobalfun"' +fi +rm -f conftest* +]) +AC_DEFINE_UNQUOTED([CL_GLOBAL_CONSTRUCTOR_SUFFIX_NOPIC(module)], [$cl_cv_cplusplus_ctorsuffix_nopic]) fi fi ]) Index: include/cln/config.h.in =================================================================== RCS file: /home/cvs/cln/include/cln/config.h.in,v retrieving revision 1.10 diff -u -r1.10 config.h.in --- include/cln/config.h.in 13 Jun 2006 18:31:18 -0000 1.10 +++ include/cln/config.h.in 6 Jan 2008 01:53:04 -0000 @@ -141,6 +141,13 @@ /* Define if a module's global constructor function and global destructor function need to be exported in order to be accessible from other modules. */ #undef CL_NEED_GLOBALIZE_CTORDTOR +/* Define as the suffix of the name of a module's global constructor function */ +#ifndef CL_GLOBAL_CONSTRUCTOR_SUFFIX_PIC +#undef CL_GLOBAL_CONSTRUCTOR_SUFFIX_PIC +#endif +#ifndef CL_GLOBAL_CONSTRUCTOR_SUFFIX_NOPIC +#undef CL_GLOBAL_CONSTRUCTOR_SUFFIX_NOPIC +#endif /* CL_CHAR_UNSIGNED */ #ifndef __CHAR_UNSIGNED__ Index: include/cln/modules.h =================================================================== RCS file: /home/cvs/cln/include/cln/modules.h,v retrieving revision 1.20 diff -u -r1.20 modules.h --- include/cln/modules.h 18 Sep 2007 21:56:18 -0000 1.20 +++ include/cln/modules.h 6 Jan 2008 01:53:04 -0000 @@ -3,6 +3,9 @@ #ifndef _CL_MODULES_H #define _CL_MODULES_H +// global constructor/destructor naming. +#include "cln/config.h" + // The order of initialization of different compilation units is not // specified in C++. AIX 4 has a linker which apparently does order // the modules according to dependencies, so that low-level modules @@ -56,6 +59,12 @@ // OK, stop reading here, because it's getting obscene. +#if defined(PIC) + #define CL_GLOBAL_CONSTRUCTOR_SUFFIX CL_GLOBAL_CONSTRUCTOR_SUFFIX_PIC +#else + #define CL_GLOBAL_CONSTRUCTOR_SUFFIX CL_GLOBAL_CONSTRUCTOR_SUFFIX_NOPIC +#endif + #if defined(__GNUC__) && defined(__OPTIMIZE__) && !(defined(__hppa__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 8)) && !defined(NO_PROVIDE_REQUIRE) #ifdef ASM_UNDERSCORE #define ASM_UNDERSCORE_PREFIX "_" @@ -227,11 +236,15 @@ // Thus we need to hack the constructors only. #define CL_PROVIDE(module) \ extern "C" void cl_module__##module##__firstglobalfun () {} \ + extern "C" void cl_module__##module##__docallctors() \ + __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ + CL_GLOBAL_CONSTRUCTOR_SUFFIX(module)); \ + extern "C" void cl_module__##module##__globalctors () \ + { cl_module__##module##__docallctors(); } \ extern "C" void cl_module__##module##__ctorend (void); \ - CL_GLOBALIZE_JUMP_LABEL(cl_module__##module##__ctorend) \ CL_GLOBALIZE_CTORDTOR_LABEL( \ ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ - "cl_module__" #module "__firstglobalfun") \ + CL_GLOBAL_CONSTRUCTOR_SUFFIX(module)) \ static int cl_module__##module##__counter; \ struct cl_module__##module##__controller { \ inline cl_module__##module##__controller () \ @@ -248,8 +261,7 @@ static cl_module__##module##__destroyer cl_module__##module##__dtordummy; #define CL_REQUIRE(module) \ extern "C" void cl_module__##module##__ctor (void) \ - __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ - "cl_module__" #module "__firstglobalfun"); \ + __asm__ ("cl_module__" #module "__globalctors"); \ struct _CL_REQUIRE_CLASSNAME(module,__LINE__) { \ inline _CL_REQUIRE_CLASSNAME(module,__LINE__) () \ { cl_module__##module##__ctor (); } \
Hello Richard, * Richard B. Kreckel wrote on Sun, Jan 06, 2008 at 03:08:15AM CET:
I wrote:
So, CL_REQUIRE can't call the global ctors directly, because it doesn't know what the symbol name is. Only CL_PROVIDE and CL_PROVIDE_END do know that. But, it doesn't appear to be possible to introduce another layer of indirection in CL_PROVIDE like the attached patch tries to. It leads to an infinite loop in the global ctors. Right now, I've run out of ideas.
Well, it turns out that the infinite recursion was due to the braindead way I implemented that other layer of indirection. A plain C function should do the trick.
The attached patch seems to work over here using prerelease GCC 4.3.0-20071130. I would appreciate it if people give it a try and report how it worx 4 them.
That seems to work fine. Thanks! Cheers, Ralf
Hello Richard, * Richard B. Kreckel wrote on Sun, Jan 06, 2008 at 03:08:15AM CET:
+2008-01-06 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + Richard B. Kreckel <kreckel@ginac.de> + + Cater to the fact that g++ 4.3 will use a different naming for + the global constructor suffix in shared and static objects. + * m4/c++-constructors.m4 (CL_GLOBAL_CONSTRUCTORS): Add test for + the global constructor suffix, define CL_GLOBAL_CONSTRUCTOR_SUFFIX_PIC + and CL_GLOBAL_CONSTRUCTOR_SUFFIX_NOPIC appropriately. + * include/cln/config.h.in: Provide templates to be filled in by + configure. + * include/cln/modules.h (CL_PROVIDE, CL_REQUIRE): Use + CL_GLOBAL_CONSTRUCTOR_SUFFIX_PIC, CL_GLOBAL_CONSTRUCTOR_SUFFIX_NOPIC.
Isn't this an API change of the library that needs a version bump? Cheers, Ralf
Hi Ralf, Ralf Wildenhues wrote:
* Richard B. Kreckel wrote on Sun, Jan 06, 2008 at 03:08:15AM CET:
+2008-01-06 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + Richard B. Kreckel <kreckel@ginac.de> + + Cater to the fact that g++ 4.3 will use a different naming for + the global constructor suffix in shared and static objects. + * m4/c++-constructors.m4 (CL_GLOBAL_CONSTRUCTORS): Add test for + the global constructor suffix, define CL_GLOBAL_CONSTRUCTOR_SUFFIX_PIC + and CL_GLOBAL_CONSTRUCTOR_SUFFIX_NOPIC appropriately. + * include/cln/config.h.in: Provide templates to be filled in by + configure. + * include/cln/modules.h (CL_PROVIDE, CL_REQUIRE): Use + CL_GLOBAL_CONSTRUCTOR_SUFFIX_PIC, CL_GLOBAL_CONSTRUCTOR_SUFFIX_NOPIC.
Isn't this an API change of the library that needs a version bump?
Sure it is. CLN 1.2.0 will have soname libcln.so.5, due to this and a few other changes. Cheers -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
On Mon, Dec 17, 2007 at 09:09:21AM +0100, Richard B. Kreckel wrote:
I don't see how your patch can work. With -fPIC, we'll have to write _GLOBAL__I_foo.cc, alright, but without -fPIC, we'll have to stick to _GLOBAL__I_func.
That makes PIC and non-PIC versions of the library binary incompatible, doesn't it? Best regards, Alexei -- All science is either physics or stamp collecting.
Alexei Sheplyakov wrote:
On Mon, Dec 17, 2007 at 09:09:21AM +0100, Richard B. Kreckel wrote:
I don't see how your patch can work. With -fPIC, we'll have to write _GLOBAL__I_foo.cc, alright, but without -fPIC, we'll have to stick to _GLOBAL__I_func.
That makes PIC and non-PIC versions of the library binary incompatible, doesn't it?
Correct. Which is exactly why I tried to re-establish binary compatibility by calling the ctors indirectly only, through a name that is the same in the shared and the static library. Thus the global ctor's real name would not be of interest for the library user any more. -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
participants (3)
-
Alexei Sheplyakov
-
Ralf Wildenhues
-
Richard B. Kreckel