On Mon, Dec 05, 2011 at 04:47:08PM +0000, Richard Sandiford wrote:
Richard Sandiford richard.sandiford@linaro.org writes:
Dave Martin dave.martin@linaro.org writes:
Another way of doing a similar thing is to mark __mylib_constructor as undefined in all the objects that make up the library.
Unfortunately, there seems to be no obvious way of doing that: the assembler generates undefined symbol references automatically for unresolved references at assembly time. There's no way for force the existence of an undefined symbol without an actual reference to it.
One way of doing this is to create an R_ARM_NONE relocation against it, such as:
.reloc .,R_ARM_NONE,__mylib_constructor
This isn't as hacky as it might sound, because undefined references don't really make much sense without an associated reloc.
Not that I recommend this as a fix for the original problem btw. :-) Just FYI.
Agreed -- it's possible, but it doesn't feel like a nice solution.
As Kito says, the easiest way of treating a static link like a shared one is to use --whole-archive -lfoo --no-whole-archive. If the library
Ideally, a lot of unused code can be discarded automatically in a static link (although this may vanish into the noise when considering that _any_ use of stdio will typically pull in over 300K of probably mostly dead code from libc). --whole-archive would completely defeat this, though the degree to which this matters depends somewhat on the size of the library.
is compiled with -ffunction-sections -fdata-sections, --gc-sections should remove the unnecessary code.
Most projects don't use those options though, and a fair number of projects make assumptions which cause them to break if --gc-sections is used.
Requiring people to link with a special option doesn't really solve the problem as stated -- they could link directly with mylib_ctors.o or -u __mylib_constructor after all.
Building a static library which "just works" with regard to running initialisation code is possible, but there seems to be no really good way of doing it.
Where the library has some notion of a session (where you create some kind of heavyweight context, do something with it and then release it), Mans' suggestion of tying the construction/destruction to this context seems the most convenient option. This exposes the link-time dependencies in a way which the linker can understand correctly without extra help, and provides a natural and convenient API to the user.
Provding you're careful to do it in a thread-safe way, you can also tie lazy initialisation of the library (if it needs global initialisation) to take place at the first "create context or session" call.
Libraries which are sessionless seem less likely to need global initialisation anyway, though it will depend on the library.
Cheers ---Dave