23

I've got a large static library in C++ with bits of Objective-C originally built for iOS (armv7).

I built a OS X (64-bit Intel x86_64) version of it, but as soon as I tried to use it in a OS X app project (targeted to Lion 10.7), tens of linker errors appeared, most of them about standard library symbols.

I know how to solve "my" linker problems, but the STD ones copied below are bugging me.

"std::basic_filebuf<char, std::char_traits<char> >::is_open() const"
"std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::str() const"
"std::basic_ios<char, std::char_traits<char> >::widen(char) const"
"std::istream& std::istream::_M_extract<double>(double&)"
"std::ostream::put(char)"
"std::ostream::flush()"
"std::ostream& std::ostream::_M_insert<void const*>(void const*)"
"std::ostream& std::ostream::_M_insert<bool>(bool)"
"std::ostream& std::ostream::_M_insert<double>(double)"
"std::ostream& std::ostream::_M_insert<unsigned long>(unsigned long)"
"std::ostream::operator<<(int)"
"std::ostream::operator<<(short)"
"std::string::_Rep::_M_destroy(std::allocator<char> const&)"
"std::string::_Rep::_S_terminal"
"std::string::_Rep::_S_empty_rep_storage"
"std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&)"
"std::string::append(char const*, unsigned long)"
"std::string::append(std::string const&)"
"std::string::assign(std::string const&)"
"std::string::reserve(unsigned long)"
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)"
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&)"
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()"
"std::basic_ofstream<char, std::char_traits<char> >::open(char const*, std::_Ios_Openmode)"
"std::basic_ofstream<char, std::char_traits<char> >::close()"
"std::basic_ofstream<char, std::char_traits<char> >::basic_ofstream()"
"std::basic_ofstream<char, std::char_traits<char> >::~basic_ofstream()"
"std::_List_node_base::hook(std::_List_node_base*)"
"std::_List_node_base::unhook()"
"std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream(std::string const&, std::_Ios_Openmode)"
"std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream(std::_Ios_Openmode)"
"std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::~basic_stringstream()"
"std::basic_ostringstream<char, std::char_traits<char>, std::allocator<char> >::basic_ostringstream(std::_Ios_Openmode)"
"std::basic_ostringstream<char, std::char_traits<char>, std::allocator<char> >::~basic_ostringstream()"
"std::ios_base::Init::Init()"
"std::ios_base::Init::~Init()"
"std::basic_ios<char, std::char_traits<char> >::clear(std::_Ios_Iostate)"
"std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)"
"std::_Rb_tree_decrement(std::_Rb_tree_node_base*)"
"std::_Rb_tree_increment(std::_Rb_tree_node_base const*)"
"std::_Rb_tree_increment(std::_Rb_tree_node_base*)"
"std::__throw_logic_error(char const*)"
"std::__throw_length_error(char const*)"
"std::__throw_out_of_range(char const*)"
"std::_Rb_tree_rebalance_for_erase(std::_Rb_tree_node_base*, std::_Rb_tree_node_base&)"
"std::_Rb_tree_insert_and_rebalance(bool, std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::_Rb_tree_node_base&)"
"std::cerr"
"std::cout"

I checked my build settings, my project links to the standard library (-stdlib=libc++) and I can use std::cout without any problem in my main.cpp.

I changed the compiler in the build settings from Apple LLVM 4.1 to LLVM GCC 4.2 and the problem disappeared. I want to keep using Apple LLVM 4.1. How can I fix that?

Thanks!

antho
  • 943
  • 2
  • 8
  • 11

6 Answers6

47

In iOS 7 I use a library for charts and have the same issue. In this case lib stdc++ does not resolve the issue.

I add the stdc++.6.dylib to my build phase and the symbols are found.

xaxxon
  • 19,189
  • 5
  • 50
  • 80
gzfrancisco
  • 812
  • 10
  • 14
45

Change the standard library that is linked to use libstdc++ instead of libc++ - the problem is that the other library was compiled using the g++ mode which uses the libstdc++ library.

Consider the following sample code:

dhcp-191:~/Development/testy/fred% cat fred.cpp
#include <iostream>
#include <string>
#include "fred.h"

using namespace std;

bool dofred(string &x)
{
    cout << x << endl;
    return true;
}
dhcp-191:~/Development/testy/fred% cat fred.h

#include <iostream>
#include <string>

bool dofred(std::string &x);

dhcp-191:~/Development/testy/fred% clang++ -stdlib=libc++ -shared -o fred.dylib fred.cpp
dhcp-191:~/Development/testy/fred% nm fred.dylib | c++filt | grep dofred
0000000000000fa0 T dofred(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
dhcp-191:~/Development/testy/fred% clang++ -stdlib=libstdc++ -shared -o fred.dylib fred.cpp
dhcp-191:~/Development/testy/fred% nm fred.dylib | c++filt | grep dofred                     
0000000000000e30 T dofred(std::string&)

You get two completely different exported symbols. When trying to use the symbol, the app that uses the same -stdlib flag will be able to link, while the app that doesn't will display a link error.

Anya Shenanigans
  • 91,618
  • 3
  • 107
  • 122
  • 9
    You can tell the difference because libc++ uses an inline namespace inside std, so the symbols in libc++ are like `std::__1::cout`. – bames53 Oct 16 '12 at 18:21
  • @bames53 That's a great tip for tracking down these kinds of link errors! – Anya Shenanigans Oct 16 '12 at 18:24
  • OK thanks! I didn't realize there were 2 available standard library implementations. I understand they have different internals, but I don't get why that leads to linker issues on things like `std::cout`. /edit: saw @bames53's answer. Now I know. A bit confused _why_ though :) – antho Oct 16 '12 at 18:25
  • 2
    @antho Well, the different internals means that the program would be horribly, horribly broken if linking succeeded. So the designer of libc++ took special measures to make sure that linking between modules that use incompatible standard library implementations would not succeed; he used a special feature called inline namespaces to make sure the symbols the linker tries to match up do not match. – bames53 Oct 16 '12 at 18:48
  • thank you! I also didn't realize there were 2 types of library. – Joey Apr 04 '13 at 00:36
  • I was following until `grep cout`, how did that work? – WiseOldDuck Mar 02 '14 at 06:17
  • @WiseOldDuck oops, typo corrected, it should have been dofred, not cout. I have no idea how that happened – Anya Shenanigans Mar 02 '14 at 14:16
11

I had this problem after putting all C++ files into a separate library. I did set the settings of all projects to use libc++, but the linker does not link with libc++. If I add a C++ file to the main project, the problem would disappear. To fix this, you can add '-lc++' on the "Other Linker Flags" section of the main project. This would force XCode to link to libc++.

EDIT: As the other poster said, XCode may be behaving correctly. I had expected it to know to add C++ linkage because the C++ lib source code is on the same workspace.

jlukanta
  • 159
  • 1
  • 11
3

I just had a similar problem, and I had to go to "Build Settings" and then "Apple LLVM 5.1 - Language - C++" and then change the "C++ Standard Library" to libstdc++.

djacobs7
  • 11,357
  • 3
  • 25
  • 33
2

you may also try adding an empty .cpp file to your project. This will trick xcode into loading C++ std libraries

Lee Irvine
  • 3,057
  • 1
  • 15
  • 12
  • 1
    Thanks! This is the only solution that worked for me. I tried linking with libc++ and libstdc++ (specified in both LLVM c++ and "other linker flags" build settings), but no luck... added an empty "foo.cpp" file to the project and, voila, no more linker errors! Thank you! – R.G. Jan 23 '17 at 23:19
0

In response to jlukanta: I had the same problem. I have been careful to choose the right STD but I still got those errors. But that's not a bug, it actually makes sense: Why should Xcode link with the c++ stdlib if you don't have any C++ code in your project?

Of course, this is a problem when you don't have C++ code in your project but still C++ libraries.