How to force include static objects from a static library in C++ (MSVC 11)
Asked Answered
M

1

3

I am trying to initialize a static object in a C++ file which is trying to auto register a class to a factory in its constructor (like any standard auto-registration problem). The problem is, this is compiled to a static library, and while linking to an executable, that is optimized away. There should have been a very simple solution to that, but surprisingly, looks like it's not that simple.

Here's my class:

In Factory.h (part of static lib project)

class DummyClass : public BaseFactoryClass
{
    int mDummyInt;
public:
    DummyClass()
    {
        std::cout << "Pretending to register myself to the factory here\n";
    }
};

In some cpp, let's say Circle.cpp (still part of the static lib project)

static DummyClass dum;

main.cpp (part of the executable)

//some code accessing the BaseFactoryClass of the Registered derived classes. 

Now, since the static object is not 'directly' used in the executable project, it's skipped from the linked library.

I want to make it work in MS VC11 (Visual Studio 2012) (and GCC 4.8.*, but that's for later). Looking at other questions, I tried various things so far, which don't seem to work:

  1. Looks like /WHOLEARCHIVE linker option is only supported from Visual Studio 2015 (We're using VS 2012)
  2. Specifying /OPT:NOREF should have worked (I tried several combination of this with other flags like /OPT:NOICF), but it doesn't work for anyone.
  3. I tried #pragma comment (linker, "/include:symbolName") in the header file, but that gives a linker error about symbol being unrecognized. (And also that wouldn't work in GCC, but probably --whole-archive works there).

There is a flag in Visual Studio Linker Settings that allows linking all object files individually rather than the static lib, but I don't want to go that route. Also, preferably I'd just want to write something in the source (.cpp) of each individual class I want to automatically register, with all the boiler plate code and macros being in a central header like BaseFactory.h etc. Is there any way to do it (even in C++ 11 where there's a guarantee that a symbol will be initialized)? Want to make the registration of a new class as easy as possible for any new developer.

Madelina answered 5/9, 2016 at 19:43 Comment(7)
This may be relevant: What’s the “static initialization order fiasco”?Topmast
Why is your dum object static? I guess that removing the static keyword will solve your problem. By making your object static, only Circle.cpp can access this variable.Trocar
Hi, I had already tried that. Since this is not directly referenced in the executable project, both static and globals are removed. I can create an accessor function and call that in the main.cop file which causes its creation, but I really don't want to do that as it's not needed there(only the class it registers to is needed).Madelina
@JesperJuhl: I don't think it is. For me, the static object is not even created as it's inside a static library and is not directly referenced in the executable project.Madelina
@JesperJuhl: No, that's an ordering problem, but it only occurs if the two objects involved are created. This is a single object, not two, and it doesn't even get created.Paolapaolina
I did say "may be relevant" - stressing the "may" ;)Topmast
@madmann91, the reason for using a static (although in C++ it should be a no name namespace...) is to avoid having the symbol appear publicly. That way you avoid potential clashes with other declarations.Ambiversion
A
1

In MSVC you have a linker pragma you can use for that purpose:

#pragma comment (linker, "/export:_dum")

This way whenever the linker is run, it will force link _dum in your executable or DLL.

A better way, though, would be to consider using a DLL instead of a static library. Then you avoid this problem altogether since on each load of the DLL that static variable will be initialized.

Ambiversion answered 19/4, 2019 at 18:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.