Reputation: 446
I have an implementation of an abstract factory with automatic registration: ie. in my derived classes I have a static call to a singleton of the factory that registered the my class. My classes are always in a library that gets linked into an executable.
This is the registration call from my cpp files:
static bool DERIVED_CLASS_NAME_reg = singleton<abstract_factory>::instance().register("DERIVED_CLASS_NAME");
This works great when linking dynamically. Even when having my derived classes in multiple libraries, they all get registered when the executable gets called. When linking statically though, the static registration call is never executed and my classes go unregistered.
I am assuming that when statically linking the executable, the compiler decides to drop everything not directly called by the executable. If this is the case, how can I tell the compiler to include this?
If it could be something else, any ideas?
Thank you
my initial implementation was discussed here: c++ automatic factory registration of derived types
Upvotes: 1
Views: 842
Reputation: 153955
When linking, there is no guarantee that object files from a library are included unless there is at least one symbol in the object file which resolves a symbol which is so far undefined. I guess your factory object is in an object file which doesn't resolve any symbols and is, thus, simply ignored during linking.
In fact, there is no guarantee that all symbols from an object file are included at all: some compilers support function-level sections and the linker will only include referenced symbols, leaving others out. Since your registration symbol is never referenced, it may end up not being included. Most systems I'm aware of don't use function-level sections by default, i.e., it would be enough to guarantee that your object files are included even if the registration symbol itself is not included.
The safest way to get things registered is to call a function for each one of them. Where calling corresponding functions isn't an option, linking the corresponding object files explicitly is the next best option. Simply linking with a static library won't do the trick. This problems doesn't happen with shared object because a shared object includes all object files with all of their symbols.
Upvotes: 2