| load(":functions.bzl", "create_option_file", "explicit_target") |
| |
| def _maven_pom_impl(ctx): |
| # Contains both *.jar and *.aar files. |
| jars = depset() |
| |
| # classfied jars. Sources are in clsjars["sources"] |
| clsjars = {} # classifier -> depset(jars) |
| clsjars["sources"] = depset() |
| |
| if ctx.attr.library: |
| if ctx.attr.file or ctx.attr.classified_files: |
| fail("Cannot set both file and library for a maven_pom.") |
| jars = jars | depset([jar.class_jar for jar in ctx.attr.library.java.outputs.jars]) |
| clsjars["sources"] = clsjars["sources"] | ctx.attr.library.java.source_jars |
| for classifier, library in zip(ctx.attr.classifiers, ctx.attr.classified_libraries): |
| if classifier not in clsjars: |
| clsjars[classifier] = depset() |
| clsjars[classifier] += depset([jar.class_jar for jar in library.java.outputs.jars]) |
| |
| if ctx.attr.file: |
| if ctx.attr.library or ctx.attr.classified_libraries: |
| fail("Cannot set both file and library for a maven_pom.") |
| jars = jars | ctx.attr.file.files |
| |
| if ctx.attr.classified_files: |
| for classifier, file in zip(ctx.attr.classifiers, ctx.attr.classified_files): |
| if classifier not in clsjars: |
| clsjars[classifier] = depset() |
| clsjars[classifier] += file.files |
| |
| if ctx.attr.properties and ctx.files.properties_files: |
| fail("Cannot set both properties and properties_files for a maven_pom.") |
| |
| parent_poms = depset([], order = "postorder") |
| parent_jars = {} |
| parent_clsjars = {} # pom -> classifier -> depset(jars) |
| |
| deps_poms = depset([], order = "postorder") |
| deps_jars = {} |
| deps_clsjars = {} # pom -> classifier -> depset(jars) |
| |
| # Transitive deps through the parent attribute |
| if ctx.attr.parent: |
| parent_poms = parent_poms | ctx.attr.parent.maven.parent.poms |
| parent_poms = parent_poms | ctx.attr.parent.maven.deps.poms |
| parent_poms = parent_poms | [ctx.file.parent] |
| parent_jars += ctx.attr.parent.maven.parent.jars |
| parent_jars += ctx.attr.parent.maven.deps.jars |
| parent_jars += {ctx.file.parent: ctx.attr.parent.maven.jars} |
| parent_clsjars += ctx.attr.parent.maven.parent.clsjars |
| parent_clsjars += ctx.attr.parent.maven.deps.clsjars |
| parent_clsjars += {ctx.file.parent: ctx.attr.parent.maven.clsjars} |
| elif hasattr(ctx.attr.source, "maven"): |
| parent_poms = ctx.attr.source.maven.parent.poms |
| parent_jars = ctx.attr.source.maven.parent.jars |
| parent_clsjars = ctx.attr.source.maven.parent.clsjars |
| |
| # Transitive deps through deps |
| if ctx.attr.deps: |
| for label in ctx.attr.deps: |
| deps_poms = deps_poms | label.maven.parent.poms |
| deps_poms = deps_poms | label.maven.deps.poms |
| deps_poms = deps_poms | [label.maven.pom] |
| deps_jars += label.maven.parent.jars |
| deps_jars += label.maven.deps.jars |
| deps_jars += {label.maven.pom: label.maven.jars} |
| deps_clsjars += label.maven.parent.clsjars |
| deps_clsjars += label.maven.deps.clsjars |
| deps_clsjars += {label.maven.pom: label.maven.clsjars} |
| elif hasattr(ctx.attr.source, "maven"): |
| deps_poms = ctx.attr.source.maven.deps.poms |
| deps_jars = ctx.attr.source.maven.deps.jars |
| deps_clsjars = ctx.attr.source.maven.deps.clsjars |
| |
| inputs = [] |
| args = [] |
| |
| # Input file to take as base |
| if ctx.file.source: |
| args += ["-i", ctx.file.source.path] |
| inputs += [ctx.file.source] |
| |
| # Output file |
| args += ["-o", ctx.outputs.pom.path] |
| |
| args += ["-x"] if ctx.attr.export_pom else [] |
| |
| # Overrides |
| if ctx.attr.group: |
| args += ["--group", ctx.attr.group] |
| if ctx.attr.artifact: |
| args += ["--artifact", ctx.attr.artifact] |
| if ctx.attr.version: |
| args += ["--version", ctx.attr.version] |
| if ctx.attr.properties: |
| args += ["--properties", ctx.file.properties.path] |
| inputs += [ctx.file.properties] |
| if ctx.files.properties_files: |
| args += ["--properties", ":".join([file.path for file in ctx.files.properties_files])] |
| inputs += ctx.files.properties_files |
| if ctx.attr.version_property: |
| args += ["--version_property", ctx.attr.version_property] |
| |
| # Exclusions |
| for (dependency, exclusions) in ctx.attr.exclusions.items(): |
| args += ["--exclusion", dependency, ",".join([e for e in exclusions])] |
| |
| args += ["--deps", ":".join([dep.path for dep in ctx.files.deps])] |
| inputs += ctx.files.deps |
| |
| ctx.action( |
| mnemonic = "GenPom", |
| inputs = inputs, |
| outputs = [ctx.outputs.pom], |
| arguments = args, |
| executable = ctx.executable._pom, |
| ) |
| |
| return struct(maven = struct( |
| parent = struct( |
| poms = parent_poms, |
| jars = parent_jars, |
| clsjars = parent_clsjars, |
| ), |
| deps = struct( |
| poms = deps_poms, |
| jars = deps_jars, |
| clsjars = deps_clsjars, |
| ), |
| pom = ctx.outputs.pom, |
| jars = jars, |
| clsjars = clsjars, |
| )) |
| |
| maven_pom = rule( |
| attrs = { |
| "deps": attr.label_list(), |
| "library": attr.label( |
| allow_files = True, |
| ), |
| "export_pom": attr.label(), |
| "classifiers": attr.string_list( |
| default = [], |
| ), |
| "classified_libraries": attr.label_list( |
| allow_files = True, |
| default = [], |
| ), |
| "file": attr.label( |
| allow_files = True, |
| ), |
| "classified_files": attr.label_list( |
| allow_files = True, |
| default = [], |
| ), |
| "group": attr.string(), |
| "version": attr.string(), |
| "artifact": attr.string(), |
| "source": attr.label( |
| allow_files = True, |
| single_file = True, |
| ), |
| "properties": attr.label( |
| allow_files = True, |
| single_file = True, |
| ), |
| "properties_files": attr.label_list( |
| allow_files = True, |
| default = [], |
| ), |
| "version_property": attr.string(), |
| "parent": attr.label( |
| allow_files = True, |
| single_file = True, |
| ), |
| "exclusions": attr.string_list_dict(), |
| "_pom": attr.label( |
| executable = True, |
| cfg = "host", |
| default = Label("//tools/base/bazel:pom_generator"), |
| allow_files = True, |
| ), |
| }, |
| outputs = { |
| "pom": "%{name}.pom", |
| }, |
| implementation = _maven_pom_impl, |
| ) |
| |
| # A java library that can be used in a maven_repo rule. |
| # |
| # Usage: |
| # maven_java_library( |
| # name = "name", |
| # deps = A list of maven_java_library or maven_java_import dependencies |
| # # all java_library attriutes |
| # info = A maven coordinate for this artifact as a string |
| # ) |
| def maven_java_library( |
| name, |
| deps = None, |
| runtime_deps = None, |
| exclusions = None, |
| export_artifact = None, |
| srcs = None, |
| resources = [], |
| exports = None, |
| pom = None, |
| visibility = None, |
| **kwargs): |
| if srcs and export_artifact: |
| fail("Ony one of [srcs, export_artifact] can be used at a time") |
| |
| if export_artifact and pom: |
| fail("If export_artifact is specified, the maven information cannot be changed.") |
| |
| java_exports = exports + [export_artifact] if export_artifact else exports |
| native.java_library( |
| name = name, |
| deps = deps, |
| runtime_deps = runtime_deps, |
| srcs = srcs, |
| resources = native.glob(["NOTICE", "LICENSE"]) + resources, |
| exports = java_exports, |
| visibility = visibility, |
| **kwargs |
| ) |
| |
| # TODO: Properly exclude libraries from the pom instead of using _neverlink hacks. |
| maven_deps = (deps or []) + (exports or []) + (runtime_deps or []) |
| |
| maven_pom( |
| name = name + "_maven", |
| deps = [explicit_target(dep) + "_maven" for dep in maven_deps if not dep.endswith("_neverlink")] if maven_deps else None, |
| exclusions = exclusions, |
| library = export_artifact if export_artifact else name, |
| visibility = visibility, |
| source = explicit_target(export_artifact) + "_maven" if export_artifact else pom, |
| export_pom = explicit_target(export_artifact) + "_maven" if export_artifact else None, |
| ) |
| |
| # A java_import rule extended with pom and parent attributes for maven libraries. |
| def maven_java_import(name, pom, classifiers = [], visibility = None, jars = [], **kwargs): |
| native.java_import( |
| name = name, |
| visibility = visibility, |
| jars = jars, |
| **kwargs |
| ) |
| |
| classified_libraries = [] |
| for classifier in classifiers: |
| native.java_import( |
| name = classifier + "-" + name, |
| visibility = visibility, |
| jars = [jar.replace(".jar", "-" + classifier + ".jar") for jar in jars], |
| **kwargs |
| ) |
| classified_libraries += [classifier + "-" + name] |
| |
| maven_pom( |
| name = name + "_maven", |
| library = name, |
| classifiers = classifiers, |
| classified_libraries = classified_libraries, |
| visibility = visibility, |
| source = pom, |
| ) |
| |
| def maven_aar(name, aar, pom, visibility = None): |
| native.filegroup( |
| name = name, |
| srcs = [aar], |
| visibility = visibility, |
| ) |
| |
| maven_pom( |
| name = name + "_maven", |
| file = aar, |
| visibility = visibility, |
| source = pom, |
| ) |
| |
| def _maven_repo_impl(ctx): |
| include_sources = ctx.attr.include_sources |
| |
| seen = {} |
| inputs = [] |
| args = [] |
| for artifact in ctx.attr.artifacts: |
| if not seen.get(artifact.maven.pom): |
| for pom in artifact.maven.parent.poms: |
| jars = artifact.maven.parent.jars[pom] |
| if not seen.get(pom): |
| inputs += [pom] + list(jars) |
| args += [pom.path] + [jar.path for jar in list(jars)] |
| clsjars = artifact.maven.parent.clsjars[pom] |
| for classifier in clsjars: |
| inputs += list(clsjars[classifier]) |
| args += [jar.path + ":" + classifier for jar in list(clsjars[classifier])] |
| seen += {pom: True} |
| inputs += [artifact.maven.pom] + list(artifact.maven.jars) |
| args += [artifact.maven.pom.path] + [jar.path for jar in list(artifact.maven.jars)] |
| for classifier in artifact.maven.clsjars: |
| inputs += list(artifact.maven.clsjars[classifier]) |
| args += [jar.path + ":" + classifier for jar in list(artifact.maven.clsjars[classifier])] |
| |
| seen += {artifact.maven.pom: True} |
| for pom in artifact.maven.deps.poms: |
| jars = artifact.maven.deps.jars[pom] |
| if not seen.get(pom): |
| inputs += [pom] + list(jars) |
| args += [pom.path] + [jar.path for jar in list(jars)] |
| if include_sources: |
| clsjars = artifact.maven.deps.clsjars[pom] |
| inputs += list(clsjars[classifier]) |
| args += [jar.path + ":" + classifier for jar in list(clsjars[classifier])] |
| seen += {pom: True} |
| |
| # Execute the command |
| option_file = create_option_file( |
| ctx, |
| ctx.outputs.repo.path + ".lst", |
| "\n".join(args), |
| ) |
| |
| ctx.action( |
| inputs = inputs + [option_file], |
| outputs = [ctx.outputs.repo], |
| mnemonic = "mavenrepo", |
| executable = ctx.executable._repo, |
| arguments = [ctx.outputs.repo.path, "@" + option_file.path], |
| ) |
| |
| _maven_repo = rule( |
| attrs = { |
| "artifacts": attr.label_list(), |
| "include_sources": attr.bool(), |
| "_repo": attr.label( |
| executable = True, |
| cfg = "host", |
| default = Label("//tools/base/bazel:repo_builder"), |
| allow_files = True, |
| ), |
| }, |
| outputs = { |
| "repo": "%{name}.zip", |
| }, |
| implementation = _maven_repo_impl, |
| ) |
| |
| # Creates a maven repo with the given artifacts and all their transitive |
| # dependencies. |
| # |
| # Usage: |
| # maven_repo( |
| # name = The name of the rule. The output of the rule will be ${name}.zip. |
| # artifacts = A list of all maven_java_libraries to add to the repo. |
| # include_sources = Add source jars to the repo as well (useful for tests). |
| # ) |
| def maven_repo(artifacts = [], include_sources = False, **kwargs): |
| _maven_repo( |
| artifacts = [explicit_target(artifact) + "_maven" for artifact in artifacts], |
| include_sources = include_sources, |
| **kwargs |
| ) |