使用Clang构建V8并发出LLVM IR

8
我正在尝试使用Clang构建V8 JavaScript引擎并输出.ll文件。我正在尝试结合这里这里的信息来实现此目标。但是,当我尝试执行make时,它失败了,并显示“没有生成目标规则”。我很困惑。我已经尝试仅编译v8.cc,但完全失败了。我想这是因为我正在尝试通过将其作为编译器来强制使用-emit-llvm,但我不确定。
$ cd v8
$ export CXX="clang++ -S -emit-llvm"
$ export CC="clang -S -emit-llvm"
$ export CPP="clang -E -S -emit-llvm"
$ export LINK="clang++ -S -emit-llvm"
$ export CXX_host="clang++ -S -emit-llvm"
$ export CC_host="clang -S -emit-llvm"
$ export CPP_host="clang -E -S -emit-llvm"
$ export LINK_host="clang++ -S -emit-llvm"
$ export GYP_DEFINES="clang=1"
$ make native
PYTHONPATH="/home/pitaj/v8/tools/generate_shim_headers:/home/pitaj/v8/build::/home/pitaj/v8/build/gyp/pylib:" \
    GYP_GENERATORS=make \
    build/gyp/gyp --generator-output="out" build/all.gyp \
                  -Ibuild/standalone.gypi --depth=. -S.native  -Dv8_enable_backtrace=1 -Darm_fpu=default -Darm_float_abi=default
make[1]: Entering directory `/home/pitaj/v8/out'
  CXX(target) /home/pitaj/v8/out/native/obj.target/v8_base/src/accessors.o

...(更多CXX调用,完整输出此处)...

  CXX(target) /home/pitaj/v8/out/native/obj.target/v8_base/src/utils.o
make[1]: *** No rule to make target `/home/pitaj/v8/out/native/obj.target/v8_base/src/v8.o', needed by `/home/pitaj/v8/out/native/obj.target/tools/gyp/libv8_base.a'.  Stop.
make[1]: Leaving directory `/home/pitaj/v8/out'
make: *** [native] Error 2

编辑:

Makefile: http://pastebin.com/PsZrCkzE

编辑2:

以下内容可以无错误地构建v8,但显然不会发出任何IR。

$ cd v8
$ export CXX="clang++"
$ export CC="clang"
$ export CPP="clang -E"
$ export LINK="clang++"
$ export CXX_host="clang++"
$ export CC_host="clang"
$ export CPP_host="clang -E"
$ export LINK_host="clang++"
$ export GYP_DEFINES="clang=1"
$ make native

你能给我们指一下在线的 Makefile 吗? - shrm
据我所知,它使用gyp进行构建,因此Makefile可能没有什么帮助,但我会将其放在网上。http://pastebin.com/PsZrCkzE - PitaJ
1个回答

11

C和C++编译器通常有四个阶段:

  1. 预处理
  2. 将源代码编译成汇编代码
  3. 将汇编代码汇编为二进制目标文件
  4. 链接多个目标文件以生成一个可执行文件、共享库或静态库

在clang的情况下,第2阶段有点分裂:首先生成LLVM IR,然后将其汇编为目标体系结构的汇编代码。

clang和gcc都共享相同的命令行选项来控制将执行哪个阶段:

  • -E只运行预处理阶段
  • -S运行预处理和编译阶段,输出汇编文件
  • -c运行预处理、编译和汇编阶段,生成.o目标文件
  • 如果您不包括这些选项中的任何一个,则还会进行链接以生成可执行文件(或者根据其他选项的设置,生成静态库或共享库)。

-emit-llvm选项仅影响编译阶段,并且必须与-S选项一起使用。添加这些选项意味着当调用编译器时,它会生成一个包含LLVM IR的单个文件。默认的输出文件名将与输入文件名相同,但扩展名为.ll。

gyp工具实际上并不构建项目。相反,它会生成一组Makefile文件,这些文件执行实际构建。这些Makefile文件包含从一个文件类型生成另一个文件类型所需的规则。主要规则是:

  1. 从.cpp输入文件生成.o文件(对于每个.cpp文件,等同于上述1-3阶段)
  2. 从目标文件生成静态(.a)和/或动态(.so)库文件

您修改的环境变量会影响这些规则中使用的命令。具体而言,CXX变量指定用于上述第一个规则的命令。

还要注意的是,编译的Makefile规则将-o选项添加到命令中,覆盖输出文件名。因此,在使用您指定的CXX环境变量设置执行此规则时,实际上是在生成LLVM IR文件,但将其命名为.o而不是.ll。

问题出现在make进入下一个阶段并尝试从这些目标文件制作.a或.so文件时--因为它们实际上不是目标文件,而是LLVM IR文件。

但好消息是,根据您自己的问题,您只想要LLVM IR文件。到达失败时,已经生成了这些文件。唯一的问题是它们被命名为.o而不是.ll,但嘿,您可以轻松地将它们重命名。

如果您希望构建干净地进行到最后,可以通过将用于链接和归档的命令更改为“true”来抑制库文件的生成:

cd v8
export CXX="clang++ -S -emit-llvm"
export CC="clang -S -emit-llvm"
export CPP="clang -E"
export LINK="true"
export AR="true"
export CXX_host="clang++ -S -emit-llvm"
export CC_host="clang -S -emit-llvm"
export CPP_host="clang -E"
export LINK_host="true"
export AR_host="true"
export GYP_DEFINES="clang=1"
make native

就像我之前所说,编译结束后,你会得到与每个 .cpp 文件对应的一个 .o 文件 - 在编译时文件名将被打印出来。这些实际上是 LLVM IR 文件。你可以使用以下命令将它们重命名:

find out/native/obj.target/ -name "*.o" -exec rename .o .ll \{\} \;

编译成功了,但是重命名的东西没生效...很奇怪。 在(eval 1)第1行语法错误,附近有“。” - PitaJ
看起来你正在使用其他基于Perl的重命名命令 (http://man.he.net/man1/rename)。它需要不同的参数。尝试使用以下命令:`find out/native/obj.target/ -name "*.o" -exec rename 's/.o$/.ll/' {} ;`。 - harmic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接