Skip to content

Commit

Permalink
Merge pull request #110 from eed3si9n/wip/classifier
Browse files Browse the repository at this point in the history
classifier support
  • Loading branch information
eed3si9n authored Sep 14, 2022
2 parents 0a2acb1 + 524bff8 commit bb586d5
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 155 deletions.
32 changes: 28 additions & 4 deletions multiversion-example/export-example/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ scala_library(

jvm_export(
name = "io1.publish",
target = ":io1",
artifacts = [":io1"],
project_name = "IO 1",
project_description = "IO library",
project_url = "http://example.com/",
Expand All @@ -36,7 +36,7 @@ jvm_assembly(

jvm_export(
name = "io1.assembly.publish",
target = ":io1.assembly",
artifacts = [":io1.assembly"],
project_name = "IO 1",
project_description = "IO library",
project_url = "http://example.com/",
Expand All @@ -51,7 +51,7 @@ scala_library(
name = "io2",
srcs = ["IO2.scala"],
tags = [
"maven_coordinates=com.twitter.dpb:io2:{pom_version}",
"maven_coordinates=com.twitter.dpb:io2:jar:abc:{pom_version}",
],
deps = [
":io1",
Expand All @@ -60,7 +60,7 @@ scala_library(

jvm_export(
name = "io2.publish",
target = ":io2",
artifacts = [":io2"],
project_name = "IO 2",
project_description = "IO library",
project_url = "http://example.com/",
Expand All @@ -70,3 +70,27 @@ jvm_export(
snapshot_repo = "https://localhost/",
# python_path = "/opt/ee/python/3.10/bin/python3.10",
)

scala_library(
name = "io3",
srcs = ["IO3.scala"],
tags = [
"maven_coordinates=com.twitter.dpb:io3:jar:abc:{pom_version}",
],
deps = [
":io2",
],
)

jvm_export(
name = "io3.publish",
artifacts = [":io3"],
project_name = "IO 3",
project_description = "IO library",
project_url = "http://example.com/",
license = "Apache-2.0",
scm_url = "http://github.com/",
release_repo = "https://localhost/",
snapshot_repo = "https://localhost/",
# python_path = "/opt/ee/python/3.10/bin/python3.10",
)
3 changes: 3 additions & 0 deletions multiversion-example/export-example/IO3.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.twitter.dpb

case class IO3()
2 changes: 1 addition & 1 deletion rules_jvm_export/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ scala_library(

jvm_export(
name = "io1.publish",
target = ":io1",
artifacts = [":io1"],
project_name = "IO 1",
project_description = "IO library",
project_url = "http://example.com/",
Expand Down
48 changes: 34 additions & 14 deletions rules_jvm_export/jvm_export/jvm_assembly.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,31 @@ def _jvm_assembly_impl(ctx):


def parse_maven_coordinates(coordinates_string, enforce_version_template=True):
coordinates = coordinates_string.split(":")
# Maven coordinates in the bazel ecosystem can include more than three fields.
# The group and artifact IDs are always the first 2 and the version is always the last field.
group_id, artifact_id = coordinates[0:2]
version = coordinates[-1]
"""
Given a string containing a standard Maven coordinate (g:a:[p:[c:]]v),
returns a Maven artifact map (see above).
See also https://github.com/bazelbuild/rules_jvm_external/blob/4.3/specs.bzl
"""
parts = coordinates_string.split(":")
group_id, artifact_id = parts[0:2]
if len(parts) == 3:
version = parts[2]
result = struct(group_id=group_id, artifact_id=artifact_id, version=version)
elif len(parts) == 4:
packaging = parts[2]
version = parts[3]
result = struct(group_id=group_id, artifact_id=artifact_id, packaging=packaging, version=version)
elif len(parts) == 5:
packaging = parts[2]
classifier = parts[3]
version = parts[4]
result = struct(group_id=group_id, artifact_id=artifact_id, packaging=packaging, classifier=classifier, version=version)
else:
fail("failed to parse '{}'".format(coordinates_string))

if enforce_version_template and version != "{pom_version}":
fail("should assign {pom_version} as Maven version via `tags` attribute")
return struct(group_id=group_id, artifact_id=artifact_id, version=version)

return result

def jar_assembler(ctx):
script = ctx.actions.declare_file(
Expand All @@ -47,14 +63,18 @@ def jar_assembler(ctx):


def runtime_output_jar(target):
if len(target[JavaInfo].runtime_output_jars) == 1:
return target[JavaInfo].runtime_output_jars[0]
else:
fail(
"expected size 1, but runtime_output_jars in {} was {}".format(
target, target[JavaInfo].runtime_output_jars
if JavaInfo in target:
if len(target[JavaInfo].runtime_output_jars) == 1:
return target[JavaInfo].runtime_output_jars[0]
else:
fail(
"expected size 1, but runtime_output_jars in {} was {}".format(
target, target[JavaInfo].runtime_output_jars
)
)
)
else:
outputs = target[DefaultInfo].files.to_list()
return outputs[0]


def generate_class_jar(ctx, pom_file):
Expand Down
129 changes: 80 additions & 49 deletions rules_jvm_export/jvm_export/jvm_export.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -12,87 +12,113 @@ load(":jvm_assembly.bzl",

JvmExportInfo = provider(
fields={
"jar": "JAR file to deploy",
"srcjar": "JAR file with sources",
"artifacts": "JAR file to deploy",
"pom": "Accompanying pom.xml file",
}
)


SOURCES_CLASSIFIER = "sources"
JAVADOC_CLASSIFIER = "javadoc"

def _jvm_export_impl(ctx):
version = ctx.attr.version[VersionInfo].value
pom_file = _generate_pom_file(ctx, version)
class_jar = runtime_output_jar(ctx.attr.target)
source_jar = _source_jar(ctx.attr.target)
output_files = [pom_file]
pom_xml_link = pom_file.basename
symlinks = {
pom_xml_link: pom_file,
}
source_jar = None
# create a dictionary of class_jar symlinks and classifier
artifacts = {}
for artifact in ctx.attr.artifacts:
this_coordinate = parse_maven_coordinates(artifact[JarInfo].name)
classifier = getattr(this_coordinate, "classifier", "")
class_jar = runtime_output_jar(artifact)
output_files.append(class_jar)
symlinks[class_jar.basename] = class_jar
artifacts[classifier] = class_jar.basename
if not classifier:
source_jar = _source_jar(artifact)
if source_jar:
output_files.append(source_jar)
src_jar_link = "lib.srcjar"
symlinks[src_jar_link] = source_jar
artifacts[SOURCES_CLASSIFIER] = src_jar_link

# TODO(vmax): use real Javadoc instead of srcjar
if (SOURCES_CLASSIFIER in artifacts) and (JAVADOC_CLASSIFIER not in artifacts):
artifacts[JAVADOC_CLASSIFIER] = artifacts[SOURCES_CLASSIFIER]

deploy_script = ctx.actions.declare_file(
"jvm-export/{}-deploy.py".format(ctx.attr.name)
)
lib_jar_link = "lib.jar"
src_jar_link = "lib.srcjar"
pom_xml_link = pom_file.basename
ctx.actions.expand_template(
template=ctx.file._deployment,
output=deploy_script,
substitutions={
"$JAR_PATH": lib_jar_link,
"$SRCJAR_PATH": src_jar_link,
"$ARTIFACTS": str(artifacts),
"$POM_PATH": pom_xml_link,
"$PYTHON_PATH": ctx.attr.python_path,
"{snapshot}": ctx.attr.snapshot_repo,
"{release}": ctx.attr.release_repo,
},
)
output_files = [pom_file, class_jar]

symlinks = {
lib_jar_link: class_jar,
pom_xml_link: pom_file,
}
if source_jar:
output_files.append(source_jar)
symlinks[src_jar_link] = source_jar

return [
DefaultInfo(
executable=deploy_script,
files=depset(output_files),
runfiles=ctx.runfiles(files=output_files, symlinks=symlinks),
),
JvmExportInfo(
jar=class_jar,
artifacts=artifacts,
pom=pom_file,
srcjar=source_jar,
),
]


def _generate_pom_file(ctx, version):
target = ctx.attr.target
if not target[JarInfo].name:
fail("{} missing 'maven_coordinates=' tags".format(target))
artifacts = ctx.attr.artifacts
for artifact in artifacts:
if not artifact[JarInfo].name:
fail("{} missing 'maven_coordinates=' tags".format(artifact))

maven_coordinates = parse_maven_coordinates(target[JarInfo].name)
pom_file = ctx.actions.declare_file("{}_pom.xml".format(ctx.attr.name))
maven_coordinates0 = parse_maven_coordinates(artifacts[0][JarInfo].name)

pom_deps = []
for pom_dependency in [
dep[JarInfo] for dep in target[JarInfo].deps if dep[JarInfo].name
]:
pom_dependency = pom_dependency.name
if pom_dependency == target[JarInfo].name:
continue
pom_dependency_coordinates = parse_maven_coordinates(pom_dependency, False)
pom_dependency_artifact = (
pom_dependency_coordinates.group_id
+ ":"
+ pom_dependency_coordinates.artifact_id
)
pom_dependency_version = pom_dependency_coordinates.version

v = ctx.attr.version_overrides.get(
pom_dependency_artifact, pom_dependency_version
)
pom_deps.append(pom_dependency_artifact + ":" + v)

# Note that all dependencies in all artifacts will be appended to
# the same POM as dependencies.
for artifact in artifacts:
this_coordinate = parse_maven_coordinates(artifact[JarInfo].name)
for pom_dependency in [
dep[JarInfo] for dep in artifact[JarInfo].deps if dep[JarInfo].name
]:
pom_dependency_coordinates = parse_maven_coordinates(pom_dependency.name, False)
if pom_dependency == this_coordinate:
continue
pom_dependency_artifact = (
pom_dependency_coordinates.group_id
+ ":"
+ pom_dependency_coordinates.artifact_id
)
pom_dependency_version = pom_dependency_coordinates.version
pom_dependency_classifier = getattr(pom_dependency_coordinates, "classifier", "")
pom_dependency_packaging = getattr(pom_dependency_coordinates, "packaging", "jar")
v = ctx.attr.version_overrides.get(
pom_dependency_artifact, pom_dependency_version
)
pom_dep = "{}:{}".format(pom_dependency_artifact, v)
if pom_dependency_classifier:
pom_dep = "{}:{}:{}:{}".format(
pom_dependency_artifact,
pom_dependency_packaging,
pom_dependency_classifier,
v)
pom_deps.append(pom_dep)

pom_gen_script = ctx.actions.declare_file(
"jvm-export/{}-pom-gen.py".format(ctx.attr.name)
Expand All @@ -109,8 +135,8 @@ def _generate_pom_file(ctx, version):
inputs=[],
outputs=[pom_file],
arguments=[
"--group_id=" + maven_coordinates.group_id,
"--artifact_id=" + maven_coordinates.artifact_id,
"--group_id=" + maven_coordinates0.group_id,
"--artifact_id=" + maven_coordinates0.artifact_id,
"--version=" + version,
"--project_name=" + ctx.attr.project_name,
"--project_description=" + ctx.attr.project_description,
Expand All @@ -126,14 +152,16 @@ def _generate_pom_file(ctx, version):


def _source_jar(target):
if len(target[JavaInfo].source_jars) < 1:
fail("Could not find source JAR to deploy in {}".format(target))
else:
if JavaInfo in target:
return target[JavaInfo].source_jars[0]
else:
return None


jvm_export = rule(
def make_jvm_export_rule():
return rule(
attrs={
"target": attr.label(
"artifacts": attr.label_list(
mandatory=True,
doc="Java target for subsequent deployment",
aspects=[
Expand Down Expand Up @@ -204,6 +232,9 @@ jvm_export = rule(
)


jvm_export = make_jvm_export_rule()


def _jvm_export_version_impl(ctx):
value = ctx.build_setting_value
return VersionInfo(value=value)
Expand Down
Loading

0 comments on commit bb586d5

Please sign in to comment.