Vague linkage and RTTI (was LINK_WITH_STANDARD_LIBRARIES = NO)
Vague linkage and RTTI (was LINK_WITH_STANDARD_LIBRARIES = NO)
- Subject: Vague linkage and RTTI (was LINK_WITH_STANDARD_LIBRARIES = NO)
- From: Steve Baxter <email@hidden>
- Date: Tue, 31 Jan 2006 13:54:37 +0000
I'm still battling with this, and trying to understand what the
dynamic linker does.
In reading the ABI documentation on vague linkage, it looks like the
dynamic linker should coalesce symbols from different bundles as they
are loaded. This means that the one-definition-rule should then hold
true for the application as a whole:
http://gcc.gnu.org/faq.html#dso
I now export all the symbols from all my plugins, and type_info
passed between plugins mostly works - the problem is it doesn't
always work. Does anyone know why?
Here is the exact scheme we have:
(a) An executable - this links to a shared framework (b). The
executable is very small, it's really just a stub to the framework.
(b) A shared framework.
(c) Plugins - these are loaded by the shared framework using
CFBundle. The plugins link to the shared framework, but cannot link
to each other. They can however pass data to each other through
messaging APIs in the shared framework.
Within this scheme we have a messaging API. Messages are all
subclasses of XMessage and are differentiated by RTTI. Messages sent
by the framework (b) to plugins (c) work fine, as do messages sent
within a plugin. The problem arises when one plugin broadcasts a
message to other plugins.
The messages are generally defined completely inline a bit like this:
class XMyMessage : public XMessage
{
XMyMessage() {}
Data someSortOfPayload;
}
Now, lets say that plugin A broadcasts a message:
SpeakMessage( new XMyMessage() );
This message is passed through our messaging system and is picked up
by plugin B:
void B::HandleMessage( const XMessage& inMsg )
{
if( typeid( inMsg ) == typeid( XMyMessage ) )
{
// This is the message we want - do something
}
}
The problem is that both plugins A and B included XMyMessage as an
inline header. They each have their own type_info for that class.
In Codewarrior and VC++, type_info is compared by name and so this
always works. In GCC, type_info is compared by address - though
these types are the same, the type_info objects have different
addresses and the comparison fails.
Looking at the ABI documentation, I was expecting the dynamic linker
to fix this up. It would see that plugin A defines type_info for
XMyMessage and that plugin B defines type_info for XMyMessage and it
should then coalesce these together dynamically so that
XMyMessage::type_info is defined only once.
Does anyone know why this sometimes works and sometimes doesn't? All
my plugins have the same compile and link settings (I use .xcconfig
files). Here is nm output for two different plugins that should
share the same type_info for a message XDetectFrameGrabbersMessage,
but do not:
From A:
000069fc (__TEXT,__const_coal) weak external
__ZTS27XDetectFrameGrabbersMessage
From B:
00057064 (__TEXT,__const_coal) weak external
__ZTS27XDetectFrameGrabbersMessage
Should I expect the dynamic linker to resolve these properly when the
two bundles are loaded?
Cheers,
Steve.
On 27 Jan 2006, at 18:06, Steve Baxter wrote:
Hi,
We have finally come up against a wall in moving our application
from CW to Xcode. The problem is that GCC's implementation of RTTI
considers the same class defined in two different DSOs to be two
different classes. This unfortunately breaks a lot of our code
(please no discussions about the wrongs and rights of having the
same class in two different DSOs, it happens unavoidably with
inline classes and it would be way too much work for us to change
this now).
The solution to this is I think to compile libsupc++ with
__GXX_MERGED_TYPEINFO_NAMES=0. This reverts GCC back to the old
(reliable) behaviour where type_info objects are compared by name()
rather than by pointer (this is the behaviour in both VC++ and
CodeWarrior as well). So, what I want to do is to link
(statically) against my own version of libsupc++. I suspect I
will also need to link my own version of libstdc++ as well. I will
link these files statically into my shared framework - this way all
my plugins will share the right RTTI information.
So:
- I can tell Xcode not to automatically link with standard
libraries using LINK_WITH_STANDARD_LIBRARIES = NO. The question
is, what are these standard libraries? Can anyone give me a list?
A search in Google and the docs for LINK_WITH_STANDARD_LIBRARIES
elicits nothing at all! I need to link to my version of libstdc+
+.a, but standard libs for everything else.
- Anyone got any pointers for compiling libstdc++ and libsupc++?
I've downloaded the darwin source and tried to make the libs, but I
get some errors from make:
steve-baxters-power-mac-g5:/Volumes/Stuff/Users/stevebaxter/Desktop/
gcc-5026.1/libstdc++-v3 stevebaxter$ make
make "AR_FLAGS=" "CC_FOR_BUILD=" "CC_FOR_TARGET=" "CFLAGS=-g -O2"
"CXXFLAGS=" "CFLAGS_FOR_BUILD=" "CFLAGS_FOR_TARGET=" "INSTALL=/usr/
bin/install -c" "INSTALL_DATA=/usr/bin/install -c -m 644"
"INSTALL_PROGRAM=/usr/bin/install -c" "INSTALL_SCRIPT=/usr/bin/
install -c" "LDFLAGS=" "LIBCFLAGS=" "LIBCFLAGS_FOR_TARGET="
"MAKE=make" "MAKEINFO=/bin/sh /Volumes/Stuff/Users/stevebaxter/
Desktop/gcc-5026.1/missing --run makeinfo " "PICFLAG="
"PICFLAG_FOR_TARGET=" "SHELL=/bin/sh" "RUNTESTFLAGS=" "exec_prefix=/
usr/local" "infodir=/usr/local/info" "libdir=/usr/local/lib"
"includedir=/usr/local/include" "prefix=/usr/local" "tooldir="
"gxx_include_dir=/usr/local/include/c++/4.0.1" "AR=ar" "AS=as"
"LD=ld" "RANLIB=ranlib" "NM=" "NM_FOR_BUILD=" "NM_FOR_TARGET="
"DESTDIR=" "WERROR=" all-recursive
Making all in include
make[2]: Nothing to be done for `all'.
Making all in libsupc++
make[2]: Nothing to be done for `all'.
Making all in libmath
make[2]: Nothing to be done for `all'.
Making all in src
/bin/sh ../libtool --tag CXX --mode=link g++ -Wl,-single_module -
fno-implicit-templates -Wall -Wextra -Wwrite-strings -Wcast-qual -
fdiagnostics-show-location=once -ffunction-sections -fdata-
sections -DAPPLE_KEYMGR -o libstdc++.la -rpath /usr/local/lib -
version-info 6:4:0 -lm bitmap_allocator.lo pool_allocator.lo
mt_allocator.lo codecvt.lo complex_io.lo ctype.lo debug.lo
debug_list.lo functexcept.lo globals_locale.lo globals_io.lo ios.lo
ios_failure.lo ios_init.lo ios_locale.lo limits.lo list.lo
locale.lo locale_init.lo locale_facets.lo localename.lo
stdexcept.lo strstream.lo tree.lo allocator-inst.lo concept-inst.lo
fstream-inst.lo ext-inst.lo io-inst.lo istream-inst.lo istream.lo
locale-inst.lo locale-misc-inst.lo misc-inst.lo ostream-inst.lo
sstream-inst.lo streambuf-inst.lo streambuf.lo string-inst.lo
valarray-inst.lo wlocale-inst.lo wstring-inst.lo atomicity.lo
codecvt_members.lo collate_members.lo ctype_members.lo
messages_members.lo monetary_members.lo numeric_members.lo
time_members.lo basic_file.lo c++locale.lo ../libmath/libmath.la ../
libsupc++/libsupc++convenience.la -lm
rm -fr .libs/libstdc++.lax
rm -fr .libs/libstdc++.lax
mkdir .libs/libstdc++.lax
rm -fr .libs/libstdc++.lax/libmath.a
mkdir .libs/libstdc++.lax/libmath.a
(cd .libs/libstdc++.lax/libmath.a && ar x /Volumes/Stuff/Users/
stevebaxter/Desktop/gcc-5026.1/libstdc++-v3/src/../libmath/.libs/
libmath.a)
rm -fr .libs/libstdc++.lax/libsupc++convenience.a
mkdir .libs/libstdc++.lax/libsupc++convenience.a
(cd .libs/libstdc++.lax/libsupc++convenience.a && ar x /Volumes/
Stuff/Users/stevebaxter/Desktop/gcc-5026.1/libstdc++-v3/src/../
libsupc++/.libs/libsupc++convenience.a)
-dynamiclib -flat_namespace -undefined suppress -o .libs/libstdc++.
6.0.4.dylib .libs/bitmap_allocator.o .libs/pool_allocator.o .libs/
mt_allocator.o .libs/codecvt.o .libs/complex_io.o .libs/
ctype.o .libs/debug.o .libs/debug_list.o .libs/functexcept.o .libs/
globals_locale.o .libs/globals_io.o .libs/ios.o .libs/
ios_failure.o .libs/ios_init.o .libs/ios_locale.o .libs/
limits.o .libs/list.o .libs/locale.o .libs/locale_init.o .libs/
locale_facets.o .libs/localename.o .libs/stdexcept.o .libs/
strstream.o .libs/tree.o .libs/allocator-inst.o .libs/concept-
inst.o .libs/fstream-inst.o .libs/ext-inst.o .libs/io-inst.o .libs/
istream-inst.o .libs/istream.o .libs/locale-inst.o .libs/locale-
misc-inst.o .libs/misc-inst.o .libs/ostream-inst.o .libs/sstream-
inst.o .libs/streambuf-inst.o .libs/streambuf.o .libs/string-
inst.o .libs/valarray-inst.o .libs/wlocale-inst.o .libs/wstring-
inst.o .libs/atomicity.o .libs/codecvt_members.o .libs/
collate_members.o .libs/ctype_members.o .libs/
messages_members.o .libs/monetary_members.o .libs/
numeric_members.o .libs/time_members.o .libs/basic_file.o .libs/c+
+locale.o .libs/libstdc++.lax/libmath.a/stubs.o .libs/libstdc+
+.lax/libsupc++convenience.a/cp-demangle.o .libs/libstdc++.lax/
libsupc++convenience.a/del_op.o .libs/libstdc++.lax/libsupc+
+convenience.a/del_opnt.o .libs/libstdc++.lax/libsupc+
+convenience.a/del_opv.o .libs/libstdc++.lax/libsupc++convenience.a/
del_opvnt.o .libs/libstdc++.lax/libsupc++convenience.a/
eh_alloc.o .libs/libstdc++.lax/libsupc++convenience.a/
eh_aux_runtime.o .libs/libstdc++.lax/libsupc++convenience.a/
eh_catch.o .libs/libstdc++.lax/libsupc++convenience.a/
eh_exception.o .libs/libstdc++.lax/libsupc++convenience.a/
eh_globals.o .libs/libstdc++.lax/libsupc++convenience.a/
eh_personality.o .libs/libstdc++.lax/libsupc++convenience.a/
eh_term_handler.o .libs/libstdc++.lax/libsupc++convenience.a/
eh_terminate.o .libs/libstdc++.lax/libsupc++convenience.a/
eh_throw.o .libs/libstdc++.lax/libsupc++convenience.a/
eh_type.o .libs/libstdc++.lax/libsupc++convenience.a/
eh_unex_handler.o .libs/libstdc++.lax/libsupc++convenience.a/
guard.o .libs/libstdc++.lax/libsupc++convenience.a/
new_handler.o .libs/libstdc++.lax/libsupc++convenience.a/
new_op.o .libs/libstdc++.lax/libsupc++convenience.a/
new_opnt.o .libs/libstdc++.lax/libsupc++convenience.a/
new_opv.o .libs/libstdc++.lax/libsupc++convenience.a/
new_opvnt.o .libs/libstdc++.lax/libsupc++convenience.a/pure.o .libs/
libstdc++.lax/libsupc++convenience.a/tinfo.o .libs/libstdc++.lax/
libsupc++convenience.a/tinfo2.o .libs/libstdc++.lax/libsupc+
+convenience.a/vec.o .libs/libstdc++.lax/libsupc++convenience.a/
vterminate.o -lm ../libmath/.libs/libmath.a -lm ../libsupc+
+/.libs/libsupc++convenience.a -lm -lm -lc -Wl,-single_module -
install_name /usr/local/lib/libstdc++.6.dylib -
compatibility_version 7 -current_version 7.4
../libtool: line 1: -dynamiclib: command not found
make[2]: *** [libstdc++.la] Error 127
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2
steve-baxters-power-mac-g5:/Volumes/Stuff/Users/stevebaxter/Desktop/
gcc-5026.1/libstdc++-v3 stevebaxter$
Cheers,
Steve.
Stephen Baxter
Software Development Manager
Improvision
email@hidden
+44-2476-692229
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40improvision.com
This email sent to email@hidden
Stephen Baxter
Software Development Manager
Improvision
email@hidden
+44-2476-692229
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden