Zig: Zig c++ fails to link against certain static library functions

Created on 13 Jul 2020  路  8Comments  路  Source: ziglang/zig

Version:
zig-linux-x86_64-0.6.0+2c882b2e6

test.cpp:

#include <iostream>
#include "OgreStringConverter.h"
#include "OgreString.h"

int main() {
    float x = 1.1;
    Ogre::String s = Ogre::StringConverter::toString(x);
    std::cout << s << std::endl;
    return 0;
    }

Command:
zig c++ -o test test.cpp -I ogre/Ogre/ogre-next/build/sdk/include/OGRE/ -D_DEBUG -Logre/Ogre/ogre-next/build/sdk/lib/ -lOgreMainStatic_d -lpthread

Output:

...
Compile C Objects [1/1] test.cpp...lld: error: undefined symbol: Ogre::StringConverter::toString(float, unsigned short, unsigned short, char, unsigned int)
>>> referenced by test.cpp
>>>               zig-cache/o/LI0cI4b1ucy8of90Qy6RkfJ7DJ4oDekve4vs2lrmT3SqgXqgxRzBv10l9TyuY7fY/test.o:(main)

Ogre is a 3d rendering library.
I can confirm that both clang++ and g++ can successfully compile and link this executable with the exact same arguments. The interesting part is that if I don't use Ogre::StringConverter::toString, then Zig can still link and use Ogre::String with no problem, so only certain functions of the static library are failing to link.

bug zig cc

Most helpful comment

It seems to be caused by zig c++ not handling [abi:cxx11] function names that are generated by clang and gcc

All 8 comments

Please first test the issue on the master branch of Zig before submitting an issue. You can download a master binary at ziglang.org/download

Exact same error with today's build(zig-linux-x86_64-0.6.0+2c882b2e6).

I think I have a reproducible example now:

OgreStringConverter.h:

#ifndef __StringConverter_H__
#define __StringConverter_H__

#include <ios> // for fmtflags
#include <string>

namespace Ogre {
    class StringConverter
    {
    public:
        /** Converts a float to a String. */
        static std::string toString(float val, unsigned short precision = 6,
                               unsigned short width = 0, char fill = ' ',
                               std::ios::fmtflags flags = std::ios::fmtflags(0));
    };
}
#endif

OgreStringConverter.cpp:

#include "OgreStringConverter.h"
#include <sstream>

namespace Ogre {
    std::string StringConverter::toString(float val, unsigned short precision,
                                     unsigned short width, char fill, std::ios::fmtflags flags)
    {
        return "foo";
    }

}

Link into static library:
$ clang++ -c OgreStringConverter.cpp
$ ar rvs libogre.a OgreStringConverter.o

Create test:
test.cpp:

#include <iostream>
#include "OgreStringConverter.h"
#include <string>

int main() {
    float x = 1.1;
    std::string s = Ogre::StringConverter::toString(x);
    std::cout << s << std::endl;
    return 0;
    }

Confirm that it works with clang++:

$ clang++ -o test test.cpp -L. -logre
$ ./test 
foo

Replace clang++ with zig c++ and you get this:

 $ ../zig-linux-x86_64-0.6.0+2c882b2e6/zig c++ -o test test.cpp -L. -logre
lld:error: undefined symbol: Ogre::StringConverter::toString(float, unsigned short, unsigned short, char, unsigned int)
>>> referenced by test.cpp
>>>               zig-cache/o/Nwbrj1nXWa9XTa12FakBpMtbQSj119lJKVLiI-M6HMk8q-5IC1eJctCrijgBlSPG/test.o:(main)

Oh, and on Windows, I can't even get past the compiler:

zig: warning: argument unused during compilation: '-nostdinc++' [-Wunused-command-line-argument]
Compile C Objects [1/1] test.cpp...zig: warning: argument unused during compilation: '-nostdinc++' [-Wunused-command-line-argument]
zig: warning: argument unused during compilation: '-nostdinc++' [-Wunused-command-line-argument]
Build Dependencies...c++abi [2] Compile C Objects [1/19] abort_message.cpp...zig: warning: argument unused during compilation: '-nostdinc++' [-Wunused-command-line-argument]
zig: warning: argument unused during compilation: '-nostdinc++' [-Wunused-command-line-argument]
In file included from D:\zig-is-broken\zig-windows-x86_64-0.6.0+2c882b2e6\lib\zig\libcxxabi\src/cxa_aux_runtime.cpp:14:
In file included from D:\zig-is-broken\zig-windows-x86_64-0.6.0+2c882b2e6\lib\zig\libcxx\include\typeinfo:72:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\vcruntime_typeinfo.h:119:13: error: target of using declaration conflicts with declaration already in scope
    using ::type_info;
            ^
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\vcruntime_typeinfo.h:69:7: note: target of using declaration
class type_info
      ^
D:\zig-is-broken\zig-windows-x86_64-0.6.0+2c882b2e6\lib\zig\libcxxabi\include\cxxabi.h:29:27: note: conflicting declaration
class _LIBCXXABI_TYPE_VIS type_info; // forward declaration
                          ^
1 error generated.

Your example works for me on linux with zig master, but the example you showed is wrong? The example should print foo should it not?

Ok it seems that when the static library is compiled with clang or gcc, then you try to link to it with zig, it breaks.

@wozeparrot My bad: I was posting the output from an older version of the test. I updated the output so people don't get confused.

It seems to be caused by zig c++ not handling [abi:cxx11] function names that are generated by clang and gcc

Was this page helpful?
0 / 5 - 0 ratings