当运行从源构建的clang时,如何指定libc ++的位置,或者,有人向我解释-stdlib = libc ++是什么

Ste*_* Lu 8 c++ macos clang

我正在使用clang的规定开发插件和工具,通过插件和clang的LibTooling来实现.我能做以下事情:

  • 通过运行configure脚本(不使用cmake)按照入门页面编译来自svn(Linux和OSX)的clang里面的llvm
  • 在Linux上编译libcxx/libc ++(也来自svn),我没理由在OSX上遇到任何麻烦.问题是libc ++头文件已存在于我的OSX系统上

    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1/
    
    Run Code Online (Sandbox Code Playgroud)

    并且libc ++ dylib位于/ usr/lib /.

    编辑4:我能够按照指示在OS X上编译libcxx.我有一个全新的libc ++.1.0.dylib现在坐在这里.

  • 在OSX上,使用Release + Asserts(和Debug + Asserts)构建clang++来编译C++源代码,方法是附加

    -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1/
    
    Run Code Online (Sandbox Code Playgroud)

    并且不使用-stdlib=libc++.使用此标志将libc ++显式指定为include目录允许我构建的clang"看到"标准c ++标头.令人惊讶的是,它在编译一个适度基本的源文件时仍然很满意(它仍然在其中运行了大量的c ++ 11疯狂)

基于此,您可以看到我正在修改我刚刚构建的clang version 3.6.0 (trunk 217905)用于查找Apple的Xcode打包的libc ++.这表面上看起来很有效,因为Apple的libc ++与Xcode一起提供的ABI兼容我刚从源代码构建的编译器.对我来说仍然很好奇的是我的新编译的clang能够找出在哪里找到相应的libc ++ dylib!这引发了后来我实际上编译libc ++时的问题,我该如何告诉我的新svn编译的clang查找并使用新的svn编译的libc ++ dylib?

所以,基本上,我还是心乱如麻什么,我真的应该做成立的libc ++正常.具体来说,当你说出来时clang 实际上做了什么-stdlib=libc++

它是一个硬编码的包含路径吗?我可能想要从svn构建libc ++ abi和libc ++以与从svn构建的clang一起使用.这是最有意义的...然后我该如何安装呢?必须将-I~/libcxx/include/c++/v1/(或任何它可能的)放入构建配置是不优雅的.

据推测,我可以设置我的llvm构建来构建clang以及libc ++ abi和libc ++,同时从svn中查看libcxxabi和libcxx,我的期望是安装它应该-stdlib=libc++神奇地工作.另请注意,Apple为您提供Xcode的铿锵声并不需要您使用-stdlib=libc++.它只是神奇地知道在哪里抓取库文件.

然而!美中不足,至少是迄今为止我所知道的唯一一个:我的机器已经有了/usr/bin/clang++:

$ ls -la $(which clang++)
-rwxr-xr-x  1 root  wheel  14240 Mar 17  2014 /usr/bin/clang++
Run Code Online (Sandbox Code Playgroud)

这不是我预期的Xcode.app里面的符号链接!我现在真的担心make install从我的llvm构建目录运行!它可能会破坏我的Xcode环境或阻止我的Mac启动(因为libc ++ llvm doc明确说明如果发生了不好的事情就会发生/usr/lib/libc++.1.dylib)!

希望那里没有我已经错过的文档可以回答这些问题,因为我现在应该已经找到它了.

编辑:我在http://libcxx.llvm.org上找到的稀疏指令中看到了

clang++ -std=c++11 -stdlib=libc++ -nostdinc++ -I<path-to-libcxx>/include -L<path-to-libcxx>/lib test.cpp
Run Code Online (Sandbox Code Playgroud)

实际上可能是现在的"正确方式".但是失败的-stdlib=libc++ 原因在于解释导致clang做什么的-nostdinc++ 原因,或者是什么原因导致clang要做.

编辑2:感谢@nm现在我们知道这-nostdinc++意味着没有标准的c ++包含搜索路径.这意味着标准包含路径是一件事.当clang建成时,这条路径是硬编码的吗?我用Google搜索并找到引用变量的内容CLANG_INCLUDEPATH,这看起来可能是一个makefile变量.不幸的是,我在我的llvm源目录上运行完整的文件系统文本搜索,并且找不到与这样的字符串匹配(因此它不能是clang使用的配置或在构建clang的过程中).

编辑3:借助于--verbose,我现在可以看到一些有用的输出:

Xcode的铿锵声:

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.
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

好的,所以这是绘制几个地方的图片来存放一些libc ++文件.

两个"忽略不存在的目录"条目的存在向我表明,Xcode的clang能够在其硬编码/Apps/Xcode.app/.../c++/v1/时找到一个libc ++,而我的svn clang却没有在它想要查看的地方找到一个(在Release+Asserts构建目录内,这似乎很傻但是它实际上可能是libcxx通过llvm构建系统将其头文件复制到的地方).

虽然没有关于从哪里获取libc ++ dylibs的提示.即使在查看clang可执行文件中的字符串时也没有使用string(无论如何都是长镜头).

不完全清楚究竟要做什么,但我现在似乎有点工具来开始我的项目.现在的主要问题是正在发生的事情libc++.dylib.我不知道新建的铿锵是不是硬编码才能找到它/usr/lib/libc++.1.dylib,或者是什么.我需要这样做:

  1. 不要触摸,/usr/lib/libc++.1.dylib以免破坏我的整个操作系统
  2. 点新编译clang++使用libc++.1.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++(参见第一次编辑)并祈祷它实际上意味着让铿锵听-I<new libc++ header path> -L<new libc++ dylib path>.我想如果它仍然不起作用并且尽管有这些努力仍然使用系统文件,只要我的程序继续编译,我仍然会很高兴...

Ste*_* Lu 4

我已经足够满意地回答我自己的问题了,所以我将在这里总结我的发现。

这可能不是全部,但它足以让我找到我难以找到的信息。

大约第 606 行左右tools/clang/lib/Driver/ToolChains.cpp是仅推-lc++送到命令参数的代码。这是在 clang 的工具链实现中(它或多或少是让 clang 模拟 gcc 命令行行为的组件的一部分,以便它与构建目的兼容)。

这意味着 libc++.dylib/so 使用与所有其他库完全相同的机制加载。C++ 标准库没有特殊处理。这也意味着它是以半硬编码的方式完成的。也许这不太准确,因为我确实希望显式库路径规范(-L)可以优先于默认根路径。

无论如何,与其尝试修补-L,不如使用更大的锤子,--sysroot。通过将 libc++ 安装到与系统不同的位置/usr/lib,我可以使用--sysrootclang 调用来强制 clang 甚至不考虑查找/usr/liblibc++ 或其他任何内容。对于交叉编译作业来说,这是一个有用的标志。

好的,这些是操纵 clang 执行我们命令的一些方法。当然,他们的实力也足够强大。现在我需要绝对确定我认为被包含和链接的 libc++ 实际上被包含和链接。

我追求的是万无一失的东西,而不是简单而聪明的东西。我对 libc++ 本身进行了一些策略性编辑,然后将其安装到另一个目录中(不是/usr/lib——请参阅我的问题,了解为什么我不想搞乱我的系统 libc++):我补充说,这可以是相当任意的

std::libcxx_custom_version_type::libcxx_custom_version_type() {
  libcxx_custom_version = "slu_libc++_svn_218071";
}
Run Code Online (Sandbox Code Playgroud)

到 src/typeinfo.cpp (在 libc++ 中)并相应地

struct libcxx_custom_version_type {
    char* libcxx_custom_version;
    libcxx_custom_version_type();
};
Run Code Online (Sandbox Code Playgroud)

包含/输入信息。这样做的目的(是的,这很糟糕,哦,好吧)是为了明确地轻松验证我链接的 libc++ 实际上是我从源代码编译的。slu_libc++_svn_218071事实上,我可以通过strings在 libc++.dylib 上使用来找到该字符串。现在,测试 C++ 文件中的少量测试代码可以轻松显示正在链接的 libc++ 是否是我刚刚编译的。

要对实际的 libc++ 头文件进行相同的验证要简单得多,我们只需要定义一个新的宏并在编译期间检查它。

现在我拥有了可以用来回答我的问题的所有工具。

好吧,实际上,现在我收到了这个错误,所以我还不能完全构建任何东西。

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
Run Code Online (Sandbox Code Playgroud)

一步一步来,我想...