I have static library (.lib) in VS2010 and am linking it to my test project.
The lib has a factory that I create using the below MACRO:
#define REGISTER_FACTORY(mType, my_class) \
class Factory##my_class : public CAbstractFactory\
{\
public:\
Factory##my_class() : CAbstractFactory(mType){}\
CBaseClass *Create()\
{ return new my_class(); }\
};\
static Factory##my_class StaticFactory##my_class;
What is supposed to happen is that in the CAbstractFactory the new factory gets registered by mtype
. But when I check the factory the factory does not exist.
It works fine when I use a DLL instead of a .lib. My guess is that the linker does not include the static variable as it is not referenced or the static variable was not even included in the library.
How can I force the linker to include all objects from the static library in my .exe.
I use the macro like this:
// Register factory that can create CMyObject with ID=100
REGISTER_FACTORY(100, CMyObject);
class CMyObject
{
};
The CAbstractFactory looks like this:
class CAbstractFactory {
CAbstractFactory(int id) {
CFactory::instance().add(id, this);
}
}
Then some where else in the code, my main .exe I use:
CBaseClass *pObject = CFactory::instance().Create(100);
This will then give my a new CMyObject
. The idea is that I have many different kind object and I have a database containing the id specifying the kind of objects I need.
100
is just an example.
So indeed, I do not reference anything from the .lib directly but I want to be able to create the objects using my factory
The CFactory class is a simple class that keeps a register (in a map) of all the CAbstractFactory classes and delegates the create method to the correct factory.
CFactory &CFactory::Instance()
{
static CFactory instance;
return instance;
}
The main problem lies in the fact that I do not reference anything from the .lib as it is all done through the CFactory. It works if I make it a DLL and make sure I add some reference to this DLL to make sure it is loaded. But for a .lib, I even added a dummy function to make sure I have at least one reference that doesn't include the rest of the code.
static
defines an object with internal linkage --> if it's not used internally in the same translation unit, it can be optimized out. Remove thestatic
from your instantiation for the object to have external linkage -Factory##my_class StaticFactory##my_class;
I had a similar problem and solved it by setting the lib project as a dependency of the main app project and then setting 'Link Library Dependencies' and 'Use Library Dependency Inputs' to Yes for the main project.
Update:
Recently I discovered that Visual Studio 2015 now supports a
/WHOLEARCHIVE
linker flag. I can't find it through the linker options, but you can add it as an additional command line option. It works similar to the GCC flag-whole-archive
and you add it to your target linker flags (not to the static lib flags).For example, specify
/WHOLEARCHIVE:lib_name
as an additional linker command line option and it will include all symbols from that lib. You can do this more than one lib as well.If you use this
/WHOLEARCHIVE:lib_name
you no longer need the 'Link Library Dependencies' and 'Use Library Dependency Inputs' set to Yes. This is perfect for solutions generated through CMAKE. See a related answer here: https://stackoverflow.com/a/42083877/1151329