diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 0f028e33d..a3791c269 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -13,6 +13,7 @@ tasks: - "//..." # These tests are currently incompatible with RBE - "-//tests/integration:UnsafeSharedCacheTest" + - "-//tests/integration/override_targets" ubuntu1804: shell_commands: - bazel run @unpinned_regression_testing//:pin @@ -36,3 +37,4 @@ tasks: # https://github.com/bazelbuild/rules_kotlin/issues/179 # https://github.com/bazelbuild/rules_kotlin/blob/master/.bazelci/presubmit.yml - "-//tests/unit/kotlin/..." + - "-//tests/integration/override_targets" diff --git a/README.md b/README.md index 225c6d354..779955c62 100644 --- a/README.md +++ b/README.md @@ -530,6 +530,31 @@ $ bazel query @pinning//:all | grep guava_guava @pinning//:com_google_guava_guava_25_0_android ``` +### Overriding generated targets + +You can override the generated targets for artifacts with a target label of your +choice. For instance, if you want to provide your own definition of +`@maven//:com_google_guava_guava` at `//third_party/guava:guava`, specify the +mapping in the `override_targets` attribute: + +```python +maven_install( + name = "pinning", + artifacts = [ + "com.google.guava:guava:27.0-jre", + ], + repositories = [ + "https://repo1.maven.org/maven2", + ], + override_targets = { + "com.google.guava:guava": "@//third_party/guava:guava", + }, +) +``` + +Note that the target label contains `@//`, which tells Bazel to reference the +target relative to your main workspace, instead of the `@maven` workspace. + ### Proxies As with other Bazel repository rules, the standard `http_proxy`, `https_proxy` diff --git a/WORKSPACE b/WORKSPACE index b4f6bc51f..c41f0fa5b 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -151,6 +151,8 @@ maven_install( "org.openjfx:javafx-base:11.0.1", # https://github.com/bazelbuild/rules_jvm_external/issues/178 "io.kubernetes:client-java:4.0.0-beta1", + # https://github.com/bazelbuild/rules_jvm_external/issues/199 + "com.google.ar.sceneform.ux:sceneform-ux:1.10.0", ], repositories = [ "https://repo1.maven.org/maven2", @@ -159,6 +161,9 @@ maven_install( ], generate_compat_repositories = True, maven_install_json = "//:regression_testing_install.json", + override_targets = { + "com.google.ar.sceneform:rendering": "@//tests/integration/override_targets:sceneform_rendering", + } ) load("@regression_testing//:defs.bzl", "pinned_maven_install") diff --git a/coursier.bzl b/coursier.bzl index 9ed9a788e..91e9cb11a 100644 --- a/coursier.bzl +++ b/coursier.bzl @@ -130,7 +130,7 @@ def _genrule_copy_artifact_from_http_file(artifact): # tree. # # Made function public for testing. -def _generate_imports(repository_ctx, dep_tree, neverlink_artifacts = {}): +def _generate_imports(repository_ctx, dep_tree, neverlink_artifacts, override_targets): # The list of java_import/aar_import declaration strings to be joined at the end all_imports = [] @@ -145,6 +145,10 @@ def _generate_imports(repository_ctx, dep_tree, neverlink_artifacts = {}): # @maven//:junit_junit, we also generate @junit_junit//jar as an alias to it. jar_versionless_target_labels = [] + labels_to_override = {} + for coord in override_targets: + labels_to_override.update({_escape(coord): override_targets.get(coord)}) + # First collect a map of target_label to their srcjar relative paths, and symlink the srcjars if needed. # We will use this map later while generating target declaration strings with the "srcjar" attr. srcjar_paths = None @@ -171,7 +175,16 @@ def _generate_imports(repository_ctx, dep_tree, neverlink_artifacts = {}): elif repository_ctx.attr.fetch_sources and ":sources:" in artifact["coord"]: # We already processed the sources above, so skip them here. pass - elif target_label not in seen_imports and artifact_path != None: + elif target_label in labels_to_override: + # Override target labels with the user provided mapping, instead of generating + # a jvm_import/aar_import based on information in dep_tree. + seen_imports[target_label] = True + all_imports.append( + "alias(\n\tname = \"%s\",\n\tactual = \"%s\",\n)" % (target_label, labels_to_override.get(target_label))) + if repository_ctx.attr.maven_install_json: + # Provide the downloaded artifact as a file target. + all_imports.append(_genrule_copy_artifact_from_http_file(artifact)) + elif artifact_path != None: seen_imports[target_label] = True # 1. Generate the rule class. @@ -233,7 +246,11 @@ def _generate_imports(repository_ctx, dep_tree, neverlink_artifacts = {}): # Coursier returns cyclic dependencies sometimes. Handle it here. # See https://github.com/bazelbuild/rules_jvm_external/issues/172 if dep_target_label != target_label: - target_import_labels.append("\t\t\":%s\",\n" % dep_target_label) + if dep_target_label in labels_to_override: + dep_target_label = labels_to_override.get(dep_target_label) + else: + dep_target_label = ":" + dep_target_label + target_import_labels.append("\t\t\"%s\",\n" % dep_target_label) target_import_labels = _deduplicate_list(target_import_labels) target_import_string.append("".join(target_import_labels) + "\t],") @@ -573,6 +590,7 @@ def _pinned_coursier_fetch_impl(repository_ctx): for a in artifacts if a.get("neverlink", False) }, + override_targets = repository_ctx.attr.override_targets, ) repository_ctx.template( @@ -767,6 +785,7 @@ def _coursier_fetch_impl(repository_ctx): repository_ctx = repository_ctx, dep_tree = dep_tree, neverlink_artifacts = neverlink_artifacts, + override_targets = repository_ctx.attr.override_targets, ) repository_ctx.template( @@ -856,6 +875,7 @@ pinned_coursier_fetch = repository_rule( "fetch_sources": attr.bool(default = False), "generate_compat_repositories": attr.bool(default = False), # generate a compatible layer with repositories for each artifact "maven_install_json": attr.label(allow_single_file = True), + "override_targets": attr.string_dict(default = {}), }, implementation = _pinned_coursier_fetch_impl, ) @@ -883,6 +903,7 @@ coursier_fetch = repository_rule( values = ["default", "pinned"], ), "maven_install_json": attr.label(allow_single_file = True), + "override_targets": attr.string_dict(default = {}), }, environ = [ "JAVA_HOME", diff --git a/defs.bzl b/defs.bzl index 5c00f1622..a57a971af 100644 --- a/defs.bzl +++ b/defs.bzl @@ -27,7 +27,8 @@ def maven_install( excluded_artifacts = [], generate_compat_repositories = False, version_conflict_policy = "default", - maven_install_json = None): + maven_install_json = None, + override_targets = {}): """Resolves and fetches artifacts transitively from Maven repositories. This macro runs a repository rule that invokes the Coursier CLI to resolve @@ -52,6 +53,9 @@ def maven_install( Coursier's default policy. maven_install_json: A label to a `maven_install.json` file to use pinned artifacts for generating build targets. e.g `//:maven_install.json`. + override_targets: A mapping of `group:artifact` to Bazel target labels. All occurrences of the + target label for `group:artifact` will be an alias to the specified label, therefore overriding + the original generated `jvm_import` or `aar_import` target. """ repositories_json_strings = [] for repository in parse.parse_repository_spec_list(repositories): @@ -90,6 +94,7 @@ def maven_install( excluded_artifacts = excluded_artifacts_json_strings, generate_compat_repositories = generate_compat_repositories, version_conflict_policy = version_conflict_policy, + override_targets = override_targets, ) if maven_install_json != None: @@ -100,6 +105,7 @@ def maven_install( maven_install_json = maven_install_json, fetch_sources = fetch_sources, generate_compat_repositories = generate_compat_repositories, + override_targets = override_targets, ) diff --git a/docs/api.md b/docs/api.md index 987397e5e..35bc5f692 100644 --- a/docs/api.md +++ b/docs/api.md @@ -31,7 +31,7 @@ load("@rules_jvm_external//:defs.bzl", "maven_install", "artifact") ## maven_install
-maven_install(name, repositories, artifacts, fail_on_missing_checksum, fetch_sources, use_unsafe_shared_cache, excluded_artifacts, generate_compat_repositories, maven_install_json)
+maven_install(name, repositories, artifacts, fail_on_missing_checksum, fetch_sources, use_unsafe_shared_cache, excluded_artifacts, generate_compat_repositories, version_conflict_policy, maven_install_json, override_targets)
 
Resolves and fetches artifacts transitively from Maven repositories. @@ -123,6 +123,17 @@ and fetch Maven artifacts transitively.

+ + version_conflict_policy + + optional. default is "default" +

+ Policy for user-defined vs. transitive dependency version + conflicts. If "pinned", choose the user's version unconditionally. If "default", follow + Coursier's default policy. +

+ + maven_install_json @@ -133,6 +144,17 @@ and fetch Maven artifacts transitively.

+ + override_targets + + optional. default is {} +

+ A mapping of `group:artifact` to Bazel target labels. All occurrences of the + target label for `group:artifact` will be an alias to the specified label, therefore overriding + the original generated `jvm_import` or `aar_import` target. +

+ + diff --git a/regression_testing_install.json b/regression_testing_install.json index eafb70e6e..2d27adb47 100644 --- a/regression_testing_install.json +++ b/regression_testing_install.json @@ -1,6 +1,6 @@ { "dependency_tree": { - "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": 481158695, + "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": -879763143, "conflict_resolution": {}, "dependencies": [ { @@ -984,6 +984,88 @@ "sha256": "b31c18d8d1cc8d9814f295ee7435471333f370ba5bd904ca14f8f2bec4f35c35", "url": "https://maven.google.com/com/google/android/gms/play-services-tasks/16.0.1/play-services-tasks-16.0.1.aar" }, + { + "coord": "com.google.ar.sceneform.ux:sceneform-ux:1.10.0", + "dependencies": [ + "android.arch.lifecycle:viewmodel:aar:1.1.1", + "com.android.support:customview:aar:28.0.0", + "com.google.ar.sceneform:rendering:aar:1.10.0", + "com.android.support:print:aar:28.0.0", + "com.android.support:asynclayoutinflater:aar:28.0.0", + "com.android.support:support-core-utils:aar:28.0.0", + "com.android.support:collections:28.0.0", + "com.google.ar.sceneform:filament-android:aar:1.10.0", + "com.android.support:support-fragment:aar:28.0.0", + "com.android.support:viewpager:aar:28.0.0", + "com.google.ar.sceneform:core:aar:1.10.0", + "com.google.ar:core:aar:1.10.0", + "com.android.support:interpolator:aar:28.0.0", + "com.android.support:versionedparcelable:aar:28.0.0", + "com.android.support:support-core-ui:aar:28.0.0", + "com.android.support:swiperefreshlayout:aar:28.0.0", + "android.arch.lifecycle:runtime:aar:1.1.1", + "com.android.support:support-annotations:28.0.0", + "android.arch.core:runtime:aar:1.1.1", + "com.android.support:coordinatorlayout:aar:28.0.0", + "com.android.support:loader:aar:28.0.0", + "android.arch.lifecycle:livedata:aar:1.1.1", + "com.google.ar.sceneform:sceneform-base:aar:1.10.0", + "com.android.support:support-compat:aar:28.0.0", + "com.android.support:localbroadcastmanager:aar:28.0.0", + "com.android.support:cursoradapter:aar:28.0.0", + "com.android.support:drawerlayout:aar:28.0.0", + "android.arch.lifecycle:livedata-core:aar:1.1.1", + "android.arch.lifecycle:common:1.1.1", + "com.android.support:slidingpanelayout:aar:28.0.0", + "com.android.support:documentfile:aar:28.0.0", + "android.arch.core:common:1.1.1" + ], + "file": "v1/https/maven.google.com/com/google/ar/sceneform/ux/sceneform-ux/1.10.0/sceneform-ux-1.10.0.aar", + "sha256": "f37d622f5f44facf953e23bcc01175c4f2df5f7234f71cd8855ca669d7c179fc", + "url": "https://maven.google.com/com/google/ar/sceneform/ux/sceneform-ux/1.10.0/sceneform-ux-1.10.0.aar" + }, + { + "coord": "com.google.ar.sceneform:core:aar:1.10.0", + "dependencies": [ + "com.google.ar:core:aar:1.10.0", + "com.google.ar.sceneform:sceneform-base:aar:1.10.0", + "com.google.ar.sceneform:filament-android:aar:1.10.0", + "com.google.ar.sceneform:rendering:aar:1.10.0" + ], + "file": "v1/https/maven.google.com/com/google/ar/sceneform/core/1.10.0/core-1.10.0.aar", + "sha256": "0652b7feb93b5c19ab314b79977aa739ec58c48a1bd727a4f8c31e61fe105e09", + "url": "https://maven.google.com/com/google/ar/sceneform/core/1.10.0/core-1.10.0.aar" + }, + { + "coord": "com.google.ar.sceneform:filament-android:aar:1.10.0", + "dependencies": [], + "file": "v1/https/maven.google.com/com/google/ar/sceneform/filament-android/1.10.0/filament-android-1.10.0.aar", + "sha256": "24751cbda2bfa49d5ab0d53f36efa7ac4f0b1ba6c7356c8bf418cb5a61dd067f", + "url": "https://maven.google.com/com/google/ar/sceneform/filament-android/1.10.0/filament-android-1.10.0.aar" + }, + { + "coord": "com.google.ar.sceneform:rendering:aar:1.10.0", + "dependencies": [ + "com.google.ar:core:aar:1.10.0" + ], + "file": "v1/https/maven.google.com/com/google/ar/sceneform/rendering/1.10.0/rendering-1.10.0.aar", + "sha256": "d2f6cd1d54eee0d5557518d1edcf77a3ba37494ae94f9bb862e570ee426a3431", + "url": "https://maven.google.com/com/google/ar/sceneform/rendering/1.10.0/rendering-1.10.0.aar" + }, + { + "coord": "com.google.ar.sceneform:sceneform-base:aar:1.10.0", + "dependencies": [], + "file": "v1/https/maven.google.com/com/google/ar/sceneform/sceneform-base/1.10.0/sceneform-base-1.10.0.aar", + "sha256": "fe2191f8a0b622bf35c91cdbe83074ff025f1641b6fe25ea0b554f208a62daff", + "url": "https://maven.google.com/com/google/ar/sceneform/sceneform-base/1.10.0/sceneform-base-1.10.0.aar" + }, + { + "coord": "com.google.ar:core:aar:1.10.0", + "dependencies": [], + "file": "v1/https/maven.google.com/com/google/ar/core/1.10.0/core-1.10.0.aar", + "sha256": "6624df5075cb9db0887abd6c84eb0889d1d7ba11bfd930b4e06a56eaffab820a", + "url": "https://maven.google.com/com/google/ar/core/1.10.0/core-1.10.0.aar" + }, { "coord": "com.google.code.findbugs:jsr305:3.0.2", "dependencies": [], @@ -1099,9 +1181,9 @@ "net.minidev:json-smart:1.3.1", "com.github.stephenc.jcip:jcip-annotations:1.0-1" ], - "file": "v1/https/repo1.maven.org/maven2/com/nimbusds/nimbus-jose-jwt/7.4/nimbus-jose-jwt-7.4.jar", - "sha256": "fc371f5472e4c116211178fb4c67d23a3d625ffee02488b73f5132532753b13a", - "url": "https://repo1.maven.org/maven2/com/nimbusds/nimbus-jose-jwt/7.4/nimbus-jose-jwt-7.4.jar" + "file": "v1/https/repo1.maven.org/maven2/com/nimbusds/nimbus-jose-jwt/7.5/nimbus-jose-jwt-7.5.jar", + "sha256": "d4ff9c0c37e70e55cc81061d34a017ed64267781ca37b12c6797d14318b2d085", + "url": "https://repo1.maven.org/maven2/com/nimbusds/nimbus-jose-jwt/7.5/nimbus-jose-jwt-7.5.jar" }, { "coord": "com.nimbusds:oauth2-oidc-sdk:5.24.1", diff --git a/tests/integration/override_targets/AndroidManifest.xml b/tests/integration/override_targets/AndroidManifest.xml new file mode 100644 index 000000000..e32936c71 --- /dev/null +++ b/tests/integration/override_targets/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/tests/integration/override_targets/BUILD b/tests/integration/override_targets/BUILD new file mode 100644 index 000000000..59a5a15cb --- /dev/null +++ b/tests/integration/override_targets/BUILD @@ -0,0 +1,32 @@ +load("@bazel_skylib//rules:build_test.bzl", "build_test") + +build_test( + name = "override_targets", + targets = [":app"], +) + +android_binary( + name = "app", + manifest = "AndroidManifest.xml", + custom_package = "not.used", + deps = [ + "@regression_testing//:com_google_ar_sceneform_ux_sceneform_ux" + ], +) + +# rendering-1.10.0.aar is known to have an incomplete list of dependencies in +# its POM file. We manually replace the generated target here to work around +# this issue. See https://github.com/bazelbuild/rules_jvm_external/issues/199 +# for more information. +aar_import( + name = "sceneform_rendering", + aar = "@regression_testing//:v1/https/maven.google.com/com/google/ar/sceneform/rendering/1.10.0/rendering-1.10.0.aar", + deps = [ + # Add the missing dependencies + "@regression_testing//:com_google_ar_core", + "@regression_testing//:com_google_ar_sceneform_sceneform_base", + "@regression_testing//:com_google_ar_sceneform_filament_android", + ], + tags = ["maven_coordinates=com.google.ar.sceneform:rendering:aar:1.10.0"], + visibility = ["@regression_testing//:__subpackages__"] +)