Overview
Pants's support for Java and Scala.
We are done implementing most functionality for Pants's Java and Scala support (tracked here). However, there may be use cases that we aren't yet handling.
Please share feedback for what you need to use Pants with your JVM project by either opening a GitHub issue or joining our Slack!
Check out github.com/pantsbuild/example-jvm to try out Pants's Java and Scala support.
Initial setup
First, activate the relevant backends in pants.toml
:
[GLOBAL]
backend_packages = [
# Each backend can be used independently, so there is no need to enable Scala if you
# have a pure-Java repository (or vice versa).
"pants.backend.experimental.java",
"pants.backend.experimental.scala",
]
Then run ./pants tailor
to generate BUILD files. This will create java_sources
and scala_sources
targets in every directory containing library code, as well as test targets like scalatest_tests
and junit_tests
for filenames that look like tests.
❯ ./pants tailor
Created src/jvm/org/pantsbuild/example/app/BUILD:
- Add scala_sources target app
Created src/jvm/org/pantsbuild/example/lib/BUILD:
- Add java_sources target lib
Created tests/jvm/org/pantsbuild/example/lib/BUILD:
- Add scalatest_tests target lib
You can run ./pants list ::
to see all targets in your project:
❯ ./pants list
...
src/jvm/org/pantsbuild/example/app:app
src/jvm/org/pantsbuild/example/app/ExampleApp.scala
src/jvm/org/pantsbuild/example/lib:lib
src/jvm/org/pantsbuild/example/lib/ExampleLib.java
tests/jvm/org/pantsbuild/example/lib:lib
tests/jvm/org/pantsbuild/example/lib/ExampleLibSpec.scala
Firstparty dependencies
In many cases, the dependencies of your firstparty code are automatically inferred via dependency inference based on your import
statements. If you do need to declare additional dependencies for any reason, you can do so using Pants' syntax for declaring dependencies for targets.
Thirdparty dependencies and lockfiles
Thirdparty dependencies (i.e. those from repositories like Maven central) are also automatically inferred via dependency inference, but must first be declared once per repository as jvm_artifact
targets:
jvm_artifact(
group="com.google.guava",
artifact="guava",
version="31.0.1-jre",
# See the callout below for more information on the `packages` argument.
packages=["com.google.common.**"],
)
Pants requires use of a lockfile for thirdparty dependencies. After adding or editing jvm_artifact
targets, you will need to update affected lockfiles by running ./pants generate-lockfiles
. The default lockfile is located at 3rdparty/jvm/default.lock
, but it can be relocated (as well as additional resolves declared) via the [jvm].resolves
option.
packages
argumentTo efficiently determine which symbols are provided by thirdparty code (i.e., without hitting the network in order to compute dependencies in the common case), Pants relies on a static mapping of which artifacts provide which symbols, and defaults to treating each jvm_artifact
as providing symbols within its group
.
The packages
argument allows you to override which symbols a jvm_artifact
provides. See the jvm_artifact
docs for more information.
resource
targets
To have your code load files as "resources":
- Add a
resource
orresources
target with the relevant files in thesource
/sources
field, respectively. - Ensure that an appropriate
source_root
is detected for theresources
target, in order to trim the relevant prefix from the filename to align with the layout of your JVM packages. - Add that target to the
dependencies
field of the relevant JVM target (usually the one that uses the JVM APIs to load the resource).
For example:
- pants.toml
- src/jvm/org/pantsbuild/example/lib/BUILD
- src/jvm/org/pantsbuild/example/lib/Loader.java
- src/jvm/org/pantsbuild/example/lib/hello.txt
[source]
# In order for the resource to be loadable as `org/pantsbuild/example/lib/hello.txt`,
# the `/src/jvm/ prefix needs to be stripped.
root_patterns = ["/src/*"]
java_sources(dependencies=[":hello"])
resources(name="hello", sources=["hello.txt"])
package org.pantsbuild.example.lib;
import com.google.common.io.Resources;
public class Loader {
public static String load() {
... = Resources.getResource(Loader.class, "hello.txt");
}
}
Hello world!
Compile code
To manually check that sources compile, use ./pants check
:
# Check a single file
❯ ./pants check src/jvm/org/pantsbuild/example/lib/ExampleLib.java
# Check files located recursively under a directory
❯ ./pants check src/jvm::
# Check the whole repository
❯ ./pants check ::
Run tests
To run tests, use ./pants test
:
# Run a single test file
❯ ./pants test tests/jvm/org/pantsbuild/example/lib/ExampleLibSpec.scala
# Test all files in a directory
❯ ./pants test tests/jvm::
# Test the whole repository
❯ ./pants test ::
You can also pass through arguments to the test runner with --
, e.g.:
# Pass `-z hello` to scalatest in order to test a single method
❯ ./pants test tests/jvm/org/pantsbuild/example/lib/ExampleLibSpec.scala -- -z hello
Lint and Format
scalafmt
and Google Java Format
can be enabled by adding the pants.backend.experimental.scala.lint.scalafmt
and pants.backend.experimental.java.lint.google_java_format
backends (respectively) to backend_packages
in the [GLOBAL]
section of pants.toml
.
Once enabled, lint
and fmt
will check and automatically reformat your code:
# Format this directory and all subdirectories
❯ ./pants fmt src/jvm::
# Check that the whole project is formatted
❯ ./pants lint ::
# Format all changed files
❯ ./pants --changed-since=HEAD fmt