Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ single_version_override(
version = "8.16.1",
)

bazel_dep(name = "rules_jvm_external", version = "6.9")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to check in a maven_install.json for this?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll also need to set this up for legacy WORKSPACE builds. That means updating:

  • scala/deps.bzl
  • scala/latest_deps.bzl
  • Probably every legacy WORKSPACE file in the project

Another reason the legacy WORKSPACE system must be destroyed, but I'm not ready to drop support just yet.

single_version_override(
module_name = "rules_jvm_external",
version = "6.9",
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also add a bazel_dep(name = "rules_jvm_external", version = "6.9") to deps/latest/MODULE.bazel.


bazel_dep(name = "rules_proto", version = "6.0.0")
single_version_override(
module_name = "rules_proto",
Expand Down
8 changes: 3 additions & 5 deletions MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

132 changes: 132 additions & 0 deletions scala/private/rules/scala_export.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
load("@bazel_skylib//rules:run_binary.bzl", "run_binary")
load("@rules_jvm_external//:defs.bzl", "create_jar", "maven_export")
load("//scala/private:rules/scala_doc.bzl", "make_scala_doc_rule", "scaladoc_intransitive_aspect")
load("//scala/private:rules/scala_library.bzl", "scala_library")

DEFAULT_EXCLUDED_WORKSPACES = [
# Note: we choose to drop the dependency entirely because
# we can't be sure which coordinate the user has
# chosen for protobuf.
"com_google_protobuf",
"protobuf", # bzlmod module deps are in the form of '@protobuf~<version>'
]

scala_doc = make_scala_doc_rule(aspect = scaladoc_intransitive_aspect)

SCALA_LIBS = []

def scala_export(
name,
maven_coordinates,
deploy_env = [],
excluded_workspaces = {name: None for name in DEFAULT_EXCLUDED_WORKSPACES},
exclusions = {},
pom_template = None,
visibility = None,
tags = [],
testonly = None,
publish_maven_metadata = False,
**kwargs):
"""Extends `scala_library` to allow maven artifacts to be uploaded. This
rule is the Scala version of `java_export`.

This macro can be used as a drop-in replacement for `scala_library`, but
also generates an implicit `name.publish` target that can be run to publish
maven artifacts derived from this macro to a maven repository. The publish
rule understands the following variables (declared using `--define` when
using `bazel run`):

* `maven_repo`: A URL for the repo to use. May be "https" or "file".
* `maven_user`: The user name to use when uploading to the maven repository.
* `maven_password`: The password to use when uploading to the maven repository.

This macro also generates a `name-pom` target that creates the `pom.xml` file
associated with the artifacts. The template used is derived from the (optional)
`pom_template` argument, and the following substitutions are performed on
the template file:

* `{groupId}`: Replaced with the maven coordinates group ID.
* `{artifactId}`: Replaced with the maven coordinates artifact ID.
* `{version}`: Replaced by the maven coordinates version.
* `{type}`: Replaced by the maven coordintes type, if present (defaults to "jar")
* `{dependencies}`: Replaced by a list of maven dependencies directly relied upon
by scala_library targets within the artifact.

The "edges" of the artifact are found by scanning targets that contribute to
runtime dependencies for the following tags:

* `maven_coordinates=group:artifact:type:version`: Specifies a dependency of
this artifact.
* `maven:compile-only`: Specifies that this dependency should not be listed
as a dependency of the artifact being generated.

To skip generation of the javadoc jar, add the `no-javadocs` tag to the target.
To skip generation of the scaladoc jar, add the `no-scaladocs` tag to the target.

Generated rules:
* `name`: A `scala_library` that other rules can depend upon.
* `name-docs`: A javadoc jar file.
* `name-scaladocs`: A scaladoc jar file.
* `name-pom`: The pom.xml file.
* `name.publish`: To be executed by `bazel run` to publish to a maven repo.

Args:
name: A unique name for this target
maven_coordinates: The maven coordinates for this target.
pom_template: The template to be used for the pom.xml file.
deploy_env: A list of labels of java targets to exclude from the generated jar
visibility: The visibility of the target
publish_maven_metadata: Whether to publish a maven-metadata.xml
kwargs: These are passed to [`scala_library`](https://github.com/bazelbuild/rules_scala/blob/master/docs/scala_library.md),
and so may contain any valid parameter for that rule.
"""
maven_coordinates_tags = ["maven_coordinates=%s" % maven_coordinates]
lib_name = "%s-lib" % name

javadocopts = kwargs.pop("javadocopts", None)
doc_resources = kwargs.pop("doc_resources", [])
classifier_artifacts = kwargs.pop("classifier_artifacts", {})

updated_deploy_env = [] + deploy_env
for lib in SCALA_LIBS:
if lib not in deploy_env:
updated_deploy_env.append(lib)

scala_library(
name = lib_name,
tags = tags + maven_coordinates_tags,
testonly = testonly,
**kwargs
)

if "no-scaladocs" not in tags:
scaladocs_name = name + "-scaladocs-html"
scala_doc(
name = scaladocs_name,
deps = [":" + lib_name],
)

scaladocs_jar_name = name + "-scaladocs"
create_jar(
name = scaladocs_jar_name,
inputs = [":" + scaladocs_name] + doc_resources,
out = name + "-scaladocs.jar",
)
classifier_artifacts["scaladoc"] = scaladocs_jar_name

maven_export(
name = name,
maven_coordinates = maven_coordinates,
classifier_artifacts = classifier_artifacts,
lib_name = lib_name,
deploy_env = updated_deploy_env,
excluded_workspaces = excluded_workspaces,
exclusions = exclusions,
pom_template = pom_template,
visibility = visibility,
tags = tags,
testonly = testonly,
javadocopts = javadocopts,
doc_resources = doc_resources,
publish_maven_metadata = publish_maven_metadata,
)
5 changes: 5 additions & 0 deletions scala/scala.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ load(
_make_scala_doc_rule = "make_scala_doc_rule",
_scaladoc_intransitive_aspect = "scaladoc_intransitive_aspect",
)
load(
"//scala/private:rules/scala_export.bzl",
_scala_export = "scala_export",
)
load(
"//scala/private:rules/scala_junit_test.bzl",
_scala_junit_test = "scala_junit_test",
Expand Down Expand Up @@ -58,6 +62,7 @@ make_scala_doc_rule = _make_scala_doc_rule
scaladoc_intransitive_aspect = _scaladoc_intransitive_aspect
scala_doc = _make_scala_doc_rule()
ScaladocAspectInfo = _ScaladocAspectInfo
scala_export = _scala_export
scala_junit_test = _scala_junit_test
scala_library = _scala_library
scala_library_for_plugin_bootstrapping = _scala_library_for_plugin_bootstrapping
Expand Down
78 changes: 78 additions & 0 deletions test/scala_export/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
load("@bazel_skylib//rules:diff_test.bzl", "diff_test")
load("@rules_scala//scala:scala.bzl", "scala_export", "scala_library")

scala_library(
name = "deploy_env_dep",
srcs = ["DeployEnvDependency.scala"],
deps = [],
)

scala_library(
name = "dep",
srcs = ["Dependency.scala"],
)

scala_export(
name = "external_dep",
srcs = ["ExternalDependency.scala"],
maven_coordinates = "com.example:external:1.0.0",
)

scala_export(
name = "test",
srcs = [
"Main.scala",
],
deploy_env = [
":deploy_env_dep",
],
maven_coordinates = "com.example:scala:1.0.0",
unused_dependency_checker_mode = "off",
deps = [
":dep",
":external_dep",
],
)

genrule(
name = "list-classes",
srcs = [
":test-project",
],
outs = ["classes.txt"],
cmd = "for SRC in $(SRCS); do jar tf $$SRC >> $@; done",
)

sh_test(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a load("@rules_shell//shell:sh_test.bzl", "sh_test") for this.

name = "check-deploy-env",
srcs = [
"check-deploy-env.sh",
],
data = [
":classes.txt",
],
deps = [
"@bazel_tools//tools/bash/runfiles",
],
)

diff_test(
name = "validate-pom",
file1 = ":test-pom",
file2 = "pom.golden.xml",
)

genrule(
name = "list-scaladocs",
srcs = [
":test-scaladocs",
],
outs = ["scaladocs.txt"],
cmd = "for SRC in $(SRCS); do jar tf $$SRC >> $@; done",
)

diff_test(
name = "validate-scaladocs",
file1 = ":scaladocs.txt",
file2 = "scaladocs.golden.txt",
)
7 changes: 7 additions & 0 deletions test/scala_export/Dependency.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package scalarules.test.scala_export

class Dependency {
def getName(): String = {
"scala_export test"
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is such a small thing, but please add newlines to the end of these test .scala files.

7 changes: 7 additions & 0 deletions test/scala_export/DeployEnvDependency.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package scalarules.test.scala_export

class DeployEnvDependency {
def getName(): String = {
"scala_export test"
}
}
7 changes: 7 additions & 0 deletions test/scala_export/ExternalDependency.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package scalarules.test.scala_export

class ExternalDependency {
def getName(): String = {
"scala_export test"
}
}
7 changes: 7 additions & 0 deletions test/scala_export/Main.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package scalarules.test.scala_export

object Main {
def main(args: Array[String]): Unit = {
println("Hello, world")
}
}
29 changes: 29 additions & 0 deletions test/scala_export/check-deploy-env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# --- begin runfiles.bash initialization v2 ---
# Copy-pasted from the Bazel Bash runfiles library v2.
set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
source "$0.runfiles/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# --- end runfiles.bash initialization v2 ---

set -euox pipefail

classes_file=$(rlocation rules_scala/test/scala_export/classes.txt)

if grep -q DeployEnvDependency.class "$classes_file"; then
echo "Unexpectedly found DeployEnvDependency class in jar"
exit 1
fi

if ! grep -q Dependency.class "$classes_file"; then
echo "Missing Dependency class from jar"
exit 1
fi

if ! grep -q Main.class "$classes_file"; then
echo "Missing Main class from jar"
exit 1
fi
18 changes: 18 additions & 0 deletions test/scala_export/pom.golden.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>

<groupId>com.example</groupId>
<artifactId>scala</artifactId>
<version>1.0.0</version>

<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>external</artifactId>
<version>1.0.0</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
Loading