Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modular Java #16502

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,11 @@ common --noenable_bzlmod
build --features=layering_check

common --repo_env=BAZEL_NO_APPLE_CPP_TOOLCHAIN=1

# JPMS and Turbine do not get along yet.
build --nojava_header_compilation
build --incompatible_use_toolchain_resolution_for_java_rules
build --java_language_version=11
build --java_runtime_version=11
build --tool_java_language_version=11
build --tool_java_runtime_version=11
1 change: 1 addition & 0 deletions .bazelversion
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6.3.2
5 changes: 3 additions & 2 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ maven_install(
repositories = [
"https://repo1.maven.org/maven2",
"https://repo.maven.apache.org/maven2",
"https://jpms.pkg.st/repository",
],
)

Expand Down Expand Up @@ -91,11 +92,11 @@ load("@rules_cc//cc:repositories.bzl", "rules_cc_dependencies")
rules_cc_dependencies()

# For `kt_jvm_library`
load("@io_bazel_rules_kotlin//kotlin:repositories.bzl", "kotlin_repositories")
load("@rules_kotlin//kotlin:repositories.bzl", "kotlin_repositories")

kotlin_repositories()

load("@io_bazel_rules_kotlin//kotlin:core.bzl", "kt_register_toolchains")
load("@rules_kotlin//kotlin:core.bzl", "kt_register_toolchains")

kt_register_toolchains()

Expand Down
149 changes: 141 additions & 8 deletions build_defs/java_opts.bzl
Original file line number Diff line number Diff line change
@@ -1,22 +1,43 @@
"""Java options and protobuf-specific java build rules with those options."""

load("@rules_java//java:defs.bzl", "java_library")
load("@rules_java//java:defs.bzl", "java_library", "java_import")
load("@rules_jvm_external//:defs.bzl", "java_export")
load("//java/osgi:osgi.bzl", "osgi_java_library")
load("//:protobuf_version.bzl", "PROTOBUF_JAVA_VERSION")

BUNDLE_DOC_URL = "https://developers.google.com/protocol-buffers/"
BUNDLE_LICENSE = "https://opensource.org/licenses/BSD-3-Clause"

## JDK target to use for versioned classes.
JPMS_JDK_TARGET = "9"

## Java compiler options for JDK 8.
JAVA_OPTS = [
"-source 8",
"-target 8",
"-Xep:Java8ApiChecker:ERROR",
]

BUNDLE_DOC_URL = "https://developers.google.com/protocol-buffers/"
BUNDLE_LICENSE = "https://opensource.org/licenses/BSD-3-Clause"
## Java compiler options for JDK 9+.
JAVA9_OPTS = [
"-source 9",
"-target 9",
]

## Default JAR manifest entries to stamp on export.
DEFAULT_MANIFEST_ENTRIES = {
"Multi-Release": "true"
}

## Default visibility settings for Java module targets.
DEFAULT_JMOD_VISIBILITY = [
"//java:__subpackages__",
]

def protobuf_java_export(**kwargs):
java_export(
javacopts = JAVA_OPTS,
manifest_entries = DEFAULT_MANIFEST_ENTRIES,
**kwargs
)

Expand All @@ -26,8 +47,122 @@ def protobuf_java_library(**kwargs):
**kwargs
)

def protobuf_java_module(
name,
module,
module_deps = [],
deps = [],
jvm_version = JPMS_JDK_TARGET,
visibility = DEFAULT_JMOD_VISIBILITY,
**kwargs):
"""Builds a `module-info.java` definition for use with a Protobuf Java target.

This macro replaces a chain of `java_library` and `genrule` steps to coax Bazel
into placing the `module-info.class` at the right path in a versioned modular
MRJAR (Multi-Release JAR).

The name provided to this target is then meant to be used downstream as a
JAR-unwrapped classfile. For example:

```starlark
protobuf_java_module(
name = "my-module",
module = "src/some/module-info.java",
)
java_library(
name = "...",
resources = [":my-module"],
resource_strip_prefix = "src/some/",
)
```

Args:
name: (required) The target name; a naked `.class` file
module: (required) Source file path for the `module-info.java`
module_deps: Other `protobuf_java_module` targets this one depends on
deps: Regular dependencies to add to the `java_library` target
jvm_version: JVM version for the path in the MRJAR; defaults to `9`.
visibility: Visibility setting to give the created targets.
**kwargs: Keyword arguments to pass to `java_library`
"""

# like: `module-java9`
module_target_name = "module-java%s" % jvm_version

# like: `module-java9-class`
module_class_target_name = "module-java%s-class" % jvm_version

# like: `module-java9-[zip|jar]`
zip_target_name = "module-java%s-zip" % jvm_version
jar_target_name = "%s-jar" % name
module_compilejar_target_name = "%s-compilejar" % name

# like: `META-INF/versions/9`
class_prefix = "META-INF/versions/%s" % jvm_version
class_file = "%s/module-info.class" % class_prefix
repacked_jar_file = "module-java%s.jar" % jvm_version

# command:
# mkdir -p `META-INF/versions/9` &&
# unzip -p module.jar module-info.class > `META-INF/verisons/9/module-info.class`
extract_classfile_command = " && ".join([
"mkdir -p %s" % class_prefix,
"unzip -p $(location :module-java%s) module-info.class > $@" % jvm_version,
])

# command:
# zip -r - META-INF > module-java9.jar
repack_zip_command = " && ".join([
"mkdir -p %s" % class_prefix,
"unzip -p $(location :module-java%s) module-info.class > %s" % (jvm_version, class_file),
"zip -r - META-INF > $@",
])

deps_rewritten = []
if len(module_deps) > 0:
deps_rewritten = [
"%s-compilejar" % i for i in module_deps
]

java_library(
name = module_target_name,
srcs = [module],
javacopts = JAVA9_OPTS,
deps = deps_rewritten + (deps or []),
visibility = visibility,
**kwargs,
)
native.genrule(
name = module_class_target_name,
srcs = [module_target_name],
outs = [class_file],
cmd = extract_classfile_command,
visibility = visibility,
)
native.genrule(
name = zip_target_name,
srcs = [module_target_name],
outs = [repacked_jar_file],
cmd = repack_zip_command,
)
java_import(
name = jar_target_name,
jars = [zip_target_name],
visibility = visibility,
)
native.alias(
name = name,
actual = module_class_target_name,
visibility = visibility,
)
native.alias(
name = module_compilejar_target_name,
actual = module_target_name,
visibility = visibility,
)

def protobuf_versioned_java_library(
automatic_module_name,
module_name,
bundle_description,
bundle_name,
bundle_symbolic_name,
Expand All @@ -45,9 +180,7 @@ def protobuf_versioned_java_library(
Args:
bundle_description: (required) The Bundle-Description header defines a short
description of this bundle.
automatic_module_name: (required) The Automatic-Module-Name header that represents
the name of the module when this bundle is used as an automatic
module.
module_name: (required) The Java 9 module name for this target.
bundle_name: (required) The Bundle-Name header defines a readable name for this
bundle. This should be a short, human-readable name that can
contain spaces.
Expand All @@ -69,7 +202,7 @@ def protobuf_versioned_java_library(
"""
osgi_java_library(
javacopts = JAVA_OPTS,
automatic_module_name = automatic_module_name,
module_name = module_name,
bundle_doc_url = BUNDLE_DOC_URL,
bundle_license = BUNDLE_LICENSE,
bundle_version = PROTOBUF_JAVA_VERSION,
Expand Down
96 changes: 96 additions & 0 deletions build_defs/kt_opts.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
"""Inlined version of `kt_jvm_export` from `rules_jvm_external`."""

load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library")
load("@rules_jvm_external//private/rules:java_export.bzl", "maven_export")
load("@rules_jvm_external//private/rules:maven_project_jar.bzl", "DEFAULT_EXCLUDED_WORKSPACES")
load("//build_defs:java_opts.bzl", "DEFAULT_MANIFEST_ENTRIES")

def kt_jvm_export(
name,
maven_coordinates,
manifest_entries = DEFAULT_MANIFEST_ENTRIES,
deploy_env = [],
excluded_workspaces = {name: None for name in DEFAULT_EXCLUDED_WORKSPACES},
pom_template = None,
visibility = None,
tags = [],
testonly = None,
**kwargs):
"""Extends `kt_jvm_library` to allow maven artifacts to be uploaded. This
rule is the Kotlin JVM version of `java_export`.

This macro can be used as a drop-in replacement for `kt_jvm_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 kt_jvm_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.

Generated rules:
* `name`: A `kt_jvm_library` that other rules can depend upon.
* `name-docs`: A javadoc 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.
manifest_entries: Manifest entries to pass to `java_export`.
deploy_env: A list of labels of java targets to exclude from the generated jar
visibility: The visibility of the target
kwargs: These are passed to [`kt_jvm_library`](https://bazelbuild.github.io/rules_kotlin/kotlin),
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", [])

# Construct the kt_jvm_library we'll export from here.
kt_jvm_library(
name = lib_name,
tags = tags + maven_coordinates_tags,
testonly = testonly,
**kwargs
)

maven_export(
name = name,
maven_coordinates = maven_coordinates,
lib_name = lib_name,
deploy_env = deploy_env,
excluded_workspaces = excluded_workspaces,
pom_template = pom_template,
visibility = visibility,
tags = tags,
testonly = testonly,
javadocopts = javadocopts,
manifest_entries = manifest_entries,
)
Binary file added java/.mvn/wrapper/maven-wrapper.jar
Binary file not shown.
18 changes: 18 additions & 0 deletions java/.mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
14 changes: 14 additions & 0 deletions java/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@ filegroup(
],
)

package_group(
name = "pkgs",
packages = [
"//java/%s" % x for x in [
"core",
"kotlin",
"kotlin-jmod",
"kotlin-lite",
"lite",
"util",
]
],
)

################################################################################
# Packaging rules
################################################################################
Expand Down