[折腾]编译 merlin compiler

背景:为了测试 HLS ,需要 merlin compiler 这个 VLS 编译器。这个库需要 gcc 4.9.4 llvm6 以及

零、阅读须知

⚠先弄好好gcc4.9.4然后开始后面llvmboostclang库的处理。 这是一个老项目了,不确定使用最新的库文件是否正常编译。且本教程最后只能编译得到编译器本身,附带的一些功能仍然编译失败。

一、gcc4.9.4

1、准备工作

从以下位置下带源代码。 一并下载编译gcc所需的依赖库。

1
2
3
wget ftp://ftp.gnu.org/gnu/gmp/gmp-4.3.2.tar.bz2 -o gmp.tar.bz2
wget https://www.mpfr.org/mpfr-3.1.0/mpfr-3.1.0.tar.bz2 -o mpfr.tar.bz2
wget https://ftp.gnu.org/gnu/mpc/mpc-1.0.1.tar.gz -o mpc.tar.gz

2、开始编译

进入gcc文件目录cd ./gcc.4.9.4,然后设定编译参数:

1
./configure --prefix=[使用本地目录即可]/gcc4  --enable-bootstrap  --enable-checking=release --enable-languages=c,c++
直接开始编译,建议开单线程,因为编译会出非常多的错误,单线程方便定位错误。
1
make -j 1

3、错误修复

这编译多是一件美事啊,编,TNND,为什么不编 因为现在系统环境上默认的 gcc 11.3 及其之后的版本默认带 c++17 标准,所以编译路上会有很多错误。 > ⚠注意以下解决方案中的 cd 路径需要根据实际情况自行修改,不可照抄

a、type bool in operator++ is forbidden in c++1789

原因:因为 C++17 标准不允许 bool 变量使用 ++ 操作符。

1
../.././gcc/reload1.c: In function ‘void init_reload()’:../.././gcc/reload1.c:89:24: error: use of an operand of type ‘bool’ in ‘operator++’ is forbidden in C++1789 |   (this_target_reload->x_spill_indirect_levels)|   ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
解决方案:
1
cd ./host-x86_64-unknown-linux-gnu/gcc
从编译日志找到错误的编译命令加上 -std=c++11 重新执行,然后回到上层目录重新 make -j 1 即可。

b、dereferencing pointer to incomplete type

原因:数据类型不匹配。

1
2
3
4
./md-unwind-support.h: 在函数'x86_64_fallback_frame_state'中:
./md-unwind-support.h:65:47: 错误: dereferencing pointer to incomplete type
sc = (struct sigcontext *) (void *) &uc_->uc_context;
make[3]: *** [../.././libgcc/shared-object.mk:14: unwind-dw2.o] 错误 1
类似的错误还有
1
2
3
./md-unwind-support.h: 在函数‘x86_fallback_frame_state’中:
./md-unwind-support.h:141:18: 错误: 字段‘uc’的类型不完全
struct ucontext uc;
解决方案
1
cd [path to gcc]/gcc4.9.4/x86_64-unknown-linux-gnu/libgcc
虽然报错是在第 65 行,但是我们需要修改第 61 行。
1
2
3
struct ucontext *uc_ = context->cfa
// 改成
struct ucontext_t *uc_ = context->cfa
对于第141行的错误则如下修改。
1
2
3
struct ucontext uc;
// 改成
struct ucontext_t uc;

c、Handler_stack未定义

原因不知道。

1
2
3
../../.././libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc: 在函数‘int __sanitizer::TracerThread(void*)’中:
../../.././libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc:241:22: 错误: 聚合‘sigaltstack handler_stack’类型不完全,无法被定义
struct sigaltstack handler_stack;
解决方案(参考llvm) - 打开 sanitizer_common/sanitizer_linux.h 去掉其中的 struct sigaltstack; 并把之后出现的两处 struct sigaltstack 换成 void 。 - 打开 sanitizer_common/sanitizer_linux.cc 文件出现的两处 struct sigaltstack 换成 void 。 - 打开 sanitizer_common/sanitizer_stoptheworld_linux_libcedep.ccstruct sigaltstack handler_stack; 换成 stack_t handler_stack 。 - 打开 tsan/rtl/tsan_platform_linux.cc 文件把 __res_state *statp = (__res_state*)state; 换成 struct __res_state *statp = (struct __res_state*) state;

d、SIGSEGV undefined

错误原因不知道。

1
2
3
../../.././libsanitizer/asan/asan_linux.cc: 在函数‘bool __asan::AsanInterceptsSignal(int)’中:
../../.././libsanitizer/asan/asan_linux.cc:107:20: 错误: ‘SIGSEGV’在此作用域中尚未声明
return signum == SIGSEGV && flags()->handle_segv;
解决方案 - 打开 libsanitizer/asan/asan_linux.cc 中添加头文件 #include <signal.h> 即可。

二、LLVM6.0.0

1、准备工作

从这个链接下载 llvm6 的源码。

2、开始编译

1
2
3
4
mkdir llvm-project-llvmorg-6.0.0/llvm/build
cd llvm-project-llvmorg-6.0.0/llvm/build
cmake -G "Unix Makefiles" -DLLVM_ENABLE_PROJECTS="clang" -DCMAKE_BUILD_TYPE=Release ../
make -j 1~~

然后不需要执行make install在build文件夹下会存在编译好的结果,把build文件夹放到merlin compiler/trunk/lib下即可。同时改名与merlin_setting.sh中的LLVM_ROOT_DIR变量一致。 这里就改名为 llvm6.0.0 。

三、Clang6.0.0

参考LLVM6那一节,已经下载好源代码了。llvm这个项目的特点是,所有的库都需要llvm-project-llvmorg-6.0.0/llvm为编译的起始点,通过设置不同的DLLVM_ENABLE_PROJECTS变量改变编译的对象,可选的对象是底下每一个文件夹。 ## 1、开始编译

1
2
3
4
5
mkdir llvm-project-llvmorg-6.0.0/build
cd llvm-project-llvmorg-6.0.0/build
cmake -G Ninja ../llvm -DLLVM_ENABLE_PROJECTS=clang -DLLVM_BUILD_TESTS=OFF -DLLVM_TARGETS_TO_BUILD="X86" -DBUILD_SHARED_LIBS=OFF
ninja
# clang 不明白为什么直接make找不到,得运行ninja指令

可以运行以下指令进行llvm编译结果测试,当然前面的-DLLVM_BUILD_TESTS=ON才行。

1
2
ninja check # Test LLVM Only
ninja clang-test # Test Clang Only
❌不需要执行make install,把build文件夹放到merlin compiler/trunk/lib下即可。同时改名与merlin_setting.sh中的LLVM_ROOT_DIR变量一致。 这里就改名为 llvm6.0.0

四、boost1.67.0

链接获得源码(记得解压),存放到merlin_compiler/trunk/source-opt/lib目录下,并修改bootstrap.shPREFIX变量如下(⚠要和merlin_setting.sh的设置一致)。

1
2
3
PREFIX=[path to merlin]/merlin_compiler/trunk/source-opt/lib/boost
# 要和下面的设置一致,这项设置来自于merlin_compiler的merlin_setting.sh
# export boost_path=$MERLIN_PATH/boost

然后,会自动在目录下生成b2bjam两个指令脚本,确保安装gcc和g++,一般不会有bug。

五、编译merlin_compiler主体

1、准备工作

在上面编译过程中多次修改 merlin_setting.sh 文件,这里干脆放出最终修改版本(TODO)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#######################################
# Merlin
#######################################
export MERLIN_COMPILER_HOME=/home/w/DSE/merlin-compiler/trunk

export MERLIN_PATH=$MERLIN_COMPILER_HOME/source-opt/lib
export llvm_path=$MERLIN_PATH/llvm6.0.0
export deps_path=$MERLIN_PATH/
export clang_path=$MERLIN_PATH/llvm6.0.0/bin
export rose_path=$MERLIN_PATH/rose
export rjson_path=$MERLIN_PATH/rapidjson
export gcc_path=$MERLIN_PATH/gcc4
export boost_path=$MERLIN_PATH/boost

export MERLIN_DEPS=$deps_path
export LLVM_ROOT_DIR=$llvm_path
export CLANG_ROOT_DIR=$llvm_path
export ROSE_ROOT_DIR=$rose_path
export RAPIDJSON_ROOT_DIR=$rjson_path
export GCC_ROOT_DIR=$gcc_path
export BOOST_ROOT=$boost_path

export PATH=$gcc_path/bin/:$PATH
export PATH=$llvm_path/bin/:$PATH

#lib32 if lib64 is not available
export LD_LIBRARY_PATH=$gcc_path/lib64:$llvm_path/lib:$LD_LIBRARY_PATH
export LIBRARY_PATH=$llvm_path/lib

export PATH=$MERLIN_COMPILER_HOME/build/bin:$PATH
在上面的所有准备工作都好了以后,回到merlin_compiler主文件夹下,执行:
1
2
3
4
5
6
source ./merlin_setting.sh
mkdir trunk/build
cd trunk/build
# 我也是绷不住了,默认 python3 执行会报错,只好指定 python2
cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=/usr/bin/python2 ..
make -j 1

2、错误修复

a、GLIBCXX_3.4.22 not found

问题原因:gcc4.9.4自带的libstdc++版本太老(我是真不明白,为什么merlin指定编译环境4.9.4,又出现libstdc++版本不够的问题,只能认为写merlin时的服务器很老很老)。

1
2
3
4
5
6
$ make -j 1
/usr/bin/cmake: /home/w/DSE/merlin-compiler/trunk/source-opt/lib/gcc4/lib64/libstdc++.so.6: version `GLIBCXX_3.4.22' not found (required by /usr/bin/cmake)
/usr/bin/cmake: /home/w/DSE/merlin-compiler/trunk/source-opt/lib/gcc4/lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by /usr/bin/cmake)
/usr/bin/cmake: /home/w/DSE/merlin-compiler/trunk/source-opt/lib/gcc4/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by /usr/bin/cmake)
Makefile:1783: recipe for target 'cmake_check_build_system' failed
make: *** [cmake_check_build_system] Error 1
解决方案: 从其他地方借一个libstdc++就好,比如我从/usr/lib/gcc环境(即服务器上的高版本gcc)中借一个。在借之前先保存原版,然后搜索本地的高版本gcc中的libstdc++的文件位置替换gcc4.9.4libstdc++文件。
1
2
3
4
5
6
mv libstdc++.so.6.0.20 libstdc++.so.6.0.20.old
mv libstdc++.so.6 libstdc++.so.6.old
mv libstdc++.so libstdc++.so.old
# 这里就偷懒搜一个,一般在 /usr/lib/x86_64-linux-gnu 目录下会有
sudo find /usr/lib -name libstdc++*
cp /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.29 [path to merlin]/merlin_compiler/trunk/source-opt/gcc4/lib64
最后重新建立软连接
1
2
ln -s libstdc++.so.6.0.29 libstdc++.so
ln -s libstdc++.so.6.0.29 libstdc++.so.6

b、MDiag::emitDiagnosticLoc() marked override, but does not override

问题原因:子类标记为override,但是父类没有标记为override。不过实际检查报错的位置发现clang对应位置是有override标记的,推测编译merlin时指定的clang位置有错误。

1
2
/home/w/DSE/merlin-compiler/trunk/mars-gen/tools/mcheck/mdiag.h:60:8: 错误: ‘void MDiag::emitDiagnosticLoc(clang::FullSourceLoc, clang::PresumedLoc, clang::DiagnosticsEngine::Level, llvm::ArrayRef<clang::CharSourceRange>)’ marked override, but does not override
void emitDiagnosticLoc(clang::FullSourceLoc, clang::PresumedLoc,

解决方案:打开merlin_compiler/trunk/mars-gen/tools/mcheck/mdiag.h去掉其中 62、63 行的 override

c、mcheck mrefactor undfeind

问题原因:clang库中确实没有这些定义,不知道是版本问题还是代码bug。错误类似下面这种:

1
2
using clang::ast_matchers::cxxNewExpr; Undefined
using clang::ast_matchers::cxxOperatorCallExpr; Undefined
⚠比较取巧的解决方案是打开merlin-compiler/trunk/mars-gen/tools/mcheck/CMakeLists.txt文件去掉以下两行(为什么取巧呢,这是因为这两个模块是工具,不确定这样编译出的merlincc是否正常工作,寄希望于这两个工具不影响正常编译不大)。
1
2
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/mcheck")
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/mrefactor")

d、/usr/bin/ld -lrose

问题原因:找不到库文件位置(经典错误了。

1
/usr/bin/ld:/home/w/DSE/merlin-compiler/trunk/source-opt/lib/rose/lib/librose.so: file format not recognized; treating as linker script
从git上下载的文件因为丢失链接位置信息,而自己编译的librose.so没有链接指向它。这里删除然后重新建立软链接即可。随即又冒出另一个问题(不是哥们,那之前找到的librose.so算什么?)。
1
2
/usr/bin/ld: 找不到 -lrose
clang: error: linker command failed with exit code 1 (use -v to see invocation)
解决方法:重新创建一个指向librose.so的软连接。
1
2
3
4
5
6
7
cd merlin-compiler/trunk/source-opt/lib/rose/lib
rm librose.so
ln -s librose.so.0.0.0 librose.so
# 然后拷贝到 /usr/bin 目录下新建一个软连接,这一步需要 sudo 权限
sudo cp librose.so.0.0.0 /usr/lib
cd /usr/lib
sudo ln -s librose.so.0.0.0 librose.so
这里也见到另一种解决方案,就是通过apt命令安装这个库。不过没有尝试。

六、见证曙光

经过三天鏖战,走了一堆弯路之后,终于见到如下的输出。(应该是好了吧

1
2
3
4
5
6
7
8
9
10
11
12
[ 92%] Built target DsBitwidthOpt
[ 92%] Built target set_cfg
[ 93%] Built target DsTiling
[ 94%] Built target DsScope
[ 95%] Built target DsLoopParallel
[ 96%] Built target DsSkeletonExtract
[ 97%] Built target DsResourceEval
[ 98%] Built target DsPipeline
[ 99%] Built target LoopParallel
[100%] Linking CXX executable ../../../bin/mars_opt_org
[100%] Built target mars_opt_org
(base) w@HAS-T640:~/DSE/merlin-compiler/trunk/build$
怀着激动的小手~
1
2
3
4
5
6
7
8
9
10
11
12
13
(base) w@HAS-T640:~/DSE/merlin-compiler/trunk/build$ merlincc -h
Smartmatch is experimental at /home/w/DSE/merlin-compiler/trunk//mars-gen/scripts/lib/message.pm line 392.


Usage: merlincc <options> <filename>.< c|cpp|mco >

Options:
-v, --version
Display compiler version

--list-platform
Display supported platforms
...
终于,c++的高层次综合功能是能用了。


[折腾]编译 merlin compiler
http://example.com/2024/11/15/折腾/折腾-编译-merlin-compiler/
Author
peach-water
Posted on
November 15, 2024
Licensed under