2

I have some code I want to execute at global scope. So, I can use a global variable in a compilation unit like this:

int execute_global_code();
namespace {
int dummy = execute_global_code();
}

The thing is that if this compilation unit ends up in a static library (or a shared one with -fvisibility=hidden), the linker may decide to eliminate dummy, as it isn't used, and with it my global code execution.

So, I know that I can use concrete solutions based on the specific context: specific compiler (pragma include), compilation unit location (attribute visibility default), surrounding code (say, make an dummy use of dummy in my code).

The question is, is there a standard way to ensure execute_global_code will be executed that can fit in a single macro which will work regardless of the compilation unit placement (executable or lib)? ie: only standard c++ and no user code outside of that macro (like a dummy use of dummy in main())

Borislav Stanimirov
  • 1,609
  • 12
  • 23
  • 1
    Related? http://stackoverflow.com/a/11336506/5265292 – grek40 Jan 27 '17 at 10:29
  • You've eliminated the possibility of various solutions to your problem, in your description. Why do you insist that code to initialise `dummy` must fit in a single macro? – Peter Jan 27 '17 at 10:33
  • @Peter because otherwise a "dummy usage of `dummy` in main" would be the solution. The key is that I don't want to burden a library user with explicit initialization code. – Borislav Stanimirov Jan 27 '17 at 10:44
  • @grek40 This is a compiler-specific solution. It is something I may need to employ, but I was hoping to find a standard C++ solution (if such exist) without having to `#if`-check various compilers or impose various compiler settings to a library user – Borislav Stanimirov Jan 27 '17 at 10:47
  • I can't verify the following right now, but it might be worth a try. Lets assume minimal user code: `#include `. In there, you can instantiate a `static` variable of a class type from your library. Inside the class type, you can have another static variable, which is initialized by your function. My theory: when (and only then) the first static header variable is instantiated, the class-static variable will be constructed (library code can be executed there). – grek40 Jan 27 '17 at 12:04
  • 2
    Adding to what @grek40 has said, it does sound as if a [Schwartz/Nifty Counter](https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter) might be what you're looking for. – G.M. Jan 27 '17 at 12:58
  • If I remember correctly, making the variable `volatile` could work. Write to volatile is an "observable side effect" and couldn't be removed by the compiler. – HolyBlackCat Jan 27 '17 at 15:57
  • Possible duplicate of [Static variable initialization over a library](http://stackoverflow.com/questions/5202142/static-variable-initialization-over-a-library) – Wandering Logic Apr 11 '17 at 17:45

1 Answers1

2

The issue is that the linker will use all object files for linking a binary given to it directly, but for static libraries it will only pull those object files which define a symbol that is currently undefined.

That means that if all the object files in a static library contain only such self-registering code (or other code that is not referenced from the binary being linked) - nothing from the entire static library shall be used!

This is true for all modern compilers. There is no platform-independent solution.

A non-intrusive to the source code way to circumvent this using CMake can be found here - read more about it here - it will work if no precompiled headers are used. Example usage:

doctest_force_link_static_lib_in_target(exe_name lib_name)

There are some compiler-specific ways to do this as grek40 has already pointed out in a comment.

Community
  • 1
  • 1
onqtam
  • 4,356
  • 2
  • 28
  • 50