How to Force Inclusion of an Object File in a Static Library When Linking into Executable

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



Leave a reply



Submit