How to force inclusion of an object file in a static library when linking into executable?
It turns out my original attempt was mostly there. The following works:
extern "C" void Af(void);
void (*Af_fp)(void) = &Af;
For those that want a self-contained preprocessor macro to encapsulate this:
#if defined(_WIN32)
# if defined(_WIN64)
# define FORCE_UNDEFINED_SYMBOL(x) __pragma(comment (linker, "/export:" #x))
# else
# define FORCE_UNDEFINED_SYMBOL(x) __pragma(comment (linker, "/export:_" #x))
# endif
#else
# define FORCE_UNDEFINED_SYMBOL(x) extern "C" void x(void); void (*__ ## x ## _fp)(void)=&x;
#endif
Which is used thusly:
FORCE_UNDEFINED_SYMBOL(Af)
How to force inclusion of unused object definitions in a library
Well, the other answers where good attempts but ultimately fruitless. I am going to use the refit trick but the rest appears to have been a red herring; it kind of makes sense since the template in question isn't actually used anywhere else so the fact that it's not explicitly instantiated shouldn't make a difference...the declaration of the global still happens in A translation unit, it has side effects...I don't think the standard allows it to be optimized away.
The unfortunate bit about the standard not saying whether or not it is required to include a translation unit at all is the ultimate issue. I think C++0x is doing something about this but maybe not... At any rate, MS feels free to not include the unit at all, and since it doesn't the global isn't ultimately included in the executable and thus none of the other crap happens.
What I've decided to do, and there are of course many other ways, is to create a file 'tag' variable. That tag is then assigned to in a function that is globally accessible (it HAS to assign or assign from or the reference is optimized away). Then that function has to be called from the executable.
I decided to do it this way because then the rest still works the same as it always has. I don't end up ultimately changing behavior like I could if I simply wrote a registration function that hand-registered the types. Plus I can do other things this way...I just have to make sure that anything that might fall into this classification of fucktardery has a tag and that tag is accessed.
I'll be writing a bunch of helper macros to make this mostly painless.
different behavior when linking with static library vs using object files in C++
This is a result of the way linkers treat libraries: they pick and choose the objects that define symbols left undefined by other objects processed so far. This helps keep executable sizes smaller, but when a static initialization has side effects, it leads to the fishy behavior you've discovered: member.obj / member.o doesn't get linked in to the program at all, although its very existence would do something.
Using g++, you can use:
g++ shell.cpp -Wl,-whole-archive registry.a -Wl,-no-whole-archive -o shell
to force the linker to put all of your library in the program. There may be a similar option for MSVC.
linking static library into dll
Just a few points:
It's entirely possible for functions in a static library to create and manipulate UI, either User32 windows or console (I guess Modern UI as well).
Unless you provide special functions for the purpose, the application using your library can't tell what macros were used for library compilation.
Windows headers sometimes will provide defaults if you haven't defined any of a set of macros
(e.g.WINVER
)These macros are only as magic as your code makes them. If you aren't testing them, then defining them is going to have almost no effect.
If your library does conditionally make UI features available, skipping those at compile-time with
#if defined(_WINDOWS)
has some advantages over run-time enable flags.
In particular, if calls to UI functions are stripped by the preprocessor, the linker won't need to add UI DLLs to the import table. Might make a difference whether your library works on Server Core installs of Windows. At the same time, runtime checks are nice because you only need to compile the library once and distribute one version. Using run-time enable flags and setting the linker to use delay-load might give the best of both worlds.
Static library linked two times
As far as I know, it depends on the operating system (because C++ language doesn't say much about how libraries should work).
On windows, you'll get twice the code and data, and worse of that all twice the global variables declared in that library (!)
This issue shows up when linking statically the standard library in a program and a library using that, when you get two default allocators and if you call new
on a library and delete
on the other, the object will leak on the new
side and the heap is likely to become corrupted on the delete
side.
I do not know the details about other operating systems, but I expect similar issues may arise
Missing symbols from static library in linked executable
Use -rdynamic -Wl,-whole-archive <all your libs> -Wl,-no-whole-archive <boost, pthread and so on>
- one of your libs aren't within --whole-archive
Related Topics
Findchessboardcorners Cannot Detect Chessboard on Very Large Images by Long Focal Length Lens
What Would a Std::Map Extended Initializer List Look Like
In Cmake, How to Work Around the Debug and Release Directories Visual Studio 2010 Tries to Add
Compile Lua Code, Store Bytecode Then Load and Execute It
Cygwin Make Bash Command Not Found
"Apientry _Twinmain" and "Winapi Winmain" Difference
How to Initialize Static Members in the Header
Getting a Directory Name from a Filename
Is There Any Advantage to Using Pow(X,2) Instead of X*X, with X Double
Serialize and Send a Data Structure Using Boost
When and Why Would You Use Static with Constexpr
C++ Overloaded Virtual Function Warning by Clang
Gcc Error: Explicit Specialization in Non-Namespace Scope
Why Can't I Store References in a 'Std::Map' in C++
What Are Potential Dangers When Using Boost::Shared_Ptr
Copying Non Null-Terminated Unsigned Char Array to Std::String