1. 概述
Pants 是一个支持多语言的构建工具。它速度快、可扩展性强、使用友好,适合各种规模的代码库,尤其适合包含多种编程语言的多语言项目(polyglot 项目)。
在本教程中,我们将学习如何配置 Pants、定义 BUILD 文件、添加依赖、测试等内容,全部以 Java 为例进行说明。
2. Pants 构建工具简介
构建工具是自动化软件开发流程的关键组件。在 Java 生态中,Maven 和 Gradle 是非常流行的构建工具。但在面对大型多语言代码库时,它们可能会显得力不从心。
Pants 提供了构建系统所需的基本功能,包括测试运行器、代码生成器、编译器、依赖解析器、打包工具等。
它非常适合单一代码库中包含多个项目的场景,尤其是这些项目使用不同编程语言编写的情况,也就是常说的 monorepo 架构。
目前,Pants 支持 Python、Go、Java、Scala 和 Shell,未来还会支持更多语言。
3. 初始配置
安装好 Pants 的二进制文件后,项目配置非常简单。它支持 Windows、Linux 和 macOS。
要创建一个 Java 项目,我们首先创建一个项目目录:
$ mkdir hello-pant
进入该目录,创建 pants.toml 文件,并添加 Java 后端支持:
[GLOBAL]
backend_packages = [
"pants.backend.experimental.java",
]
这里我们告诉 Pants,这是一个 Java 项目。由于 Pants 擅长处理 monorepo 项目,我们可以配置其支持多种语言:
[GLOBAL]
backend_packages = [
"pants.backend.experimental.java",
"pants.backend.experimental.scala",
]
上面的配置启用了 Java 和 Scala 的支持。
接下来,我们需要为项目创建目录结构。在根目录下创建 src 目录存放源代码:
$ mkdir -p src/com/baeldung/hellopant
再创建一个 test 目录用于存放单元测试:
$ mkdir -p test/com/baeldung/hellopant
4. 编译代码
Pants 可以轻松编译代码并生成 JAR 文件。本节我们将介绍如何使用 Pants 编译代码、运行测试以及打包为 JAR。
4.1. 生成 BUILD 文件
前面我们创建了 Java 项目的目录结构。现在在 src 目录下添加一个 Hello.java 文件:
public class Hello {
public static void main(String [] args) {
System.out.println ("Hello World!");
}
}
这段代码是最经典的 “Hello World!” 示例。
为了让 Pants 能够识别并编译代码,我们需要生成 BUILD 文件。执行以下命令:
$ pants tailor ::
该命令会在每个包含代码的目录中生成 java_sources target,在测试目录中生成 junit_tests target:
Created src/com/baeldung/hellopant/BUILD:
- Add java_sources target hellopant
Created test/com/baeldung/hellopant/BUILD:
- Add junit_tests target tests
⚠️ 没有 BUILD 文件,代码将无法编译。
测试目录下的 BUILD 文件内容如下:
junit_tests(
name="tests",
)
源码目录下的 BUILD 文件内容如下:
java_sources(
)
此外,我们还需要生成锁文件以设置默认的 JVM 并管理第三方依赖:
$ pants generate-lockfiles
该命令会在项目根目录下生成一个 default.lock 文件和一个 jvm 子目录。
最后,我们执行代码:
pants run src/com/baeldung/hellopant/Hello.java
输出结果为:
Hello World!
4.2. 添加第三方依赖
添加第三方依赖需要修改 default.lock 文件并定义依赖信息。我们以添加 Guava 为例。
首先修改 default.lock 文件内容:
# {
# "version": 1,
# "generated_with_requirements": [
# "com.google.guava:guava:18.0,url=not_provided,jar=not_provided",
# ]
# }
然后在 jvm 目录下创建对应的目录结构:
$ mkdir -p com/google/guava
接着创建 BUILD 文件定义 Guava 的 artifact 信息:
jvm_artifact(
group="com.google.guava",
artifact="guava",
version="32.1.1-jre",
)
注意目录结构应与 artifact 的 group 名称一致。其他以 com 开头的依赖也应放在 com 目录下。
例如,添加 Jackson Core:
$ mkdir -p com/fasterxml/jackson/core
然后添加对应的 BUILD 文件即可。
最后执行:
$ pants generate-lockfiles
该命令会根据 default.lock 文件下载对应的依赖。
4.3. 运行测试
我们可以添加 JUnit 依赖来运行单元测试。更新 default.lock 文件:
# "generated_with_requirements": [
# "junit:junit:4.13.2,url=not_provided,jar=not_provided",
# ]
创建目录结构:
$ mkdir -p junit/junit
创建 BUILD 文件:
jvm_artifact(
group="junit",
artifact="junit",
version="4.13.2"
)
执行:
$ pants generate-lockfiles
接下来编写一个测试类:
class GuavaUnitTest {
@Test
void whenConvertListToStringAndSkipNull_thenConverted() {
List<String> names = Lists.newArrayList("John", null, "Jane", "Adam", "Tom");
final String result = Joiner.on(",")
.skipNulls()
.join(names);
assertEquals(result, "John,Jane,Adam,Tom");
}
}
运行测试:
$ pants test test/com/baeldung/hellopant/GuavaUnitTest.java
✅ 测试成功时,控制台会输出类似如下信息(截图略):
4.4. 资源文件处理
我们可以将资源文件放在 resources 目录中。例如:
$ mkdir -p resource/com/baeldung/hellopant
创建一个 word.txt 文件,内容为:
from Us
创建 BUILD 文件:
resources(name = "word", sources=["word.txt"])
编写测试类读取资源文件:
@Test
public void whenGettingTextFromAResourceFile_thenJoined() throws IOException {
String world = Resources.toString(Resources.getResource(GuavaUnitTest.class, "word.txt"), Charsets.UTF_8).strip();
String result = Joiner.on(" ").join("Hello", world);
assertEquals(result, "Hello from Us");
}
在测试的 BUILD 文件中添加依赖:
junit_tests(
name="tests",
dependencies=[
"src/resources/com/baeldung/hellopant:word",
],
)
✅ 这样测试就能成功读取资源文件。
4.5. 打包为 JAR
打包为 JAR 文件非常简单。首先在 src 目录下的 BUILD 文件中定义目标:
java_sources()
deploy_jar(
name="HelloPant",
main="com.baeldung.hellopant",
dependencies=[
":hellopant",
],
)
执行打包命令:
$ pants package ::
成功后会在项目根目录下生成 dist 文件夹,里面包含 JAR 文件:
5. 与 IDE 集成
Pants 可以通过 Build Server Protocol (BSP) 加载到 IntelliJ IDEA 中。默认情况下,IntelliJ 不支持 BSP,需要安装 Scala 插件。
创建 bsp-groups.toml 文件:
[groups.default]
addresses = [
"src/jvm::",
"tests/jvm::",
]
resolve = "jvm:jvm-default"
更新 pants.toml 文件:
[experimental-bsp]
groups_config_files = ["bsp-groups.toml"]
最后导入项目到 IntelliJ,Pants 会启动 BSP 服务并与 IntelliJ 同步模块信息。
6. 其他功能
Pants 提供了丰富的功能,包括代码格式化、测试超时设置、指定 JDK 版本等。
6.1. 代码格式化与检查
Pants 支持 Google Java Format。启用方式如下:
[GLOBAL]
backend_packages = [
"pants.backend.experimental.java",
"pants.backend.experimental.java.lint.google_java_format"
]
格式化代码:
$ pants fmt test/com::
检查格式:
$ pants lint ::
6.2. 设置测试超时
可以在 BUILD 文件中设置测试超时时间:
junit_tests(
name="tests",
timeout=120,
)
也可以在 pants.toml 中设置默认值和最大值:
[test]
timeout_default = 60
timeout_maximum = 120
调试时可禁用超时:
$ pants test --no-timeouts
6.3. 指定 JDK 版本
在 pants.toml 中设置 JDK 版本:
[jvm]
jdk = 1.8
若未指定,Pants 会使用主机默认的 JDK。
7. 总结
在本文中,我们了解了 Pants 构建工具的基本功能,并通过 Java 示例展示了其使用方法。我们还介绍了如何与 IDE 集成,以及一些高级功能如代码格式化、测试超时设置和 JDK 版本指定。
Pants 是 monorepo 架构项目的理想选择,尤其适合多语言项目。
如需查看完整示例代码,请访问 GitHub 仓库。