Short answer for android NDK work, any static libs that are affected by this problem should be added to the LOCAL_WHOLE_STATIC_LIBRARIES variable -- they'll then be referenced using the -Wl,--whole-archive
flag and won't be subject to stripping.
Longer answer for MSVC:
Static variables in a translation unit are initialized before any regular code in the
translation unit executes. In practice the initialization happens when the containing
executable or dynamic library is loaded. When your c main() is called, or your call to
LoadLibrary()/dlopen()
completes, any static variables will have been initialized.
The Problem, as described by MSDN:
Constructors and assignment by global function or static methods in the declaration do
not create a reference and will not prevent /OPT:REF elimination. Side effects from such
code should not be depended on when no other references to the data exist.
It can be convenient to place the object code from multiple translation units in a single
file, a static library conventionally named with a c .lib or c .a suffix. The MSVC linker does
dependency analysis on static libraries and will not include code that is not referenced
by the including entity.
The common pattern of using a static variable to declare and cause the registration of
a factory object can fail in this circumstance -- the MSVC linker deems the static as
being unreachable and strips it from the result.
Solutions
A useful google search: http://www.google.com/search?q=msvc+factory+static+library
One solution is to set the /OPT:NOREF
linker flag on the including entity. However,
this is an all or nothing setting, and will require that all included libraries be fully linkable.
If something in the file containing the static is referenced (directly or indirectly) by
the including entity, then by the language rules the static itself must be preserved.
The most basic approach is to put a dummy function in the file, and reference that from
somewhere known to be considered reachable.
Another approach is to use the /INCLUDE
linker flag to reference an entity in the problem file.
Assuming an entity named DummyForLinkProblem, this can be done in the including entity's source:
#pragma comment(linker, "/include:DummyForLinkProblem")
ZooLib's Solution
ZooLib entities currently affected by this problem are those in
ZFile_Win.cpp, ZGRgnRep_HRGN.cpp, ZNet_Internet_WinSock.cpp, ZStreamRWCon_SSL_Win.cpp,
ZTextCoder_Win.cpp and ZUnicode_Normalize_Win.cpp.
We #include ZCompat_MSVCStaticLib.h
in the corresponding header files, and put in each a
ZMACRO_MSVCStaticLib_Reference(ModifiedFileName)
. In the cpp files we put a
ZMACRO_MSVCStaticLib_cpp(ModifiedFileName)
. The ModifiedFileName
is generally the
filename with the leading Z and file extension removed, the same style as
used in ZCONFIG_API_XXX
macros.
To ensure that your executable or library does not strip these entities, simply #include
the appropriate header file from known referenced code in your including entity. This will
cause a non-executing reference to occur, and things will work as expected.