5
\$\begingroup\$

I have a bunch of variables that should be initialized then my game launches, but must of them are never initialized.

Here is an example of the code:

MyClass.h

class MyClass : public BaseObject {
    DECLARE_CLASS_RTTI(MyClass, BaseObject);
    ...
};

MyClass.cpp

REGISTER_CLASS(MyClass)

Where REGISTER_CLASS is a macro defined as follow

#define REGISTER_CLASS(className)\
class __registryItem##className : public __registryItemBase {\
    virtual className* Alloc(){ return NEW className(); }\
    virtual BaseObject::RTTI& GetRTTI(){ return className::RTTI; }\
}\
\
const __registryItem##className __registeredItem##className(#className);

and __registryItemBase looks like this:

class __registryItemBase {
    __registryItemBase(const _string name):mName(name){ ClassRegistry::Register(this); }
    const _string mName;
    virtual BaseObject* Alloc() = 0;
    virtual BaseObject::RTTI& GetRTTI() = 0;
}

Now the code is similar to what I currently have and what I have works flawlessly, all the registered classes are registered to a ClassManager before main(...) is called. I'm able to instantiate and configure components from scripts and auto-register them to the right system etc...

The problem arrises when I create a static library (currently for the iPhone, but I fear it will happen with android as well). In that case the code in the .cpp files is never registered.

Why is the resulting code not executed when it is in the library while the same code in the program's binary is always executed?


Bonus questions:

For this to work in the static library, what should I do?

  • Is there something I am missing?
  • Do I need to pass a flag when building the lib?
  • Should I create another structure and init all the __registeredItem##className using that structure?
\$\endgroup\$
6
  • 2
    \$\begingroup\$ I remember having the same issue.. where I initialized a factory through a bunch of global variables. Didn't work as a static lib. Ended up writing an "init" function that had to be called by the application. \$\endgroup\$ Sep 27, 2012 at 18:43
  • \$\begingroup\$ @JariKomppa yes, this confirms snake5's answer. I was hoping for a more dynamic option, I will do the same (init function) then if time allows I will explore a few other options. Thanks. \$\endgroup\$
    – Coyote
    Sep 28, 2012 at 6:12
  • \$\begingroup\$ Note that names containing two consecutive underscores anywhere, starts with an underscore and a capital letter, or is in the global namespace and starts with an underscore are all reserved for the implementation. \$\endgroup\$ Dec 20, 2013 at 12:59
  • \$\begingroup\$ @JoshPetrie Why not move the question to stack overflow directly instead of closing it? It's been sitting in Game Dev for over a year... Why close it now? \$\endgroup\$
    – Coyote
    Dec 20, 2013 at 15:22
  • \$\begingroup\$ @Coyote The rules of the site have changed a bit since this question was asked. Closing old questions to new rules is one way to make sure people searching the site know what kind of questions are off and on topic (if they see someone else doing it, it makes it seem OK). Further, questions can't be migrated this long after they've been asked. It's not something that you did wrong. It's OK for the question to be closed, it will still remain on the site and people can still benefit from it. \$\endgroup\$
    – House
    Dec 20, 2013 at 15:42

2 Answers 2

4
\$\begingroup\$

My guess is that none of those static library variables are used directly by the executable. The compiler likes to optimize these situations by removing the initialization code of unused variables.

For this thing to work, you have to at least touch each variable (do a read/write that cannot be optimized out*) that you want initialized from all static libraries. This basically means creating a function in the library that touches all variables and is called from the executable, somewhere before the point the variables are actually used for the first time.

*- Since this task heavily depends on compiler type, settings and many other things, I'll leave it up to you. For starters, you could try printf'ing some of the contents of those variables.

\$\endgroup\$
2
  • \$\begingroup\$ I feared the solution could not be automated. The variables serve no real purpose apart from forcing the initialization. I wouldn't like having to touch them manually as this introduces more room for human error. Some of the code of the library is never exposed to the application so maybe I'll keep it all organized myself in the meantime. \$\endgroup\$
    – Coyote
    Sep 28, 2012 at 3:44
  • \$\begingroup\$ "none of those static library variables are used directly by the executable" Marked as the correct answer. But I'm sure some references and a mode detailed peek into gcc and/or clang would be instructive. \$\endgroup\$
    – Coyote
    Aug 11, 2013 at 7:39
3
\$\begingroup\$

This answer actually fixes the issue:

Use the -all_load linker option to load all members of static libraries. Or for a specific library, use -force_load path_to_archive.

In Xcode, you'll want to add these options under "Other Linker Flags" for your executable (not your static library).

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged .