How can I tell clang to use (link to) a specific libc++ shared library?

Hi all,

Apologies in advance if this is not the appropriate mailing list.

I am struggling with a bit of confusion over some things.

I have a very long-winded question posted here (http://stackoverflow.com/questions/25920130) which essentially boils down to one basic question.

When compiling clang from source, how do I specify to it where it should fetch the libc++ library from?

I am talking about libc++.dylib (or whatever it is symlinked to) on OS X/BSD or libc++.so on Linux. This is the component of the libc++ library that has to be linked in order to work with the libc++ headers, in order to actually compile any C++ that uses the standard library, which is after all, most of the reasons to use C++ to begin with.

One possible answer is that this cannot be done, and that it is hardcoded.

My follow-up question to this is: Can you show me where it is hardcoded? I have grepped the entire clang project and strangely enough, I have seen no files in clang/llvm’s source code (aside from cmake/make/buildit files inside of the libcxx project) that reference “/usr/lib/libc++.1.dylib”.

However, I have also looked at the generated clang++ executable (whose size is 50504624 bytes) at strings inside, and found that the string “/usr/lib/libc++.1.dylib” exists at offset 2184. A more useful check yields this:

$ otool -L Release+Asserts/bin/clang
Release+Asserts/bin/clang:
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
/usr/lib/libedit.3.dylib (compatibility version 2.0.0, current version 3.0.0)
/usr/lib/libncurses.5.4.dylib (compatibility version 5.4.0, current version 5.4.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)

This leaves me puzzled because I see no straightforward code, whether in clang’s build configuration files, or in clang’s source code, that determines that it shall link /usr/lib/libc++.1.dylib, and yet there it is.

This issue does not crop up on Linux because Linux does not come with clang as part of the system. Therefore the clang install process will properly handle the library and install it where it needs to go, which I will be surprised if it turns out to be anything other than /usr/lib/.

The problem on OS X is that the OS will break if the system’s /usr/lib/libc++.1.dylib is tampered with, so I want to specify it separately so that the system continues using that one provided by Apple, and I can specify explicitly for my svn-built clang where it should go to grab its corresponding svn-built libc++ shared library.

I guess I also must mention the distinct possibility that I am getting all worked up over nothing, as would be the case if building libc++/libcxx from source yields the exact same library as the one my system already has.

However, this also is not clear:

$ cd ~/Documents/llvm/

$ diff /usr/lib/libc++.1.dylib projects/libcxx/build/lib/libc++.1.0.dylib
Binary files /usr/lib/libc++.1.dylib and projects/libcxx/build/lib/libc++.1.0.dylib differ

$ ls -la /usr/lib/libc++.1.dylib projects/libcxx/build/lib/libc++.1.0.dylib
-rwxr-xr-x 1 root wheel 1405296 Mar 17 2014 /usr/lib/libc++.1.dylib
-rwxr-xr-x 1 steven staff 1688180 Sep 18 15:55 projects/libcxx/build/lib/libc++.1.0.dylib

I hope someone can shed a little light on this.

Thanks
Steven

Hi all,

My follow-up question to this is: Can you show me where it is hardcoded?

See clang/lib/Driver/ToolChains.cpp. A specific example is around line 600 in `void DarwinClang::AddCXXStdlibLibArgs()`

If you want to install your own, the best bet is to make a separate sysroot (in, say, /opt/foo), and install it there. Installing in the root directory, as you say, is pretty dangerous on OSX.

Cheers,

Jon

Thanks Jon, this is starting to make more sense now. This must mean that on Darwin, a -lc++ is just automatically added to the args for all compilations! This naturally grabs /usr/lib/libc++.dylib.

The digging I did that resulted in otool -L showing a dependency on libc++.dylib must then in fact be due to simply using Apple’s clang 5.1 (based on 3.4-svn) to build the clang (3.6.0-svn) that I am testing. This is just a case of clang itself needing to use the C standard library, as it should in this situation.

So to achieve my goals it would appear that I need to do two things:

  1. Install freshly built libcxx to e.g. /opt/foo
  2. Somehow coerce clang to look somewhere inside /opt/foo to grab both its libc++ headers and libc++.dylib

I would hope that configuring a clang build for /opt/foo as sysroot will do exactly this (where I can conveniently remember that all i need to access my new clang is to use the one that resides in /opt/foo/bin).

Then I don’t even have to patch any code or anything!