问题描述
我开发插件和工具使用clang的规定这样做通过插件和clang的libTooling。我可以做以下事情:
- 通过下面的入门,通过svn(Linux和OSX)编译llvm,通过运行configure脚本(不使用cmake)
- 在Linux上编译libcxx / libc ++(也来自svn),我没有理由期望在OSX上出现任何问题。事情是libc ++标头,在我的OSX系统上已经存在
/Applications/Xcode.app/Contents/Developer/Toolchains /XcodeDefault.xctoolchain/usr/lib/c++/v1/
和libc ++ dylib位于/ usr / lib /.
编辑4:我可以按照说明在OS X上编译libcxx。
-
在OSX上,使用Release + Asserts(和Debug + Asserts)构建
clang ++
通过添加
$ b编译C ++源代码Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1/
并且不使用
-stdlib = libc ++
。使用这个标志来显式地指定libc ++作为一个include目录允许我构建的clang看到标准的c ++头文件。令人惊讶的是,它似乎很高兴,同时编译一个中等基本的源文件(它仍然在其中运行很多的c ++ 11疯狂)
clang版本3.6.0(trunk 217905)
来查找苹果的Xcode包装libc ++。这是表面上工作现在因为苹果的libc ++与Xcode一起来保持ABI兼容的编译器,我刚刚从源代码构建。对我来说还很好奇的是我的新鲜编译的铛是如何找出在哪里找到相应的libc ++ dylib!这提出了以后的问题,当我实际获得libc ++编译,我应该告诉我的新的svn编译clang查找和使用新的svn编译libc ++ dylib ?? 所以,基本上,我仍然完全困惑我应该真正设置libc ++正确的。具体来说,当你告诉 -stdlib = libc ++
?
p>它是一个硬编码的包含路径?我可能想要从svn构建libc ++ abi和libc ++,以便与从svn构建的clang一起使用。这是最有意义的...然后我应该怎么安装它?不必把
-I〜/ libcxx / include / c ++ / v1 /
(或其他任何东西)放入构建配置中是不够的。 据推测,我可以设置我的llvm构建与libc ++ abi和libc ++通过检查libcxxabi和libcxx从svn构建铛,我的期望是安装它应该使 -stdlib = libc ++
神奇的工作。还要注意,苹果给你Xcode的俚语不真正要求你使用 -stdlib = libc ++
。它只是神奇地知道在哪里抓取图书馆文件。
但是!在软膏飞,至少唯一一个到目前为止我知道要寻找:我的机器已经有一个 / usr / bin / clang ++
:
$ ls -la $(其中clang ++)
-rwxr-xr-x 1根轮14240 2014年3月17日/ usr / bin / clang ++
这不是Xcode.app里面的符号链接!我现在真正关心从我的llvm构建目录中运行 make install
!它可能会打破我的Xcode环境或阻止我的Mac启动(因为libc ++ llvm文件清楚地说明会发生如果 / usr / lib / libc ++发生错误1.dylib
)!
希望没有文档,我错过了回答这些问题,因为我真的应该已经找到它现在。
编辑:我在
clang ++ -std = c ++ 11 - stdlib = libc ++ -nostdinc ++ -I< path-to-libcxx> / include -L< path-to-libcxx> / lib test.cpp
实际上可能是正确的方式现在。但是失败的原因是解释 -stdlib = libc ++
导致clang做什么,或者 -nostdinc ++
导致clang执行。
编辑2:感谢@ n.m。现在我们知道 -nostdinc ++
意味着没有标准的c ++包含搜索的路径。这意味着标准包含路径是一件事。当ang构建时,这个路径是否被硬编码?我googled并发现引用变量 CLANG_INCLUDEPATH
的东西,这看起来像可能是一个makefile变量。不幸的是,我运行完整的文件系统文本搜索我的llvm源目录,并发现没有匹配到这样的字符串(所以它不能是一个配置使用由clang或在构建clang过程中)。
编辑3:借助 - verbose
,我现在可以看到一些有用的输出:
Xcode的clang:
clang -cc1 5.1版本基于LLVM 3.4svn默认目标x86_64-apple-darwin13.4.0
忽略不存在的目录/ usr / include / c ++ / v1
#include...搜索从这里开始:
#include< >搜索从这里开始:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1
/ usr / local / include
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/5.1/include
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault .xctoolchain / usr / include
/ usr / include
/ System / Library / Frameworks(框架目录)
/ Library / Frameworks(框架目录)
搜索结束。
svn fresh clang:
clang -cc1 3.6.0基于LLVM 3.6.0svn默认目标x86_64-apple-darwin13.4.0
忽略不存在的目录/ Users / username / Documents / llvmbuild / Release + Asserts / bin /../ include / c ++ / v1
忽略不存在的目录/ usr / include / c ++ / v1
#include...搜索从这里开始:
#include< ; ...>搜索从这里开始:
/ usr / local / include
/Users/username/Documents/llvmbuild/Release+Asserts/bin/../lib/clang/3.6.0/include
/ usr / include
/ System / Library / Frameworks(框架目录)
/ Library / Frameworks(框架目录)
搜索结束。
好吧,所以这是画几个地方的图片来存放一些libc ++文件。
两个忽略不存在的目录条目的存在表明Xcode的clang能够找到一个libc ++的硬编码 / Apps / Xcode .app /.../ c ++ / v1 /
而我的svn clang找不到一个在它想看的地方(在 Release + Asserts
build dir,这看起来很蠢,但实际上可能是libcxx将其头文件复制到llvm构建系统中)。
没有提示它从哪里获取libc ++ dylibs。即使在查看clang可执行文件中的字符串时,使用 string
(这是一个长镜头)。
不完全清楚什么做,但我确实似乎有工具现在要去我的项目。现在的主要问题是 libc ++。dylib
正在发生什么。我不能告诉是否新建的铛是硬编码,以找到它 / usr / lib / libc ++。1.dylib
,或什么。我需要这样做:
- 不要触摸
/ usr / lib / libc ++ 1.dylib
以免破坏我的整个操作系统 - 指向新编译的
clang ++
使用libc ++ .dylib
现在已经构建,并且位于/ usr / lib / libc ++的不同位置。1.dylib
。我不在乎这里的哪里,但我不是要运行make install
这将可能覆盖/ usr / lib / libc ++ .1.dylib
。
这只是不清楚什么是有意义的。指定 -stdlib = libc ++
导致 clang ++
链接硬编码的 / usr / lib / libc ++ .1.dylib
?如果是这样,我可以只删除它,并且 -l< compiled libc ++。dylib>
显式?否则,如何编译clang以修改此路径以使其使用正确的路径?
暂时我将使用 -stdlib = libc ++ -nostdinc ++
(参见第一次编辑),并祈祷它实际上意味着clang听到 -I< new libc ++ header path> -L< new libc ++ dylib path>
。我想如果它仍然不工作,系统文件,无论如何尽管这些努力,我仍然会很高兴,只要我的程序继续编译...
我已经足够了,能够满意地回答我自己的问题,所以我将在这里总结我的发现。
这可能不是整个画面,但它足够让我找到我找不到的信息。
tools / clang / lib / Driver / ToolChains.cpp
的第606行左右是一个代码, code> -lc ++ 到命令参数。这是在clang的工具链实现中(这或多或少是让clang模拟gcc的命令行行为的一部分,以便它与构建目的兼容)。
这意味着libc ++。dylib / so被加载使用与所有其他库完全相同的机制。没有对C ++标准库的特殊处理。这也意味着它是以半硬编码的方式完成的。也许这不是很准确,因为我确实期望显式库路径规范( -L
)可以优先于默认根路径。
无论如何,不要尝试修改 -L
, - sysroot
。通过将libc ++安装到与系统的 / usr / lib
不同的位置,我可以使用 - sysroot
强迫clang甚至不考虑在 / usr / lib
中查找libc ++或其他任何东西。这是一个有用的标志为例如。交叉编译工作。
好吧,这些是操作ang来做我们的投标的一些方法。当然,他们足够强大。现在我需要绝对确保我认为包含和链接的libc ++实际上是被包含和链接的。
我去了一些傻瓜,而不是简单的东西聪明。我对libc ++本身做了一些战略编辑,然后将它安装到一个备用目录(不是 / usr / lib
- 看我的问题为什么我不想乱我的系统libc ++):这可以是任意的,我添加
std :: libcxx_custom_version_type :: libcxx_custom_version_type b $ b libcxx_custom_version =slu_libc ++ _ svn_218071;
}
到src / typeinfo.cpp(在libc ++中)
struct libcxx_custom_version_type {
char * libcxx_custom_version;
libcxx_custom_version_type();
};
包含/ typeinfo。这个服务的目的(是的,它的可怕,哦好)是让它毫不含糊地容易验证,我链接的libc ++实际上是我从源编译的。实际上,我可以通过使用libc ++。dylib上的 strings
找到字符串 slu_libc ++ _ svn_218071
测试c ++文件中的少量测试代码现在可以很容易地显示是否正在链接的libc ++是我刚编译的那个。
要对实际的libc ++头文件很简单,我们只需要定义一个新的宏并在编译期间检查它。
现在我有了所有的工具来回答我的问题。
好吧,实际上,现在我得到这个错误,所以我还不能建立任何东西。
架构x86_64的未定义符号:
std :: terminate(),引用自:
___clang_call_terminate in reflect-16fcd7.o
ld:没有为架构x86_64找到符号
一次一步,我猜...
I am developing plugins and tools using clang's provisions for doing so via plugins and clang's LibTooling. I am able to do the following things:
- Compile llvm with clang inside, from svn (Linux and OSX), by following the getting started page by running the configure script (without using cmake)
Compile libcxx/libc++ on Linux (also from svn), and I have no reason to expect any trouble with this on OSX. The thing is that libc++ headers, already exist on my OSX system at
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1/
and the libc++ dylib lives at /usr/lib/.
Edit 4: I was able to compile libcxx just fine on OS X by following the directions. I've got a brand new libc++.1.0.dylib sitting here now.
On OSX, use the Release+Asserts (and Debug+Asserts) builds of
clang++
to compile C++ source code by appending-I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1/
and without using
-stdlib=libc++
. Using this flag to explicitly specify libc++ as an include directory allows the clang that I built to "see" the standard c++ headers. Surprisingly, it seems to be happy with it while compiling a moderately basic source file (which still exercises a good amount of c++11 madness in it)
Based on this, you can see that I am hacking my freshly built clang version 3.6.0 (trunk 217905)
to look up Apple's Xcode-packaged libc++. This is ostensibly working for now because Apple's libc++ that came with Xcode remains ABI-compatible with the compiler that I just built from source. What is still very curious to me is how my freshly compiled clang is able to figure out where to find the corresponding libc++ dylib! This raises the question later on of when I actually get libc++ compiled, how am I supposed to tell my new svn-compiled clang to look up and use the new svn-compiled libc++ dylib??
So, basically, I am still utterly confused about what I'm really supposed to do to set up libc++ properly. What, specifically, does clang actually do when you tell it -stdlib=libc++
?
Is it a hardcoded include path? I probably want to be building libc++abi and libc++ from svn to use along with the clang that has been built from svn. That makes the most sense... Then how should I go about installing it? Having to put -I~/libcxx/include/c++/v1/
(or whatever it would be) into a build config is inelegant.
Presumably I can just set up my llvm build to build clang along with libc++abi and libc++ by also checking out libcxxabi and libcxx from svn, and my expectation is that installing it ought to make -stdlib=libc++
magically work. Note also that the clang that Apple gives you with Xcode doesn't really require you to use -stdlib=libc++
. It just magically knows where to grab the library files.
However! The fly in the ointment, at least the only one so far that I know to look for: my machine already has a /usr/bin/clang++
:
$ ls -la $(which clang++)
-rwxr-xr-x 1 root wheel 14240 Mar 17 2014 /usr/bin/clang++
This is not a symlink to inside Xcode.app as I expected! I now have real concern about running make install
from my llvm build directory! It could probably break my Xcode environment or prevent my Mac from booting (as the libc++ llvm doc clearly states will happen if something bad happens to /usr/lib/libc++.1.dylib
)!
Hopefully there is not already documentation out there that I have missed that answers these questions, because I really should have found it by now.
Edit: I see in the sparse instructions found on http://libcxx.llvm.org that
clang++ -std=c++11 -stdlib=libc++ -nostdinc++ -I<path-to-libcxx>/include -L<path-to-libcxx>/lib test.cpp
might actually be the "proper way" right now. But what this fails at is explaining what -stdlib=libc++
causes clang to do, or what -nostdinc++
causes clang to do.
Edit 2: Thanks to @n.m. now we know that -nostdinc++
means no standard c++ include path searched. This means that standard include path is a thing. Is this path hardcoded when clang is built? I googled and found something referencing a variable CLANG_INCLUDEPATH
, this appears like possibly a makefile variable. Unfortunately I am running full filesystem text search over my llvm source dir and finding no matches to such a string (so it can't be a config used by clang or during the process of building clang).
Edit 3: With the aid of --verbose
, I can now see some helpful output:
Xcode's clang:
clang -cc1 version 5.1 based upon LLVM 3.4svn default target x86_64-apple-darwin13.4.0
ignoring nonexistent directory "/usr/include/c++/v1"
#include "..." search starts here:
#include <...> search starts here:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1
/usr/local/include
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/5.1/include
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
/usr/include
/System/Library/Frameworks (framework directory)
/Library/Frameworks (framework directory)
End of search list.
svn fresh clang:
clang -cc1 version 3.6.0 based upon LLVM 3.6.0svn default target x86_64-apple-darwin13.4.0
ignoring nonexistent directory "/Users/username/Documents/llvmbuild/Release+Asserts/bin/../include/c++/v1"
ignoring nonexistent directory "/usr/include/c++/v1"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/Users/username/Documents/llvmbuild/Release+Asserts/bin/../lib/clang/3.6.0/include
/usr/include
/System/Library/Frameworks (framework directory)
/Library/Frameworks (framework directory)
End of search list.
Okay, so this is painting a picture of a few places to deposit some libc++ files.
The presence of two "ignoring nonexistent directory" entries indicates to me that Xcode's clang is able to find a libc++ at its hardcoded /Apps/Xcode.app/.../c++/v1/
while my svn clang is not finding one at the place it wants to look (inside the Release+Asserts
build dir, which seems silly but it may actually be where libcxx copies its headers into by the llvm build system).
No hints on where it's fetching the libc++ dylibs from though. Not even when looking through the strings that are in the clang executables, using string
(which was a long shot anyway).
Not exactly crystal clear what exactly to do, but I do appear to sort of have the tools now to get going on my project. The main issue now is what's going on with the libc++.dylib
. I can't tell if the freshly built clang is hardcoded to find it at /usr/lib/libc++.1.dylib
, or what. I need to do this:
- Not touch
/usr/lib/libc++.1.dylib
so as not to break my entire operating system - Point freshly compiled
clang++
to use thelibc++.1.dylib
that's now been built, and is sitting in a different location than/usr/lib/libc++.1.dylib
. I don't care where it goes at this point, but I am NOT about to runmake install
which will likely overwrite/usr/lib/libc++.1.dylib
.
It's just not clear what makes sense to do. Does specifying -stdlib=libc++
cause clang++
to link the hardcoded /usr/lib/libc++.1.dylib
? If so, can I just drop it, and -l<compiled libc++.dylib>
explicitly? Otherwise, how do I compile clang in a way to modify this path to get it to use the right one?
For the time being I will use -stdlib=libc++ -nostdinc++
(see first edit) and pray that it actually means for clang to listen to the -I<new libc++ header path> -L<new libc++ dylib path>
. I guess if it still doesn't work and the system files get used anyway despite these efforts, I'll still be happy as long as my programs continue to compile...
I have gotten far enough to satisfactorily answer my own questions, so I will summarize my findings here.
This may not be the whole picture, but it paints enough to get me the information that I was having trouble finding.
Around about line 606 of tools/clang/lib/Driver/ToolChains.cpp
is code that just pushes -lc++
to the command arguments. This is in the toolchain implementation of clang (which is more or less part of the component(s) that let clang emulate the command line behavior of gcc, in order that it is compatible for building purposes).
What this means is that libc++.dylib/so gets loaded in using the exact same mechanism as all other libraries are. There is no special treatment for the C++ standard library. What this also means is that it is being done in a semi-hardcoded fashion. Perhaps this is not quite accurate, because I do expect that explicit library path specifications (-L
) can take precedence over default root paths.
At any rate, rather than try to tinker with -L
, there is a bigger hammer that can be used, --sysroot
. By installing libc++ to a separate location from the system's /usr/lib
, I can use --sysroot
with clang invocations to force clang to not even think about looking in /usr/lib
for libc++, or anything else, for that matter. This is something of a useful flag for e.g. cross-compiling jobs.
Okay, those are some ways to manipulate clang to do our bidding. Surely they are sufficiently powerful. Now I needed to be absolutely sure that the libc++ that I thought was being included and linked was actually being included and linked.
I went for something foolproof rather than something simple and clever. I made a few strategic edits to libc++ itself, and then installed it into an alternate directory (not /usr/lib
-- see my question for why i do not want to mess around with my system libc++): this can be pretty arbitrary, I added
std::libcxx_custom_version_type::libcxx_custom_version_type() {
libcxx_custom_version = "slu_libc++_svn_218071";
}
to src/typeinfo.cpp (in libc++) and correspondingly
struct libcxx_custom_version_type {
char* libcxx_custom_version;
libcxx_custom_version_type();
};
to include/typeinfo. The purpose this serves (yeah it's awful, oh well) is to make it unambiguously easy to verify that the libc++ I'm linking with is in fact the one I compiled from source. Indeed I can find the string slu_libc++_svn_218071
by using strings
on the libc++.dylib. A small amount of test code in a test c++ file can now easily show whether the libc++ being linked is the one I just compiled.
To do the same verification for the actual libc++ headers is much more trivial, we just need to define a new macro and check for it during a compile.
Now I have all the tools to use to answer my questions.
Well, Actually, right now I am getting this error so I can't quite build anything just yet.
Undefined symbols for architecture x86_64:
"std::terminate()", referenced from:
___clang_call_terminate in reflect-16fcd7.o
ld: symbol(s) not found for architecture x86_64
One step at a time, I guess...
这篇关于当运行clang从源代码构建时,如何指定libc ++的位置,或者有人向我解释什么-stdlib = libc ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!