Question

I'm compiling OpenTTD on Mavericks. The only change I have made is to define CXXFLAGS="-stdlib=stdc++". When linking, I get many linker errors that look like this:

  "std::string::compare(char const*) const", referenced from:
     LoadTranslations() in game_text.o
     IsSameScript(ContentInfo const*, bool, ScriptInfo*, Subdirectory) in script_scanner.o
  "std::string::compare(unsigned long, unsigned long, char const*) const", referenced from:
     LoadTranslations() in game_text.o

However, I know that these symbols should be in libstdc++, which is being linked:

$ nm -a /usr/lib/libstdc++.dylib  | c++filt | grep "std::string::compare"
000000000002ed12 T std::string::compare(char const*) const
000000000002ec02 T std::string::compare(std::string const&) const
000000000002ed68 T std::string::compare(unsigned long, unsigned long, char const*) const
000000000002ede6 T std::string::compare(unsigned long, unsigned long, char const*, unsigned long) const
000000000002ec44 T std::string::compare(unsigned long, unsigned long, std::string const&) const
000000000002eca4 T std::string::compare(unsigned long, unsigned long, std::string const&, unsigned long, unsigned long) const

I know libstdc++ is being linked in, as I can see -lstdc++ in the call to the linker (using "make VERBOSE=1"):

g++ -L/opt/local/lib  -framework Cocoa  3rdparty/md5/md5.o <lots of .o files> video/cocoa/wnd_quickdraw.o   -lstdc++ -lc -F/System/Library/Frameworks -framework Cocoa -framework Carbon -framework AudioUnit -framework AudioToolbox -lz -L/opt/local/lib -llzma    -llzo2 -L/opt/local/lib -lpng15  -L/opt/local/lib -lfreetype -lz -lbz2  -L/opt/local/lib  -licui18n -licuuc -licudata  -licule -liculx   -o openttd

I am using the current version of clang:

Apple LLVM version 5.0 (clang-500.2.78) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.0
Thread model: posix

Why isn't the linker matching up the missing symbols, and their definitions in libstdc++?

EDIT: I manually ran the above GCC command, this time manually adding -stdlib=stdc++ to the end of the command line, and it worked just fine. I knew that order matters, but which of the flags would be overriding the earlier -stdlib=stdc++?

Was it helpful?

Solution

I knew that order matters, but which of the flags would be overriding the earlier -stdlib=stdc++?

At a guess, I expect that Clang behaves like g++ and adds something to the linker command to link to the standard library. g++ adds -lstdc++ after all the libraries you specify, so Clang probably adds either -lc++ by default or -lstdc++, depending on the value of stdlib you use. It might even filter out any -lstdc++ you specify if it's going to add -lc++, so if you want Clang to reliably link to the right library, you need to use the right option, instead of trying to pass -lstdc++ manually.

You can add -v to the clang command and it should show you the precise command it uses to invoke the linker, including whatever options are implicitly added.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top