Search code examples
iosxcodeundefinedsymbolsgameplay3d

XCode: "undefined symbols" for one specific method from library (iOS)


I have a test project that is linked against a game engine static library. I managed to successfully build it for OS X and iOS, and then, during my experiments, added a new usage of library method to my application code (having some other usages already):

std::vector<Node*> allNodes;
_scene->findNodes("", allNodes, true, false);

After that iOS build started to produce linker errors (while OS X build still works fine):

Undefined symbols for architecture armv7:
  "gameplay::Scene::findNodes(char const*, std::vector<gameplay::Node*, std::allocator<gameplay::Node*> >&, bool, bool) const", referenced from:
      App::initialize() in App.o
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Undefined symbols for architecture armv7s:
  "gameplay::Scene::findNodes(char const*, std::vector<gameplay::Node*, std::allocator<gameplay::Node*> >&, bool, bool) const", referenced from:
      App::initialize() in App.o
ld: symbol(s) not found for architecture armv7s
clang: error: linker command failed with exit code 1 (use -v to see invocation)

At the same time other functions (from even the same class Scene) are linked and work fine. This method has the following signature:

unsigned int findNodes(const char* id, std::vector<Node*>& nodes, bool recursive = true, bool exactMatch = true) const;

In .cpp file its implementation has matching signature:

unsigned int Scene::findNodes(const char* id, std::vector<Node*>& nodes, bool recursive, bool exactMatch) const

Still it doesn't link. What could be wrong with this particular method?

XCode version is 5.0.2

EDIT 1: The library was built from sources for armv7/armv7s architecture, so as the app itself.


Solution

  • The problem came from C++11. My app uses it, but the engine library doesn't. In library settings the options "C++ Language Dialect" and "C++ Standard Library" are set to "Compiler Default". In app settings they were set to "C++11 [-std=c++11]" and "Compiler Default" respectively. With these options I once had many linker errors for std functions, so I also specified libc++.dylib manually in "Link Binary With Libraries" section, and everything worked fine for a while. However, this combination of options resulted in such odd behavior.

    I fixed the problem by removing libc++.dylib from the list and setting "C++ Standard Library" to "libc++". Library options remained unchanged. I began looking in this direction after comparing the nm output for the library and my object file:

    $ nm -arch armv7 -A Products/Debug-iphoneos/libgameplay.a | grep findNodes
    ...
    Products/Debug-iphoneos/libgameplay.a:Scene.o: 00000ea0 T __ZNK8gameplay5Scene9findNodesEPKcRNSt3__16vectorIPNS_4NodeENS3_9allocatorIS6_EEEEbb
    ...
    $ c++filt __ZNK8gameplay5Scene9findNodesEPKcRNSt3__16vectorIPNS_4NodeENS3_9allocatorIS6_EEEEbb
    gameplay::Scene::findNodes(char const*, std::__1::vector<gameplay::Node*, std::__1::allocator<gameplay::Node*> >&, bool, bool) const
    
    $ nm -arch armv7 -A Intermediates/Rebus.build/Debug-iphoneos/Rebus-ios.build/Objects-normal/armv7/App.o | grep findNodes
    <long_path>App.o: U __ZNK8gameplay5Scene9findNodesEPKcRSt6vectorIPNS_4NodeESaIS5_EEbb
    $ c++filt __ZNK8gameplay5Scene9findNodesEPKcRSt6vectorIPNS_4NodeESaIS5_EEbb
    gameplay::Scene::findNodes(char const*, std::vector<gameplay::Node*, std::allocator<gameplay::Node*> >&, bool, bool) const
    

    (notice the "__1" difference in std::vector).

    Thanks @sergio for clues.