编译原理 H 实验环境配置

本课程推荐的实验环境有两种:

  • Linux
  • Mac with Homebrew installed

Linux 和 Mac 都是不错的 POSIX 环境,也都各自有好用的包管理器、便利的图形化环境。

1. 基本的编译执行环境

为了编译实验代码,你需要安装以下软件:

1.1. 依赖软件的安装

在 Linux 的发行版上安装这些软件会十分简单,例如, 在 Ubuntu 下,运行如下命令即可:

sudo apt install cmake g++ openjdk-8-jdk pkg-config uuid-dev

在 Mac 下,你需要使用 clang 作为编译器(随 XCode 安装),单独安装 JVM,然后从 Homebrew 安装其余包:

brew install cmake pkg-config ossp-uuid antlr4-cpp-runtime

1.2. CMake 的使用

CMake 根据内置的规则和语法来自动生成相关的Makefile 文件进行编译,同时还支持静态库和动态库的构建等。通过 CMake 管理的项目主目录下会有一个 CMakeLists.txt ,其中会包括工程包含哪些子目录等内容;而在每个子目录下,也会包含一个 CMakeLists.txt,用来管理该子目录中相关内容的构建。

编译

编译的时候,可以建立单独的文件夹(如build),让编译产生的文件和源代码区分出来,以下是一种常用的编译方式, 当前目录为项目源代码目录:

$ mkdir build
$ cd build
$ cmake ..
$ make

编写CMakeLists.txt

在 CMakeLists.txt 中,可以包含如下一些内容:

cmake_minimum_required(VERSION 3.1)  # CMake 版本要求
PROJECT(hello)                       # 项目名称

set(CMAKE_CXX_STANDARD 14)           # 设置编译器遵循的C++标准

set(CMAKE_CXX_FLAGS “-O2 -g”)        # 自定义编译选项

假设 args 代表通过空格或换行分隔的多个参数,你可以

  • 通过 include_directories(args) 来添加外部库的头文件所在的一组目录 args 作为头文件查找目录;
  • 通过 link_directories(args) 来添加外部链接库的查找目录;
  • 通过 link_libraries(args) 来添加链接的外部库;
  • 通过 target_link_libraries(hello args) 来设置生成的可执行目标及其要链接的库
  • 通过 add_library(mylib STATIC ${SRC}) 来创建静态库libmylib.a; 如果 STATIC 换成 SHARED,则为创建动态库 libmylib.so;
  • 通过 add_executable(hello ${SRC}) 来创建可执行文件 hello

你可以使用内置宏 CMAKE_CURRENT_SOURCE_DIR 来获取当前CMakeLists.txt 所在目录,例如 ${CMAKE_CURRENT_SOURCE_DIR}/..表示CMakeLists.txt 所在目录的上一级目录。

2. ANTLR

ANTLR (ANother Tool for Language Recognition)是一个强大的解析器的生成器。在课程实验中,你将利用 ANTLR 工具读入描述要解析的语言词法和语法的文法文件(扩展名是 .g4), 生成解析器的源码。ANTLR v4 使用 Java 实现,但是生成的解析器源码可以是 Java、C++、C#、Go、JavaScript、Swift等。

2.1. 依赖环境准备

ANTLR 工具需要 JVM 才能执行;另一方面,为了方便使用 grun,你需要一个能够编译 java 源文件的环境。因此,你需要一个完整的 Java Development Kit。

  • 如果你使用 Linux:

    推荐通过包管理器安装 OpenJDK 8。在你的包管理器中通过搜索确定包名,如 Ubuntu 下包名为openjdk-8-jdk, 安装之即可。

  • 如果你使用 Mac:

    你需要手动安装一个 JDK。

2.2. 获取 ANTLR

你需要从 ANTLR Download 下载 antlr-4.7.1-complete.jar

然后,你需要将该jar包的路径加入到环境变量 CLASSPATH 中,即 Bash 中执行

export CLASSPATH=".:/path/to/your/antlr-4.7.1-complete.jar:$CLASSPATH"

你可以考虑将这一命令加入.bashrc(对于Bash),以省去你每次配置的麻烦。

2.3. antlr4 和 grun 工具

可以定义别名 antlr4 表示 ANTLR 工具,即

alias antlr4='java org.antlr.v4.Tool'

这样,你可以直接使用 antlr4 your.g4 来为your.g4 生成解析器源码。

ANTLR 的运行时库中还提供了一个灵活的测试工具 TestRig,它可以显示解析器如何匹配输入的许多相关信息。TestRig使用Java的反射机制来调用编译过的解析器。为了方便用户使用,ANTLR 提供了一个 grun 工具来使用 TestRig

grun 本质上是一个别名,可以定义如下:

alias grun='java org.antlr.v4.runtime.misc.TestRig'

alias grun='java org.antlr.v4.gui.TestRig'

同样的,你可以将这些别名命令加入到.bashrc,以节省你配置和使用的时间。

3. LLVM 配置

由于 Ubuntu 源中 LLVM 的打包错误、以及此后对 Clang 和 LLVM 的实验需要,这里推荐同学们自行编译 LLVM。

3.1. 获取 LLVM

这里将在当前目录下建立一个名为llvm的目录,其中包含了 LLVM 和 Clang。

wget http://releases.llvm.org/6.0.1/llvm-6.0.1.src.tar.xz
wget http://releases.llvm.org/6.0.1/cfe-6.0.1.src.tar.xz
tar xvf llvm-6.0.1.src.tar.xz
mv llvm-6.0.1-src llvm
tar xvf cfe-6.0.1.src.tar.xz
mv cfe-6.0.1.src llvm/tools/clang

3.2. 编译并安装

这里将在当前目录下建立一个名为llvm-build的目录(和llvm同级),用于构建 LLVM 和 Clang,并将安装目录配置为和这两个目录同级的llvm-install目录。

mkdir llvm-build && cd llvm-build
cmake ../llvm -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=`cd .. && pwd`/llvm-install
make -j install

推荐考虑使用make -jn,其中将n替换为你的 CPU 逻辑处理器数目减一。例如,在 i5-7287U 上,使用make -j3,编译时间可能不到一个小时。而如果使用单线程,那么编译时间可能超过两个小时。这段时间里你可能需要玩一会儿手机或者去冲一杯咖啡,当然复习一下编译的知识、看一下 LALR 是个不错的选择。

请注意,为了避免你的内存爆炸,这里使用了 Release 配置。这一配置下,链接时无需处理调试符号,内存占用大幅度降低。考虑到同学们不会有 Debug 进入 LLVM 中的需求,Release 配置已经足够使用。

但是,我们强烈建议你使用 Debug 配置进行编译。一方面是让你体验一下比较大的工程的编译过程,另一方面在这个过程里面会有一点点奇怪又好玩的问题出现,强烈安利!前两年课程的llvm编译,用的不是新版的llvm 6,所以编译的时候大家都遇到了一些很多好玩的问题,得到了刺激的体验!内存占用峰值也超过了12GB。所以真的强烈安利!内存不大的同学也可以尝试一下,看看会有什么有趣的问题,理解一下编译过程、链接过程的各种优化的必要性!

results matching ""

    No results matching ""