GraalVM与Java静态编译:原理与应用
上QQ阅读APP看书,第一时间看更新

3.2 GraalVM编译系统工具mx

因为项目本身的复杂性和定制化程度较高,GraalVM项目组并没有使用诸如Ant、Maven、Gradle等现有的主流Java编译系统,而使用自己基于Python开发的命令行编译系统工具mx[1]

mx是一个通用的编译工具链,可以支持对任意Java项目的编译、测试、运行和升级。mx以套件(suite)的形式组织代码,在GraalVM中一个子项目就是一个套件,套件又由若干个项目(在Intellij中被视为模块)组成。一个套件的基本目录组织结构如代码清单3-1所示。

代码清单3-1 mx套件目录组织结构

[suite]
├── mx.[suite]
│  ├── mx_[suite].py
│  └── suite.py
└── src
   └── [project.name]
      └── src
         └── [package.name]
            └── Code.java

代码清单3-1中的[suite]指套件名,用于指代实际的项目名。在[suite]根目录下的mx.[suite]目录中放置套件的配置文件,我们将其称为套件元数据目录。该目录中的suite.py文件定义了套件的组成内容,包括项目名称、版本信息、子项目构成以及第三方依赖等具体内容,类似于Maven中pom.xml文件的作用,其基本结构为:

suite={
"mxversion":,
    "name":,
    "version":,
    "release":,
    "url":,
    "groupId":,
    "developer":{},
    "scm":
    "defaultLicense":,
    "versionConflictResolution":,
    "javac.lint.overrides":,
    "imports":{},
    "libraries":{},
    "projects":{},
    "distributions":{},
}

以上各项配置属性说明如下。

1)mxversion指当前套件依赖的mx工具的版本。

2)name指套件名,与当前套件所在的mx.[suite]目录中的[suite]保持一致。

3)version指项目的版本号。

4)imports指当前套件依赖的其他套件。

5)libraries指当前套件依赖的外部类库,需要给出它们的下载地址和校验的SHA值。

6)projects指套件包含的项目(模块),这是套件最重要的一部分内容,定义了项目的组成内容。其中由若干个项目的定义组成。下边展示的就是substratevm套件定义中的一个项目:

"com.oracle.svm.util": {
    "subDir": "src",
    "sourceDirs": ["src"],
    "dependencies": [
        "sdk:GRAAL_SDK",
        "compiler:GRAAL",
    ],
    "javaCompliance": "8+",
    "annotationProcessors": [
        "compiler:GRAAL_PROCESSOR",
    ],
    "checkstyle": "com.oracle.svm.core",
    "workingSets": "SVM",
},

对上述代码的主要内容说明如下。

① subDir指项目的目录对于套件根目录的相对地址,sourceDirs指项目的源码对于项目目录的相对地址。结合先前提到的套件的目录体系,[suite]/[subDir]/com.oracle.svm.util/[sourceDirs]/就是该项目的源码位置,代入实际的例子就是substratevm/src/com.oracle.svm.util/src/,也就是代码清单3-1中的src部分的结构。

② dependencies指当前项目依赖的内容。本例中形如sdk:GRAAL_SDK结构的值是指另一个套件sdk中的GRAAL_SDK产物(jar包),也可以是当前套件的其他项目,只需要直接写项目全名即可。

7)distributions指从当前套件的源码要编译出哪些jar包。

另一个Python文件mx_[suite].py定义了套件的编译过程,与suite.py共同定义了套件是什么,怎么编译的问题。图3-2展示了Substrate VM项目套件的元数据目录mx.substratevm,里面的mx_substratevm.py文件定义了编译Substrate VM的过程,suite.py定义了Substrate VM项目的具体组成结构、依赖的库文件等。

043-01

图3-2 substratevm目录结构

执行mx任务要指定一个主套件作为工作的入口,默认以当前目录为主套件,从当前目录里寻找套件元数据目录,当然也可以在其他任意位置通过mx的-p参数指定主套件的目录。mx的功能非常强大,是GraalVM开发者日常工作的必需品,对学习者来说,在基本了解mx的组织形式后,通常会在以下4个场景中用到mx。

1)为GraalVM项目生成IDE配置文件,以便在自己习惯的IDE中查看、编辑GraalVM代码,这部分内容会在3.3节介绍。

2)将GraalVM源码编译为成品,这是日常使用最多的方式,会在4.1.2节介绍。

3)作为持续集成工具执行代码规范检查和单元测试等操作。比如mx checkstyle可以启动checkstyle工具检查源码规范,mx eclipseformat可以自动按照Eclipse格式整理代码,mx gate则会启动CI测试。

4)项目升级。GraalVM项目的演进速度很快,项目主体升级后也往往需要更新的mx工具支持。如果mx工具不符合当前GraalVM项目的最低版本要求,在使用mx时会被提示需要对mx工具进行升级。一般只需执行mx update即可进行升级,但是如果用户修改过mx工具的代码,就需要按Git项目的管理方式更新项目。

其他mx功能不再一一介绍,读者可以通过执行mx help命令查看。


[1]参见https://github.com/GraalVM/mx