什么是 clang/llvm/libc++
先说一下背景,以防有些同学对 clang/llvm/libc++ 是什么还没有概念:
clang 是最近几年(在大财主苹果的支持下)发展得非常好的 C 家族语言 (包括C/C++/Obj-C/Obj-C++) 编译器前端,所谓前端,就是它可以认识 C/C++/Obj-C/ObjC++ 代码,并且把它转化成某种更接近机器指令的形式。理论上说,“某种形式”是语法树,但作为一个工具,clang 实际上会帮助你调用链接器生成可执行代码,这跟 gcc 是一样的。
llvm 是一个通用的编译优化和代码生成平台,它定义了一个中间语言 LLVM IR,只要前端把代码编译成 LLVM IR,就可以使用 llvm 丰富的优化模块和代码生成模块。换句话说,llvm 让“创造一种计算机语言”变成了一个相对容易的事情,这件事情会有深远的影响。
libc++ 是针对 clang 特别重写的 C++ 标准库,也算是 clang 的“御用”库了。这就像 libstdc++ 和 gcc 的关系,但 clang 也可以用 libstdc++,这是本文的主题之一。
使用预编译的 clang
新鲜出炉的 clang/llvm 3.0 可以在这里下载,它提供了 Debian/FreeBSD9/MacOS X/Ubuntu 11.04, 11.10 的预编译二进制文件。假设你用的和我一样是版本足够的 Ubuntu ,那就只需要下载相应文件,展开,然后把文件拷到 /usr/local 底下就好了。例如下载的是 clang+llvm-3.0-i386-linux-Ubuntu-11_10.tar.gz ,则
tar xvf clang+llvm-3.0-i386-linux-Ubuntu-11_10.tar.gz
cd clang+llvm-3.0-i386-linux-Ubuntu-11_10
sudo cp -r * /usr/local
事实上这样就可以用了,即便没有 libcxx 也没关系,clang 可以使用 libstdc++ 。譬如一个经典的 hello.c (内容就不必多说了),用
clang hello.c
./a.out
应该就可以看到结果。
加上 libc++
如果想要用 libc++ ,需要拿下它的代码,自己编译,不过非常容易。首先保证你有 subversion:
sudo apt-get install subversion
然后从 libc++ 代码仓库下载代码:
svn co http://llvm.org/svn/llvm-project/libcxx/trunk libcxx
随后进入目录 libcxx 并编译
cd libcxx/lib
./buildit
编译没问题的话,会在 lib 目录下生成一个 libc++.so.1.0 文件,把它拷贝到 /usr/lib,并加上两个符号链接:
sudo cp ./libc++.so.1.0 /usr/lib
cd /usr/lib
sudo ln -sf libc++.so libc++.so.1.0
sudo ln -sf libc++.so.1 libc++.so.1.0
然后,由于 clang 认为 libc++ 头文件位于 /usr/include/c++/v1 底下,只需要把 libcxx/include 这个目录链接到该处就好了,换句话说,如果你
ls /usr/include/c++/v1
看到熟悉的 C++ 标准库头文件们,那就对了。
使用 clang++/libc++
clang 3.0 支持几个连 gcc 4.6 都没支持的 C++11 特性,比如初始化非静态类成员,看看下面的代码 (new_feature.cpp):
1 #include <iostream>
2 #include <string>
3
4 class MyClass
5 {
6 public:
7 std::string s = "Hello, world\n"; // Non-static data member initializer
8 };
9
10 int main()
11 {
12 std::cout << MyClass().s;
13 }
第7行直接在类声明处初始化一个 std::string 成员,这是原本只在 Java/C# 里面才能做的事情,如今终于飞入 C++ 程序中。编译命令:
clang++ --std=c++0x -stdlib=libc++ new_feature.cpp
./a.out
输出熟悉的
Hello, world
我们的 clang 就算正式能用了。