Problem with libc++

I don't know if this is the right place for this, if not please direct me to a better place.

I just downloaded clang and libc++ trunk. This code fails:

#include <string>
#include <vector>

using namespace std;

int main(int argc, const char * argv)
{
  vector<string> v;
  v.push_back("Hello"); // <--- error here

    return 0;
}

The error is "no viable overloaded '='". It seems as if moving strings is broken...

This is in Xcode 4.3.2 (with the include directory from libc++ trunk replacing /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk/usr/include/c++/v1). If I switch to the "normal" clang Compiler in Xcode it works. If I switch from using "libc++" to "libstdc++" it also works, its the combination of the current clang and libc++ that have this problem.

/opt/bin/clang --version
clang version 3.1 (trunk 153948)
Target: x86_64-apple-darwin11.3.0

This is looking like a clang problem. I've got TOT libc++, but a slightly older clang and I'm not seeing this behavior.

Howard

I don't think. I have a TOT clang & libc++, and don't have any issue. Probably a problem with the way clang and libc++ are used with Xcode.

-- Jean-Daniel

Spot on!

Xcode has (at least) 2 locations for the c++ headers, one in Xcode/Developer/Toolchains and another in Xcode/Developer/Platforms/MacOSX.platform/blablabla. I had replaced the one in Toolchains with the libc++ ToT headers, but not the other. Still figuring out how and when it uses which headers, but indeed it's an Xcode problem. Or rather a problem with me not understanding how Xcode works :slight_smile:

Thanks,
Dix

I don't think you want to replace the built-in headers or libraries.
Instead you should probably set up the version of libc++ you want
somewhere, disable the standard c++ library in your project with
-nostdinc++ and then point your Xcode project at the libc++ build you
set up using the search path and linker options.

On the command line this might look like:

clang++ -nostdinc++ -H../libcxx/include -L../libcxx/lib -lc++ main.cpp

AFAIK, you don't have too use -nostdinc++. clang lookups libc++ headers relatively to its resources directory, so if you install your custom clang in /usr/local/bin, just put them in /usr/local/lib/c++/v1 and it should works.

I tried Seth' suggestion first, that worked... then I read Jean-Daniels mail, threw most of my changes out again, copied the headers to yet another location... and that works too!

Awesome, many thanks to both of you.

I am afraid it does not work for the dylib though: with clang installed in /usr/local, installing

/usr/local/lib/libc++.1.dylib
/usr/local/lib/libc++.dylib

and then compiling a trivial program with clang++ -stdlib=libc++, I verified using otool -L that it is linked against

/usr/lib/libc++.1.dylib

That's with clang 3.1 branch. Linking against one lib and using the headers of another one, that would be a bug, wouldn't it?

Luc Bourhis

When linking against a dylib, the linker use the library install path that is encoded in the library itself, and has nothing to do with the actual library path.

You can query it using the otool command line tool:

otool -L /usr/local/lib/libc++.dylib
/usr/local/lib/libc++.dylib:
  /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 28.1.0)
  /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
  /usr/lib/libc++abi.dylib (compatibility version 1.0.0, current version 14.0.0)

The first line is the install name (it can also be query by listing the load command using the '-lv' flag and looking for the LC_ID_DYLIB command).
Other lines are the library dependencies.

Using the same tool, you can check what library your binary will use.

If you want that your resulting binary use the library in /usr/local, you have to update your library first to change its install name, and then relink your binary.

It can be done using install_name_tool :

install_name_tool -id /usr/local/lib/libc++.1.dylib /usr/local/lib/libc++.1.dylib

The first '/usr/local/lib/libc++.1.dylib' is the install path that will be saved in the binary, and the second one, is the path to the binary itself.

Note that this tool may also be used to edit the path of a dependency in an existing binary. If you have an executable that link on /usr/lib/libc++.dylib, you can edit it to use your custom build instead using the '-change' flag.

About using new headers and linking against the system library. Don't forget that libc++ is a template library. Most of the code is in the headers, and only some implementation details are in the binary.
The binary interface of the library (exported functions) didn't change since the Lion release, so it is perfectly valid to use the new headers and link on the existing library. It may contains some bugs fixed in the 3.1release, but AFAIK, most of the changes between the Lion release and the clang 3.1 release was done in the headers.

-- Jean-Daniel