From c3b8035a9816eda2084f6a8f5ec7362fdea30783 Mon Sep 17 00:00:00 2001 From: Tyler Rockwood Date: Fri, 14 Feb 2020 14:22:10 -0600 Subject: [PATCH 01/16] Allow resources to be in a kotlin directory (#268) * Allow resources to be in a kotlin directory We just put everything in a `kotlin` directory (which the test rules allow for) so it'd be nice if resources also didn't need this prefix. * Update docs --- kotlin/internal/jvm/compile.bzl | 1 + kotlin/internal/jvm/jvm.bzl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/kotlin/internal/jvm/compile.bzl b/kotlin/internal/jvm/compile.bzl index bc94db1bf..671109533 100644 --- a/kotlin/internal/jvm/compile.bzl +++ b/kotlin/internal/jvm/compile.bzl @@ -52,6 +52,7 @@ def _fold_jars_action(ctx, rule_kind, output_jar, input_jars): _CONVENTIONAL_RESOURCE_PATHS = [ "src/main/resources", "src/test/resources", + "kotlin", ] def _adjust_resources_path_by_strip_prefix(path, resource_strip_prefix): diff --git a/kotlin/internal/jvm/jvm.bzl b/kotlin/internal/jvm/jvm.bzl index deee1cdc7..ea95acf0c 100644 --- a/kotlin/internal/jvm/jvm.bzl +++ b/kotlin/internal/jvm/jvm.bzl @@ -168,7 +168,7 @@ _common_attr = utils.add_dicts( ), "resource_strip_prefix": attr.string( doc = """The path prefix to strip from Java resources, files residing under common prefix such as - `src/main/resources` or `src/test/resources` will have stripping applied by convention.""", + `src/main/resources` or `src/test/resources` or `kotlin` will have stripping applied by convention.""", default = "", ), "resource_jars": attr.label_list( From 5e58b4b41039d24b0da265115aa8750ea37e26c8 Mon Sep 17 00:00:00 2001 From: Christian Edward Gruber Date: Tue, 18 Feb 2020 17:08:10 -0500 Subject: [PATCH 02/16] Only propagate srcjar if it isn't the default empty jar added in ae70089a2f672182d55ef8cd1bd97ec6d2370d6a to fix bazelbuild/intellij#1616 (#276) --- kotlin/internal/jvm/impl.bzl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/kotlin/internal/jvm/impl.bzl b/kotlin/internal/jvm/impl.bzl index 5c5d86d2b..fa86a71e0 100644 --- a/kotlin/internal/jvm/impl.bzl +++ b/kotlin/internal/jvm/impl.bzl @@ -73,7 +73,10 @@ def _unify_jars(ctx): else: # Legacy handling. jars = [] - source_jars = [ctx.file.srcjar] if ctx.file.srcjar else [] + if (ctx.file.srcjar and not "%s" % ctx.file.srcjar.path == "third_party/empty.jar"): + source_jars = [ctx.file.srcjar] + else: + source_jars = [] # TODO after a while remove the for block, the checks after it,and simplify the source-jar to jar allignment. # There must be a single jar jar and it can either be a filegroup or a JavaInfo. @@ -98,9 +101,7 @@ def _unify_jars(ctx): fail("got more than one jar, this is an error create an issue: %s" % jars) if len(source_jars) > 1: fail("got more than one source jar. " + - "Did you include both srcjar and a sources jar in the jars attribute?: " + - jars) - print(source_jars) + "Did you include both srcjar and a sources jar in the jars attribute?: %s" % source_jars) return struct(class_jar = jars[0], source_jar = source_jars[0] if len(source_jars) == 1 else None, ijar = None) def kt_jvm_import_impl(ctx): From df0c541ca5b38e5e1c3a208c651cc0f50a9ae065 Mon Sep 17 00:00:00 2001 From: Corbin McNeely-Smith <58151731+restingbull@users.noreply.github.com> Date: Tue, 18 Feb 2020 17:27:10 -0500 Subject: [PATCH 03/16] Remove third_party checked in jars, and properly pull maven dependencies. (#279) * Convert all dependencies to the modern equivalents. * Introduce maven_install for all maven third_party dependencies * Collected all http_* downloads into downloads.bzl, and configuration in setup.bzl. Simplifies example setup. * Remove checked in jars, fixed build references. * Fix kapt test by referencing the underlying maven jav and not using the generated jvm_import rule. There is a strange interaction with jvm_import and java_test.data. Issue: bazelbuild/rules_kotlin/issues/275 Issue: bazelbuild/rules_kotlin/issues/269 * Correct the examples to reference the dev dependencies properly. * Correct the examples to reference the dev dependencies properly. * Documentation fixes. * Fix comment spelling and revert define_kt_toolchain removal. Whoops. We should have tests for that. * fix spaces --- README.md | 26 ++- WORKSPACE | 122 +------------- examples/android/WORKSPACE | 4 + examples/dagger/BUILD | 25 +-- examples/node/WORKSPACE | 44 ++--- examples/trivial/WORKSPACE | 3 + kotlin/dependencies.bzl | 19 +++ kotlin/internal/jvm/android.bzl | 4 +- kotlin/internal/repositories/BUILD | 3 +- kotlin/internal/repositories/download.bzl | 106 +++++++++++++ .../repositories/http_java_proto_file.bzl | 105 ++++++++++++ ...ositories.bzl => release_repositories.bzl} | 0 kotlin/internal/repositories/repositories.bzl | 42 +---- kotlin/internal/repositories/setup.bzl | 63 ++++++++ src/main/kotlin/io/bazel/kotlin/builder/BUILD | 18 ++- src/main/protobuf/BUILD | 48 +++--- src/test/data/jvm/basic/BUILD | 4 +- src/test/data/jvm/kapt/BUILD | 28 ++-- src/test/kotlin/io/bazel/kotlin/BUILD | 8 +- src/test/kotlin/io/bazel/kotlin/builder/BUILD | 28 ++-- .../tasks/jvm/KotlinBuilderJvmKaptTest.java | 24 +-- third_party/BUILD | 48 +----- third_party/dependencies.yaml | 73 --------- third_party/jvm/BUILD | 0 third_party/jvm/com/google/auto/BUILD | 16 -- third_party/jvm/com/google/auto/service/BUILD | 28 ---- third_party/jvm/com/google/auto/value/BUILD | 23 --- .../jvm/com/google/code/findbugs/BUILD | 13 -- third_party/jvm/com/google/code/gson/BUILD | 13 -- third_party/jvm/com/google/dagger/BUILD | 75 --------- third_party/jvm/com/google/errorprone/BUILD | 23 --- .../jvm/com/google/googlejavaformat/BUILD | 17 -- third_party/jvm/com/google/guava/BUILD | 42 ----- third_party/jvm/com/google/j2objc/BUILD | 13 -- third_party/jvm/com/google/protobuf/BUILD | 28 ---- third_party/jvm/com/google/truth/BUILD | 21 --- .../jvm/com/googlecode/java_diff_utils/BUILD | 13 -- third_party/jvm/com/squareup/BUILD | 13 -- third_party/jvm/javax/annotation/BUILD | 13 -- third_party/jvm/javax/enterprise/BUILD | 17 -- third_party/jvm/javax/inject/BUILD | 13 -- third_party/jvm/junit/BUILD | 16 -- third_party/jvm/net/ltgt/gradle/incap/BUILD | 13 -- third_party/jvm/org/apache/ant/BUILD | 26 --- third_party/jvm/org/apache/commons/BUILD | 13 -- third_party/jvm/org/apache/maven/BUILD | 46 ------ third_party/jvm/org/checkerframework/BUILD | 23 --- third_party/jvm/org/codehaus/mojo/BUILD | 13 -- third_party/jvm/org/codehaus/plexus/BUILD | 33 ---- third_party/jvm/org/eclipse/sisu/BUILD | 30 ---- third_party/jvm/org/hamcrest/BUILD | 13 -- third_party/jvm/org/jetbrains/BUILD | 13 -- third_party/jvm/org/jetbrains/kotlin/BUILD | 43 ----- third_party/jvm/org/jetbrains/kotlinx/BUILD | 30 ---- third_party/jvm/org/ow2/asm/BUILD | 54 ------- third_party/jvm/org/pantsbuild/BUILD | 19 --- third_party/jvm/workspace.bzl | 150 ------------------ 57 files changed, 449 insertions(+), 1312 deletions(-) create mode 100644 kotlin/dependencies.bzl create mode 100644 kotlin/internal/repositories/download.bzl create mode 100644 kotlin/internal/repositories/http_java_proto_file.bzl rename kotlin/internal/repositories/{nomaven_repositories.bzl => release_repositories.bzl} (100%) create mode 100644 kotlin/internal/repositories/setup.bzl delete mode 100644 third_party/dependencies.yaml delete mode 100644 third_party/jvm/BUILD delete mode 100644 third_party/jvm/com/google/auto/BUILD delete mode 100644 third_party/jvm/com/google/auto/service/BUILD delete mode 100644 third_party/jvm/com/google/auto/value/BUILD delete mode 100644 third_party/jvm/com/google/code/findbugs/BUILD delete mode 100644 third_party/jvm/com/google/code/gson/BUILD delete mode 100644 third_party/jvm/com/google/dagger/BUILD delete mode 100644 third_party/jvm/com/google/errorprone/BUILD delete mode 100644 third_party/jvm/com/google/googlejavaformat/BUILD delete mode 100644 third_party/jvm/com/google/guava/BUILD delete mode 100644 third_party/jvm/com/google/j2objc/BUILD delete mode 100644 third_party/jvm/com/google/protobuf/BUILD delete mode 100644 third_party/jvm/com/google/truth/BUILD delete mode 100644 third_party/jvm/com/googlecode/java_diff_utils/BUILD delete mode 100644 third_party/jvm/com/squareup/BUILD delete mode 100644 third_party/jvm/javax/annotation/BUILD delete mode 100644 third_party/jvm/javax/enterprise/BUILD delete mode 100644 third_party/jvm/javax/inject/BUILD delete mode 100644 third_party/jvm/junit/BUILD delete mode 100644 third_party/jvm/net/ltgt/gradle/incap/BUILD delete mode 100644 third_party/jvm/org/apache/ant/BUILD delete mode 100644 third_party/jvm/org/apache/commons/BUILD delete mode 100644 third_party/jvm/org/apache/maven/BUILD delete mode 100644 third_party/jvm/org/checkerframework/BUILD delete mode 100644 third_party/jvm/org/codehaus/mojo/BUILD delete mode 100644 third_party/jvm/org/codehaus/plexus/BUILD delete mode 100644 third_party/jvm/org/eclipse/sisu/BUILD delete mode 100644 third_party/jvm/org/hamcrest/BUILD delete mode 100644 third_party/jvm/org/jetbrains/BUILD delete mode 100644 third_party/jvm/org/jetbrains/kotlin/BUILD delete mode 100644 third_party/jvm/org/jetbrains/kotlinx/BUILD delete mode 100644 third_party/jvm/org/ow2/asm/BUILD delete mode 100644 third_party/jvm/org/pantsbuild/BUILD delete mode 100644 third_party/jvm/workspace.bzl diff --git a/README.md b/README.md index 4a2558baf..5c972078e 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,31 @@ _(e.g. Maven artifacts)_ Third party (external) artifacts can be brought in with systems such as [`rules_jvm_external`](https://github.com/bazelbuild/rules_jvm_external) or [`bazel_maven_repository`](https://github.com/square/bazel_maven_repository) or [`bazel-deps`](https://github.com/johnynek/bazel-deps), but make sure the version you use doesn't naively use `java_import`, as this will cause bazel to make an interface-only (`ijar`), or ABI jar, and the native `ijar` tool does not know about kotlin metadata with respect to inlined functions, and will remove method bodies inappropriately. Recent versions of `rules_jvm_external` and `bazel_maven_repository` are known to work with Kotlin. +# Development Setup Guide +To use the rules directly from the rules_kotlin workspace (i.e. not the release artifact) additional dependency downloads are required. + +In the project's `WORKSPACE`, change the setup: +```python +load("//kotlin:dependencies.bzl", "kt_download_local_dev_dependencies") +kt_download_local_dev_dependencies() + + + +rules_kotlin_version = "legacy-1.3.0-rc4" +rules_kotlin_sha = "fe32ced5273bcc2f9e41cea65a28a9184a77f3bc30fea8a5c47b3d3bfc801dff" +http_archive( + name = "io_bazel_rules_kotlin", + urls = ["https://github.com/bazelbuild/rules_kotlin/archive/%s.zip" % rules_kotlin_version], + type = "zip", + strip_prefix = "rules_kotlin-%s" % rules_kotlin_version, + sha256 = rules_kotlin_sha, +) + +load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kotlin_repositories", "kt_register_toolchains") +kotlin_repositories() # if you want the default. Otherwise see custom kotlinc distribution below +kt_register_toolchains() # to use the default toolchain, otherwise see toolchains below +``` + ## Examples Examples can be found in the [examples directory](https://github.com/bazelbuild/rules_kotlin/tree/master/examples), including usage with Android, Dagger, Node-JS, etc. @@ -157,4 +182,3 @@ This project is licensed under the [Apache 2.0 license](LICENSE), as are all con See the [CONTRIBUTING](CONTRIBUTING.md) doc for information about how to contribute to this project. - diff --git a/WORKSPACE b/WORKSPACE index 4c0af828e..2dde36617 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -13,126 +13,20 @@ # limitations under the License. workspace(name = "io_bazel_rules_kotlin") -RULES_NODEJS_VERSION = "0.36.1" -RULES_NODEJS_SHA = "3356c6b767403392bab018ce91625f6d15ff8f11c6d772dc84bc9cada01c669a" -BAZEL_TOOLCHAINS_VERSION = "be10bee3010494721f08a0fccd7f57411a1e773e" -BAZEL_TOOLCHAINS_SHA = "5962fe677a43226c409316fcb321d668fc4b7fa97cb1f9ef45e7dc2676097b26" +load("//kotlin:dependencies.bzl", "kt_download_local_dev_dependencies") +kt_download_local_dev_dependencies() -SKYLIB_VERSION = "0.8.0" -SKYLIB_SHA = "2ea8a5ed2b448baf4a6855d3ce049c4c452a6470b1efd1504fdb7c1c134d220a" - -PROTOBUF_GIT_COMMIT = "09745575a923640154bcf307fba8aedff47f240a" # v3.8.0, as of 2019-05-28 -PROTOBUF_SHA = "76ee4ba47dec6146872b6cd051ae5bd12897ef0b1523d5aeb56d81a5a4ca885a" - -BAZEL_DEPS_VERSION = "0.1.0" -BAZEL_DEPS_SHA = "05498224710808be9687f5b9a906d11dd29ad592020246d4cd1a26eeaed0735e" - - -local_repository( - name = "node_example", - path = "examples/node", -) - -load("//kotlin/internal/repositories:repositories.bzl", "github_archive") - -github_archive( - name = "com_google_protobuf", - commit = PROTOBUF_GIT_COMMIT, - repo = "google/protobuf", - sha256 = PROTOBUF_SHA, -) - -load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") - -protobuf_deps() - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_jar") - -http_archive( - name = "bazel_skylib", - urls = ["https://github.com/bazelbuild/bazel-skylib/archive/%s.tar.gz" % SKYLIB_VERSION], - strip_prefix = "bazel-skylib-%s" % SKYLIB_VERSION, - sha256 = SKYLIB_SHA, -) - -http_jar( - name = "bazel_deps", - sha256 = BAZEL_DEPS_SHA, - url = "https://github.com/hsyed/bazel-deps/releases/download/v%s/parseproject_deploy.jar" % BAZEL_DEPS_VERSION, -) - -http_archive( - name = "bazel_toolchains", - sha256 = BAZEL_TOOLCHAINS_SHA, - strip_prefix = "bazel-toolchains-%s" % BAZEL_TOOLCHAINS_VERSION, - urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/%s.tar.gz" % BAZEL_TOOLCHAINS_VERSION, - "https://github.com/bazelbuild/bazel-toolchains/archive/%s.tar.gz" % BAZEL_TOOLCHAINS_VERSION, - ], -) - -load("@bazel_toolchains//rules:rbe_repo.bzl", "rbe_autoconfig") +load("//kotlin:kotlin.bzl", "kotlin_repositories", "kt_register_toolchains") +kotlin_repositories() +kt_register_toolchains() # Creates toolchain configuration for remote execution with BuildKite CI # for rbe_ubuntu1604 +load("@bazel_toolchains//rules:rbe_repo.bzl", "rbe_autoconfig") rbe_autoconfig( name = "buildkite_config", ) -load( - "//third_party/jvm:workspace.bzl", "maven_dependencies", -) - -maven_dependencies() -load("//kotlin:kotlin.bzl", "kotlin_repositories", "kt_register_toolchains") - -kotlin_repositories() - -kt_register_toolchains() - -# The following are to support building and running nodejs examples from src/test - -http_archive( - name = "build_bazel_rules_nodejs", - sha256 = RULES_NODEJS_SHA, - url = "https://github.com/bazelbuild/rules_nodejs/releases/download/{0}/rules_nodejs-{0}.tar.gz".format(RULES_NODEJS_VERSION), -) - -load("@build_bazel_rules_nodejs//:defs.bzl", "yarn_install") - -yarn_install( - name = "node_ws", - package_json = "@node_example//:package.json", - yarn_lock = "@node_example//:yarn.lock", -) - -RULES_JVM_EXTERNAL_TAG = "2.7" - -RULES_JVM_EXTERNAL_SHA = "f04b1466a00a2845106801e0c5cec96841f49ea4e7d1df88dc8e4bf31523df74" - -http_archive( - name = "rules_jvm_external", - sha256 = RULES_JVM_EXTERNAL_SHA, - strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG, - url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG, -) - -load("@rules_jvm_external//:defs.bzl", "maven_install") - -maven_install( - artifacts = [ - "org.jetbrains.kotlinx:atomicfu-js:0.13.1", - "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:1.3.2", - ], - repositories = [ - "https://maven-central.storage.googleapis.com/repos/central/data/", - "https://repo1.maven.org/maven2", - ], -) - -http_archive( - name = "rules_pkg", - url = "https://github.com/bazelbuild/rules_pkg/releases/download/0.2.4/rules_pkg-0.2.4.tar.gz", - sha256 = "4ba8f4ab0ff85f2484287ab06c0d871dcb31cc54d439457d28fd4ae14b18450a", -) \ No newline at end of file +android_sdk_repository(name = "androidsdk") +android_ndk_repository(name = "androidndk") \ No newline at end of file diff --git a/examples/android/WORKSPACE b/examples/android/WORKSPACE index f701c3868..01c672342 100644 --- a/examples/android/WORKSPACE +++ b/examples/android/WORKSPACE @@ -52,6 +52,10 @@ local_repository( path = "../..", ) + +load("@io_bazel_rules_kotlin//kotlin:dependencies.bzl", "kt_download_local_dev_dependencies") +kt_download_local_dev_dependencies() + load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kotlin_repositories", "kt_register_toolchains") kotlin_repositories() diff --git a/examples/dagger/BUILD b/examples/dagger/BUILD index 2e1ab62b7..1d567601d 100644 --- a/examples/dagger/BUILD +++ b/examples/dagger/BUILD @@ -17,27 +17,6 @@ package(default_visibility = ["//visibility:private"]) load("//kotlin:kotlin.bzl", "kt_jvm_library") -java_plugin( - name = "dagger_plugin", - processor_class = "dagger.internal.codegen.ComponentProcessor", - deps = [ - "//third_party/jvm/com/google/dagger", - "//third_party/jvm/com/google/dagger:dagger_compiler", - "//third_party/jvm/com/google/dagger:dagger_producers", - "//third_party/jvm/javax/inject:javax_inject", - "@//third_party/jvm/com/google/guava", - ], -) - -java_library( - name = "dagger_lib", - exported_plugins = ["dagger_plugin"], - exports = [ - "//third_party/jvm/com/google/dagger", - "//third_party/jvm/javax/inject:javax_inject", - ], -) - # Generate a srcjar to validate intellij plugin correctly attaches it. genrule( name = "tea_lib_src", @@ -62,8 +41,8 @@ kt_jvm_library( ":tea_lib_src", ], deps = [ - ":dagger_lib", - "//third_party/jvm/org/jetbrains/kotlinx:kotlinx_coroutines_core", + "//third_party:dagger", + "@kotlin_rules_maven//:org_jetbrains_kotlinx_kotlinx_coroutines_core", ], ) diff --git a/examples/node/WORKSPACE b/examples/node/WORKSPACE index c04a1fcee..85a682561 100644 --- a/examples/node/WORKSPACE +++ b/examples/node/WORKSPACE @@ -1,40 +1,20 @@ workspace(name = "kotlin_node_examples") +# Directly load the kotlin rules from the parent repo. local_repository( name = "io_bazel_rules_kotlin", path = "../.." ) +load("@io_bazel_rules_kotlin//kotlin:dependencies.bzl", "kt_download_local_dev_dependencies") +kt_download_local_dev_dependencies() + load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kotlin_repositories", "kt_register_toolchains") kotlin_repositories() kt_register_toolchains() +# Node example dependencies load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -http_archive( - name = "build_bazel_rules_nodejs", - sha256 = "3356c6b767403392bab018ce91625f6d15ff8f11c6d772dc84bc9cada01c669a", - urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.36.1/rules_nodejs-0.36.1.tar.gz"], -) - -load("@build_bazel_rules_nodejs//:defs.bzl", "yarn_install") - -yarn_install( - name = "node_ws", - package_json = "//:package.json", - yarn_lock = "//:yarn.lock", -) - -RULES_JVM_EXTERNAL_TAG = "2.7" - -RULES_JVM_EXTERNAL_SHA = "f04b1466a00a2845106801e0c5cec96841f49ea4e7d1df88dc8e4bf31523df74" - -http_archive( - name = "rules_jvm_external", - sha256 = RULES_JVM_EXTERNAL_SHA, - strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG, - url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG, -) - load("@rules_jvm_external//:defs.bzl", "maven_install") maven_install( @@ -49,7 +29,15 @@ maven_install( ) http_archive( - name = "rules_pkg", - url = "https://github.com/bazelbuild/rules_pkg/releases/download/0.2.4/rules_pkg-0.2.4.tar.gz", - sha256 = "4ba8f4ab0ff85f2484287ab06c0d871dcb31cc54d439457d28fd4ae14b18450a", + name = "build_bazel_rules_nodejs", + sha256 = "3356c6b767403392bab018ce91625f6d15ff8f11c6d772dc84bc9cada01c669a", + urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.36.1/rules_nodejs-0.36.1.tar.gz"], +) + +load("@build_bazel_rules_nodejs//:defs.bzl", "yarn_install") + +yarn_install( + name = "node_ws", + package_json = "//:package.json", + yarn_lock = "//:yarn.lock", ) \ No newline at end of file diff --git a/examples/trivial/WORKSPACE b/examples/trivial/WORKSPACE index 5c575e7eb..e43c98aad 100644 --- a/examples/trivial/WORKSPACE +++ b/examples/trivial/WORKSPACE @@ -5,6 +5,9 @@ local_repository( path = "../..", ) +load("@io_bazel_rules_kotlin//kotlin:dependencies.bzl", "kt_download_local_dev_dependencies") +kt_download_local_dev_dependencies() + load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kotlin_repositories", "kt_register_toolchains") kotlin_repositories() diff --git a/kotlin/dependencies.bzl b/kotlin/dependencies.bzl new file mode 100644 index 000000000..c1aa2984d --- /dev/null +++ b/kotlin/dependencies.bzl @@ -0,0 +1,19 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed 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. + + +load("//kotlin/internal/repositories:download.bzl", + _kt_download_local_dev_dependencies="kt_download_local_dev_dependencies") + +kt_download_local_dev_dependencies=_kt_download_local_dev_dependencies \ No newline at end of file diff --git a/kotlin/internal/jvm/android.bzl b/kotlin/internal/jvm/android.bzl index a1fdcfc17..ab329a713 100644 --- a/kotlin/internal/jvm/android.bzl +++ b/kotlin/internal/jvm/android.bzl @@ -22,8 +22,8 @@ def _kt_android_artifact(name, srcs = [], deps = [], plugins = [], **kwargs): """ base_name = name + "_base" kt_name = name + "_kt" - - base_deps = deps + ["@io_bazel_rules_kotlin//third_party:android_sdk"] + # TODO(bazelbuild/rules_kotlin/issues/273): This should be retrieved from a provider. + base_deps = deps + [ "@io_bazel_rules_kotlin//third_party:android_sdk" ] native.android_library( name = base_name, diff --git a/kotlin/internal/repositories/BUILD b/kotlin/internal/repositories/BUILD index 36fec980f..cd4191ac1 100644 --- a/kotlin/internal/repositories/BUILD +++ b/kotlin/internal/repositories/BUILD @@ -18,8 +18,9 @@ release_archive( srcs = [ "BUILD", "BUILD.com_github_jetbrains_kotlin", + "download.bzl" ], src_map = { - "nomaven_repositories.bzl": "repositories.bzl", + "release_repositories.bzl": "repositories.bzl", }, ) diff --git a/kotlin/internal/repositories/download.bzl b/kotlin/internal/repositories/download.bzl new file mode 100644 index 000000000..99d90f2b5 --- /dev/null +++ b/kotlin/internal/repositories/download.bzl @@ -0,0 +1,106 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed 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. +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file", "http_jar") +load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") + +RULES_NODEJS_VERSION = "0.36.1" +RULES_NODEJS_SHA = "3356c6b767403392bab018ce91625f6d15ff8f11c6d772dc84bc9cada01c669a" + +BAZEL_TOOLCHAINS_VERSION = "be10bee3010494721f08a0fccd7f57411a1e773e" +BAZEL_TOOLCHAINS_SHA = "5962fe677a43226c409316fcb321d668fc4b7fa97cb1f9ef45e7dc2676097b26" + +SKYLIB_VERSION = "0.8.0" +SKYLIB_SHA = "2ea8a5ed2b448baf4a6855d3ce049c4c452a6470b1efd1504fdb7c1c134d220a" + +PROTOBUF_GIT_COMMIT = "09745575a923640154bcf307fba8aedff47f240a" # v3.8.0, as of 2019-05-28 +PROTOBUF_SHA = "76ee4ba47dec6146872b6cd051ae5bd12897ef0b1523d5aeb56d81a5a4ca885a" + +BAZEL_DEPS_VERSION = "0.1.0" +BAZEL_DEPS_SHA = "05498224710808be9687f5b9a906d11dd29ad592020246d4cd1a26eeaed0735e" + +RULES_JVM_EXTERNAL_TAG = "2.7" +RULES_JVM_EXTERNAL_SHA = "f04b1466a00a2845106801e0c5cec96841f49ea4e7d1df88dc8e4bf31523df74" + +def kt_download_local_dev_dependencies(): + """ + Downloads all necessary http_* artifacts for rules_kotlin dev configuration. + + Must be called before setup_dependencies in the WORKSPACE. + """ + maybe( + http_archive, + name = "com_google_protobuf", + sha256 = "b404fe166de66e9a5e6dab43dc637070f950cdba2a8a4c9ed9add354ed4f6525", + strip_prefix = "protobuf-b4f193788c9f0f05d7e0879ea96cd738630e5d51", + url = "https://github.com/protocolbuffers/protobuf/archive/b4f193788c9f0f05d7e0879ea96cd738630e5d51.zip", + ) + + maybe( + http_archive, + name = "rules_proto", + sha256 = "602e7161d9195e50246177e7c55b2f39950a9cf7366f74ed5f22fd45750cd208", + strip_prefix = "rules_proto-97d8af4dc474595af3900dd85cb3a29ad28cc313", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/97d8af4dc474595af3900dd85cb3a29ad28cc313.tar.gz", + "https://github.com/bazelbuild/rules_proto/archive/97d8af4dc474595af3900dd85cb3a29ad28cc313.tar.gz", + ], + ) + + maybe( + http_archive, + name = "bazel_skylib", + urls = ["https://github.com/bazelbuild/bazel-skylib/archive/%s.tar.gz" % SKYLIB_VERSION], + strip_prefix = "bazel-skylib-%s" % SKYLIB_VERSION, + sha256 = SKYLIB_SHA, + ) + + maybe( + http_jar, + name = "bazel_deps", + sha256 = BAZEL_DEPS_SHA, + url = "https://github.com/hsyed/bazel-deps/releases/download/v%s/parseproject_deploy.jar" % BAZEL_DEPS_VERSION, + ) + + maybe( + http_archive, + name = "bazel_toolchains", + sha256 = BAZEL_TOOLCHAINS_SHA, + strip_prefix = "bazel-toolchains-%s" % BAZEL_TOOLCHAINS_VERSION, + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/%s.tar.gz" % BAZEL_TOOLCHAINS_VERSION, + "https://github.com/bazelbuild/bazel-toolchains/archive/%s.tar.gz" % BAZEL_TOOLCHAINS_VERSION, + ], + ) + + maybe( + http_archive, + name = "build_bazel_rules_nodejs", + sha256 = RULES_NODEJS_SHA, + url = "https://github.com/bazelbuild/rules_nodejs/releases/download/{0}/rules_nodejs-{0}.tar.gz".format(RULES_NODEJS_VERSION), + ) + + maybe( + http_archive, + name = "rules_jvm_external", + sha256 = RULES_JVM_EXTERNAL_SHA, + strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG, + url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG, + ) + + maybe( + http_archive, + name = "rules_pkg", + url = "https://github.com/bazelbuild/rules_pkg/releases/download/0.2.4/rules_pkg-0.2.4.tar.gz", + sha256 = "4ba8f4ab0ff85f2484287ab06c0d871dcb31cc54d439457d28fd4ae14b18450a", + ) diff --git a/kotlin/internal/repositories/http_java_proto_file.bzl b/kotlin/internal/repositories/http_java_proto_file.bzl new file mode 100644 index 000000000..3c2a2d03e --- /dev/null +++ b/kotlin/internal/repositories/http_java_proto_file.bzl @@ -0,0 +1,105 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed 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. + +def _http_java_proto_file_impl(repo_ctx): + """ See documentation below for usage. """ + repo_ctx.download( + sha256 = repo_ctx.attr.sha256, + url = repo_ctx.attr.urls, + output = repo_ctx.attr.name + ".proto", + ) + repo_ctx.file("WORKSPACE", content = """ +workspace(name = "{name}") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file") + +http_archive( + name = "rules_proto", + sha256 = "602e7161d9195e50246177e7c55b2f39950a9cf7366f74ed5f22fd45750cd208", + strip_prefix = "rules_proto-97d8af4dc474595af3900dd85cb3a29ad28cc313", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/97d8af4dc474595af3900dd85cb3a29ad28cc313.tar.gz", + "https://github.com/bazelbuild/rules_proto/archive/97d8af4dc474595af3900dd85cb3a29ad28cc313.tar.gz", + ], +) +load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains") +rules_proto_dependencies() +rules_proto_toolchains() + """.format( + name = repo_ctx.name, + )) + repo_ctx.file("BUILD", content = """ +package(default_visibility = ["//visibility:public"]) + +load("@rules_proto//proto:defs.bzl", "proto_library") +load("@rules_java//java:defs.bzl", "java_proto_library") + +proto_library( + name = "proto", + srcs = glob(["*.proto"]), +) + +java_proto_library( + name = "java_proto", + deps = [":proto"], +) +""") + +http_java_proto_file = repository_rule( + doc = """Downloads a proto file from an outside source and provides a java_proto_library in a repository. + + The java_proto_library will be made available as @//:proto. + + Example: + + WORKSPACE: + load("//kotlin/internal/repositories/http_java_proto_file.bzl", "http_java_proto_file") + + http_java_proto_file( + name = "oysters", + urls = [ + "https://west.ocean/mollusc.proto", + "https://futher_west.ocean/mollusc.proto", + ] + ) + + BUILD.bazel: + + java_library( + name = "walrus", + srcs = [...], + deps = [ + "@oysters//:proto" + ] + ) + + """, + implementation = _http_java_proto_file_impl, + attrs = { + "sha256": attr.string( + doc = """The expected SHA-256 of the file downloaded. + + This must match the SHA-256 of the file downloaded. _It is a security risk + to omit the SHA-256 as remote files can change._ At best omitting this + field will make your build non-hermetic. It is optional to make development + easier but should be set before shipping.""", + ), + "urls": attr.string_list( + mandatory = True, + doc = """A list of URLs to a file that will be made available to Bazel. + + Each entry must be a file, http or https URL. Redirections are followed. + Authentication is not supported.""", + ), + }, +) diff --git a/kotlin/internal/repositories/nomaven_repositories.bzl b/kotlin/internal/repositories/release_repositories.bzl similarity index 100% rename from kotlin/internal/repositories/nomaven_repositories.bzl rename to kotlin/internal/repositories/release_repositories.bzl diff --git a/kotlin/internal/repositories/repositories.bzl b/kotlin/internal/repositories/repositories.bzl index 2aec6e04c..1030709bc 100644 --- a/kotlin/internal/repositories/repositories.bzl +++ b/kotlin/internal/repositories/repositories.bzl @@ -13,50 +13,18 @@ # limitations under the License. """This file contains the Kotlin compiler repository definitions. It should not be loaded directly by client workspaces. """ - -load( - "@bazel_tools//tools/build_defs/repo:http.bzl", - _http_archive = "http_archive", - _http_file = "http_file", -) -load( - "//kotlin/internal:defs.bzl", - _KT_COMPILER_REPO = "KT_COMPILER_REPO", -) -load( - "//third_party/jvm:workspace.bzl", - _maven_dependencies = "maven_dependencies", -) +load("//kotlin/internal/repositories:setup.bzl", "kt_configure") load( - "//kotlin/internal/repositories:nomaven_repositories.bzl", + "//kotlin/internal/repositories:release_repositories.bzl", + _release_kotlin_repositories = "kotlin_repositories", "KOTLIN_CURRENT_COMPILER_RELEASE", - _kotlin_repositories_no_maven = "kotlin_repositories", ) -def github_archive(name, repo, commit, build_file_content = None, sha256 = None): - if build_file_content: - _http_archive( - name = name, - strip_prefix = "%s-%s" % (repo.split("/")[1], commit), - url = "https://github.com/%s/archive/%s.zip" % (repo, commit), - type = "zip", - build_file_content = build_file_content, - sha256 = sha256, - ) - else: - _http_archive( - name = name, - strip_prefix = "%s-%s" % (repo.split("/")[1], commit), - url = "https://github.com/%s/archive/%s.zip" % (repo, commit), - type = "zip", - sha256 = sha256, - ) - def kotlin_repositories(compiler_release = KOTLIN_CURRENT_COMPILER_RELEASE): """Call this in the WORKSPACE file to setup the Kotlin rules. Args: compiler_release: (internal) dict containing "urls" and "sha256" for the Kotlin compiler. """ - _maven_dependencies() - _kotlin_repositories_no_maven(compiler_release) + kt_configure() + _release_kotlin_repositories(compiler_release) diff --git a/kotlin/internal/repositories/setup.bzl b/kotlin/internal/repositories/setup.bzl new file mode 100644 index 000000000..98e01350e --- /dev/null +++ b/kotlin/internal/repositories/setup.bzl @@ -0,0 +1,63 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed 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. + +load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains") +load("@rules_jvm_external//:defs.bzl", "maven_install") +load("//kotlin/internal/repositories:http_java_proto_file.bzl", "http_java_proto_file") + +def kt_configure(): + """Setup dependencies. Must be called AFTER kt_download_local_dev_dependencies() """ + maven_install( + name = "kotlin_rules_maven", + fetch_sources = True, + artifacts = [ + "org.jetbrains.kotlinx:atomicfu-js:0.13.1", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:1.3.2", + "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1", + "com.google.code.findbugs:jsr305:3.0.2", + "junit:junit:4.13-beta-3", + "com.google.protobuf:protobuf-java:3.6.0", + "com.google.protobuf:protobuf-java-util:3.6.0", + "com.google.guava:guava:27.1-jre", + "com.google.truth:truth:0.45", + "com.google.auto.service:auto-service:1.0-rc5", + "com.google.auto.service:auto-service-annotations:1.0-rc5", + "com.google.auto.value:auto-value:1.6.5", + "com.google.auto.value:auto-value-annotations:1.6.5", + "com.google.dagger:dagger:2.26", + "com.google.dagger:dagger-compiler:2.26", + "com.google.dagger:dagger-producers:2.26", + "javax.inject:javax.inject:1", + "org.pantsbuild:jarjar:1.7.2", + ], + repositories = [ + "https://maven-central.storage.googleapis.com/repos/central/data/", + "https://repo1.maven.org/maven2", + ], + ) + + rules_proto_dependencies() + rules_proto_toolchains() + + http_java_proto_file( + name = "deps", + sha256 = "b861dbce04177df9e4b7204876b2f27e18f40eb6d20b3dffefecdd2baf3cfe92", + urls = ["https://raw.githubusercontent.com/bazelbuild/bazel/2.0.0/src/main/protobuf/deps.proto"], + ) + + http_java_proto_file( + name = "worker_protocol", + sha256 = "1157c93666f98cfcfcc9f7b073b8dac5bbd50e18f5ab981e93c71e03ed08f304", + urls = ["https://raw.githubusercontent.com/bazelbuild/bazel/2.0.0/src/main/protobuf/worker_protocol.proto"], + ) diff --git a/src/main/kotlin/io/bazel/kotlin/builder/BUILD b/src/main/kotlin/io/bazel/kotlin/builder/BUILD index 7f9ea786e..385295d17 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/BUILD +++ b/src/main/kotlin/io/bazel/kotlin/builder/BUILD @@ -22,13 +22,13 @@ kt_bootstrap_library( "utils/**/*.kt", ]), deps = [ - "//src/main/protobuf:deps", - "//src/main/protobuf:kotlin_model", - "//src/main/protobuf:worker", + "//src/main/protobuf:deps_java_proto", + "//src/main/protobuf:kotlin_model_java_proto", + "//src/main/protobuf:worker_protocol_java_proto", "@com_github_jetbrains_kotlin//:kotlin-preloader", - "@io_bazel_rules_kotlin_com_google_protobuf_protobuf_java//jar", - "@io_bazel_rules_kotlin_com_google_protobuf_protobuf_java_util//jar", - "@io_bazel_rules_kotlin_javax_inject_javax_inject//jar", + "@kotlin_rules_maven//:com_google_protobuf_protobuf_java", + "@kotlin_rules_maven//:com_google_protobuf_protobuf_java_util", + "@kotlin_rules_maven//:javax_inject_javax_inject", ], ) @@ -43,10 +43,12 @@ java_library( ], deps = [ ":builder_kt", - "//src/main/protobuf:kotlin_model", + "//src/main/protobuf:deps_java_proto", + "//src/main/protobuf:kotlin_model_java_proto", + "//src/main/protobuf:worker_protocol_java_proto", "//third_party:dagger", "@com_github_jetbrains_kotlin//:annotations", "@com_github_jetbrains_kotlin//:kotlin-stdlib", - "@io_bazel_rules_kotlin_com_google_protobuf_protobuf_java//jar", + "@kotlin_rules_maven//:javax_inject_javax_inject", ], ) diff --git a/src/main/protobuf/BUILD b/src/main/protobuf/BUILD index 3ac044207..2027df051 100644 --- a/src/main/protobuf/BUILD +++ b/src/main/protobuf/BUILD @@ -15,6 +15,19 @@ load("@rules_java//java:defs.bzl", "java_import") package(default_visibility = ["//visibility:public"]) +load("@rules_proto//proto:defs.bzl", "proto_library") +load("@rules_java//java:defs.bzl", "java_proto_library") + +alias( + name = "deps_java_proto", + actual = "@deps//:java_proto", +) + +alias( + name = "worker_protocol_java_proto", + actual = "@worker_protocol//:java_proto", +) + proto_library( name = "kotlin_model_proto", srcs = [":kotlin_model.proto"], @@ -26,32 +39,11 @@ java_proto_library( deps = [":kotlin_model_proto"], ) -_PROTO_LIBS = [ - "deps", - "worker_protocol", -] - -[proto_library( - name = "%s_proto" % lib, - srcs = ["%s.proto" % lib], -) for lib in _PROTO_LIBS] - -[java_proto_library( - name = "%s_java_proto" % lib, - deps = ["%s_proto" % lib], -) for lib in _PROTO_LIBS] - -java_import( - name = "deps", - jars = ["jars/libdeps_proto-speed.jar"], -) - -java_import( - name = "worker", - jars = ["jars/libworker_protocol_proto-speed.jar"], -) - -java_import( - name = "kotlin_model", - jars = ["jars/libkotlin_model_proto-speed.jar"], +java_library( + name = "protobuf", + exports = [ + ":deps_java_proto", + ":kotlin_model_java_proto", + ":worker_protocol_java_proto", + ], ) diff --git a/src/test/data/jvm/basic/BUILD b/src/test/data/jvm/basic/BUILD index e4c00c8f1..5a3764e00 100644 --- a/src/test/data/jvm/basic/BUILD +++ b/src/test/data/jvm/basic/BUILD @@ -73,13 +73,13 @@ kt_jvm_library( kt_jvm_library( name = "propagation_test_exporter_lib", srcs = ["propagation/Stub.kt"], - exports = ["//third_party/jvm/junit"], + exports = ["@kotlin_rules_maven//:junit_junit"], ) kt_jvm_library( name = "propagation_test_runtime_lib", srcs = ["propagation/Stub.kt"], - runtime_deps = ["//third_party/jvm/junit"], + runtime_deps = ["@kotlin_rules_maven//:junit_junit"], ) java_binary( diff --git a/src/test/data/jvm/kapt/BUILD b/src/test/data/jvm/kapt/BUILD index 2a7d786fb..dc3d7e557 100644 --- a/src/test/data/jvm/kapt/BUILD +++ b/src/test/data/jvm/kapt/BUILD @@ -20,27 +20,27 @@ java_plugin( name = "autovalue", generates_api = 1, processor_class = "com.google.auto.value.processor.AutoValueProcessor", - deps = ["//third_party/jvm/com/google/auto/value:auto_value"], + deps = ["@kotlin_rules_maven//:com_google_auto_value_auto_value"], ) java_plugin( name = "autoservice", generates_api = 0, processor_class = "com.google.auto.service.processor.AutoServiceProcessor", - deps = ["//third_party/jvm/com/google/auto/service:auto_service"], + deps = ["@kotlin_rules_maven//:com_google_auto_service_auto_service"], ) java_plugin( name = "autovalue_no_processor_class", generates_api = 1, - deps = ["//third_party/jvm/com/google/auto/value:auto_value_annotations"], + deps = ["@kotlin_rules_maven//:com_google_auto_value_auto_value_annotations"], ) kt_jvm_library( name = "ap_kotlin", srcs = ["kotlin/TestKtValue.kt"], plugins = [":autovalue"], - deps = ["//third_party/jvm/com/google/auto/value:auto_value_annotations"], + deps = ["@kotlin_rules_maven//:com_google_auto_value_auto_value_annotations"], ) kt_jvm_library( @@ -49,7 +49,7 @@ kt_jvm_library( "java/TestAPNoGenReferences.java", "kotlin/TestKtAPNoGenReference.kt", ], - deps = ["//third_party/jvm/com/google/auto/value:auto_value_annotations"], + deps = ["@kotlin_rules_maven//:com_google_auto_value_auto_value_annotations"], ) kt_jvm_library( @@ -59,14 +59,14 @@ kt_jvm_library( "kotlin/TestKtValue.kt", ], plugins = [":autovalue"], - deps = ["//third_party/jvm/com/google/auto/value:auto_value_annotations"], + deps = ["@kotlin_rules_maven//:com_google_auto_value_auto_value_annotations"], ) kt_jvm_library( name = "ap_kotlin_resources", srcs = ["kotlin/TestKtService.kt"], plugins = [":autoservice"], - deps = ["//third_party/jvm/com/google/auto/service:auto_service_annotations"], + deps = ["@kotlin_rules_maven//:com_google_auto_service_auto_service_annotations"], ) kt_jvm_library( @@ -76,7 +76,7 @@ kt_jvm_library( "kotlin/TestKtService.kt", ], plugins = [":autoservice"], - deps = ["//third_party/jvm/com/google/auto/service:auto_service_annotations"], + deps = ["@kotlin_rules_maven//:com_google_auto_service_auto_service_annotations"], ) kt_jvm_library( @@ -92,8 +92,8 @@ kt_jvm_library( ":autovalue", ], deps = [ - "//third_party/jvm/com/google/auto/service:auto_service_annotations", - "//third_party/jvm/com/google/auto/value:auto_value_annotations", + "@kotlin_rules_maven//:com_google_auto_service_auto_service_annotations", + "@kotlin_rules_maven//:com_google_auto_value_auto_value_annotations", ], ) @@ -110,8 +110,8 @@ kt_jvm_library( ":autovalue_no_processor_class", ], deps = [ - "//third_party/jvm/com/google/auto/service:auto_service_annotations", - "//third_party/jvm/com/google/auto/value:auto_value_annotations", + "@kotlin_rules_maven//:com_google_auto_service_auto_service_annotations", + "@kotlin_rules_maven//:com_google_auto_value_auto_value_annotations", ], ) @@ -134,8 +134,8 @@ kt_jvm_library( plugins = [":autovalue"], deps = [ "library_exporting_autovalue_and_junit", - "//third_party/jvm/com/google/auto/service:auto_service_annotations", - "//third_party/jvm/com/google/auto/value:auto_value_annotations", + "@kotlin_rules_maven//:com_google_auto_service_auto_service_annotations", + "@kotlin_rules_maven//:com_google_auto_value_auto_value_annotations", ], ) diff --git a/src/test/kotlin/io/bazel/kotlin/BUILD b/src/test/kotlin/io/bazel/kotlin/BUILD index 97707afef..b291c8f8c 100644 --- a/src/test/kotlin/io/bazel/kotlin/BUILD +++ b/src/test/kotlin/io/bazel/kotlin/BUILD @@ -22,14 +22,14 @@ kt_jvm_library( srcs = ["KotlinAssertionTestCase.kt"], visibility = ["//visibility:public"], exports = [ - "//third_party/jvm/com/google/truth", - "//third_party/jvm/junit", "@com_github_jetbrains_kotlin//:kotlin-test", - "@io_bazel_rules_kotlin_com_google_guava_guava//jar", + "@kotlin_rules_maven//:com_google_guava_guava", + "@kotlin_rules_maven//:com_google_truth_truth", + "@kotlin_rules_maven//:junit_junit", ], deps = [ "@com_github_jetbrains_kotlin//:kotlin-test", - "@io_bazel_rules_kotlin_com_google_guava_guava//jar", + "@kotlin_rules_maven//:com_google_guava_guava", ], ) diff --git a/src/test/kotlin/io/bazel/kotlin/builder/BUILD b/src/test/kotlin/io/bazel/kotlin/builder/BUILD index fdbda59c1..37db8ff13 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/BUILD +++ b/src/test/kotlin/io/bazel/kotlin/builder/BUILD @@ -18,11 +18,12 @@ load("//src/test/kotlin/io/bazel/kotlin:defs.bzl", "kt_rules_test") _COMMON_DEPS = [ "//src/main/kotlin/io/bazel/kotlin/builder", - "//src/main/protobuf:kotlin_model", - "//third_party/jvm/com/google/truth", - "//third_party/jvm/junit", - "//third_party/jvm/com/google/guava", - "//third_party/jvm/com/google/code/findbugs:jsr305", + "//src/main/protobuf:kotlin_model_java_proto", + "//src/main/protobuf:deps_java_proto", + "@kotlin_rules_maven//:com_google_truth_truth", + "@kotlin_rules_maven//:junit_junit", + "@kotlin_rules_maven//:com_google_guava_guava", + "@kotlin_rules_maven//:com_google_code_findbugs_jsr305", ] java_library( @@ -40,8 +41,7 @@ java_library( "@com_github_jetbrains_kotlin//:home", ], exports = _COMMON_DEPS + [ - "@io_bazel_rules_kotlin_com_google_protobuf_protobuf_java//jar", - "//src/main/protobuf:deps", + "@kotlin_rules_maven//:com_google_protobuf_protobuf_java", ], runtime_deps = [ "@com_github_jetbrains_kotlin//:kotlin-reflect", @@ -67,12 +67,22 @@ kt_rules_test( srcs = ["tasks/jvm/KotlinBuilderJvmBasicTest.java"], ) +# TODO(bazelbuild/rules_kotlin/issues/275): Remove full jar reference when the kt_rules_test handles jvm_import data better. +_MAVEN_CENTRAL_PREFIX = "@kotlin_rules_maven//:v1/https/maven-central.storage.googleapis.com/repos/central/data" +_AUTO_VALUE_PREFIX = "%s/com/google/auto/value" % _MAVEN_CENTRAL_PREFIX +_AUTO_VALUE_JAR = _AUTO_VALUE_PREFIX+ "/auto-value/1.6.5/auto-value-1.6.5.jar" +_AUTO_VALUE_ANNOTATIONS_JAR = _AUTO_VALUE_PREFIX+ "/auto-value-annotations/1.6.5/auto-value-annotations-1.6.5.jar" + kt_rules_test( name = "KotlinBuilderJvmKaptTest", srcs = ["tasks/jvm/KotlinBuilderJvmKaptTest.java"], data = [ - "//third_party/jvm/com/google/auto/value:auto_value", - "//third_party/jvm/com/google/auto/value:auto_value_annotations", + _AUTO_VALUE_JAR, + _AUTO_VALUE_ANNOTATIONS_JAR, + ], + jvm_flags = [ + "-Dauto_value=$(location %s)" % _AUTO_VALUE_JAR, + "-Dauto_value_annotations=$(location %s)" % _AUTO_VALUE_ANNOTATIONS_JAR, ], ) diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmKaptTest.java b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmKaptTest.java index 4091aba0c..e68f5b3d9 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmKaptTest.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmKaptTest.java @@ -23,29 +23,31 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import java.io.File; import java.util.function.Consumer; import java.util.stream.Collectors; -import static io.bazel.kotlin.builder.KotlinJvmTestBuilder.*; +import static io.bazel.kotlin.builder.KotlinJvmTestBuilder.KOTLIN_ANNOTATIONS; +import static io.bazel.kotlin.builder.KotlinJvmTestBuilder.KOTLIN_STDLIB; @RunWith(JUnit4.class) public class KotlinBuilderJvmKaptTest { private static final Dep AUTO_VALUE_ANNOTATIONS = Dep.importJar( "autovalue_annotations", - "external/io_bazel_rules_kotlin_com_google_auto_value_auto_value_annotations" - + "/jar/io_bazel_rules_kotlin_com_google_auto_value_auto_value_annotations.jar"); + System.getProperty("auto_value_annotations") + .replaceFirst("external" + File.separator, "")); private static final Dep AUTO_VALUE = Dep.importJar( "autovalue", - "external/io_bazel_rules_kotlin_com_google_auto_value_auto_value" - + "/jar/io_bazel_rules_kotlin_com_google_auto_value_auto_value.jar"); - private static final AnnotationProcessor AUTO_VALUE_ANNOTATION_PROCESSOR = - AnnotationProcessor.builder() - .processClass("com.google.auto.value.processor.AutoValueProcessor") - .processorPath( - Dep.classpathOf(AUTO_VALUE_ANNOTATIONS, AUTO_VALUE, KOTLIN_ANNOTATIONS).collect(Collectors.toSet())) - .build(); + System.getProperty("auto_value") + .replaceFirst("external" + File.separator, "")); + private static final AnnotationProcessor AUTO_VALUE_ANNOTATION_PROCESSOR = + AnnotationProcessor.builder() + .processClass("com.google.auto.value.processor.AutoValueProcessor") + .processorPath( + Dep.classpathOf(AUTO_VALUE_ANNOTATIONS, AUTO_VALUE, KOTLIN_ANNOTATIONS).collect(Collectors.toSet())) + .build(); private static final KotlinJvmTestBuilder ctx = new KotlinJvmTestBuilder(); diff --git a/third_party/BUILD b/third_party/BUILD index ce1fb71a2..8c463f0e3 100644 --- a/third_party/BUILD +++ b/third_party/BUILD @@ -19,54 +19,19 @@ load("//kotlin/internal/utils:packager.bzl", "release_archive") exports_files(["empty.jar"]) -java_binary( - name = "bazel_deps", - main_class = "com.github.johnynek.bazel_deps.ParseProject", - runtime_deps = ["@bazel_deps//jar"], -) - -sh_test( - name = "force_import_load_test", - srcs = ["//:scripts/noop.sh"], - data = [":force_import_load_deploy.jar"], -) - -# This binary isn't used except to test the two usages of kt_jvm_import below. -java_binary( - name = "force_import_load", - create_executable = False, - runtime_deps = [ - ":kotlinx_coroutines", - ":kotlinx_coroutines_common", - ], -) - -kt_jvm_import( - name = "kotlinx_coroutines", - jars = [ - "@io_bazel_rules_kotlin_org_jetbrains_kotlinx_kotlinx_coroutines_core//jar", - ], -) - -kt_jvm_import( - name = "kotlinx_coroutines_common", - jar = "@io_bazel_rules_kotlin_org_jetbrains_kotlinx_kotlinx_coroutines_core_common//jar:io_bazel_rules_kotlin_org_jetbrains_kotlinx_kotlinx_coroutines_core_common.jar", - srcjar = "@io_bazel_rules_kotlin_org_jetbrains_kotlinx_kotlinx_coroutines_core_common//jar:io_bazel_rules_kotlin_org_jetbrains_kotlinx_kotlinx_coroutines_core_common-sources.jar", -) - java_plugin( name = "autovalue_plugin", generates_api = 1, processor_class = "com.google.auto.value.processor.AutoValueProcessor", visibility = ["//visibility:private"], - deps = ["//third_party/jvm/com/google/auto/value:auto_value"], + deps = ["@kotlin_rules_maven//:com_google_auto_value_auto_value"], ) java_library( name = "autovalue", exported_plugins = [":autovalue_plugin"], neverlink = 1, - exports = ["//third_party/jvm/com/google/auto/value:auto_value_annotations"], + exports = ["@kotlin_rules_maven//:com_google_auto_value_auto_value_annotations"], ) java_plugin( @@ -75,7 +40,7 @@ java_plugin( processor_class = "dagger.internal.codegen.ComponentProcessor", visibility = ["//visibility:private"], deps = [ - "//third_party/jvm/com/google/dagger:dagger_compiler", + "@kotlin_rules_maven//:com_google_dagger_dagger_compiler", ], ) @@ -83,8 +48,8 @@ java_library( name = "dagger", exported_plugins = [":dagger_component_plugin"], exports = [ - "//third_party/jvm/com/google/dagger", - "//third_party/jvm/javax/inject:javax_inject", + "@kotlin_rules_maven//:com_google_dagger_dagger", + "@kotlin_rules_maven//:javax_inject_javax_inject", ], ) @@ -92,9 +57,10 @@ java_binary( name = "jarjar_runner", main_class = "org.pantsbuild.jarjar.Main", visibility = ["//visibility:public"], - runtime_deps = ["//third_party/jvm/org/pantsbuild:jarjar"], + runtime_deps = ["@kotlin_rules_maven//:org_pantsbuild_jarjar"], ) +# TODO(bazelbuild/rules_kotlin/issues/273): Remove android_sdk import. java_import( name = "android_sdk", jars = ["@bazel_tools//tools/android:android_jar"], diff --git a/third_party/dependencies.yaml b/third_party/dependencies.yaml deleted file mode 100644 index 82f7a7e67..000000000 --- a/third_party/dependencies.yaml +++ /dev/null @@ -1,73 +0,0 @@ -options: - thirdPartyDirectory: "third_party/jvm" - buildHeader: [ 'licenses(["notice"])' ] - resolvers: - - id: "mavencentral" - type: "default" - url: https://repo.maven.apache.org/maven2/ - resolverType: coursier - transitivity: runtime_deps - versionConflictPolicy: highest - namePrefix: "io_bazel_rules_kotlin_" - -dependencies: - com.google.code.findbugs: - jsr305: - lang: "java" - version: "3.0.2" - junit: - junit: - lang: "java" - version: "4.13-beta-3" - com.google.protobuf: - protobuf: - modules: ["java", "java-util"] - lang: "java" - version: "3.6.0" - com.google.guava: - guava: - lang: "java" - version: "27.1-jre" - com.google.truth: - truth: - lang: "java" - version: "0.45" - com.google.auto.service: - auto-service: - modules: ["", "annotations"] - lang: "java" - version: "1.0-rc5" - com.google.auto.value: - auto-value: - modules: ["", "annotations"] - lang: "java" - version: "1.6.5" - com.google.dagger: - dagger: - modules: ["", "compiler", "producers"] - lang: "java" - version: "2.23.1" - javax.inject: - javax.inject: - lang: "java" - version: "1" - org.jetbrains.kotlinx: - kotlinx-coroutines: - modules: ["core"] - lang: "java" - version : "1.1.1" - org.pantsbuild: - jarjar: - lang: "java" - version: "1.7.2" -replacements: - org.jetbrains.kotlin: - kotlin-stdlib: - lang: java - target: "@com_github_jetbrains_kotlin//:kotlin-stdlib" - kotlin-reflect: - lang: java - target: "@com_github_jetbrains_kotlin//:kotlin-reflect" - kotlin-script-runtime: - lang: java - target: "@com_github_jetbrains_kotlin//:kotlin-script-runtime" diff --git a/third_party/jvm/BUILD b/third_party/jvm/BUILD deleted file mode 100644 index e69de29bb..000000000 diff --git a/third_party/jvm/com/google/auto/BUILD b/third_party/jvm/com/google/auto/BUILD deleted file mode 100644 index d52db146c..000000000 --- a/third_party/jvm/com/google/auto/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "auto_common", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/auto/auto_common", - ], - runtime_deps = [ - "//third_party/jvm/com/google/guava", - ], -) diff --git a/third_party/jvm/com/google/auto/service/BUILD b/third_party/jvm/com/google/auto/service/BUILD deleted file mode 100644 index 8a7915147..000000000 --- a/third_party/jvm/com/google/auto/service/BUILD +++ /dev/null @@ -1,28 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "auto_service", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/auto/service/auto_service", - ], - runtime_deps = [ - ":auto_service_annotations", - "//third_party/jvm/com/google/auto:auto_common", - "//third_party/jvm/com/google/guava", - ], -) - -java_library( - name = "auto_service_annotations", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/auto/service/auto_service_annotations", - ], -) diff --git a/third_party/jvm/com/google/auto/value/BUILD b/third_party/jvm/com/google/auto/value/BUILD deleted file mode 100644 index 73e6ed243..000000000 --- a/third_party/jvm/com/google/auto/value/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "auto_value", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/auto/value/auto_value", - ], -) - -java_library( - name = "auto_value_annotations", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/auto/value/auto_value_annotations", - ], -) diff --git a/third_party/jvm/com/google/code/findbugs/BUILD b/third_party/jvm/com/google/code/findbugs/BUILD deleted file mode 100644 index bd909a620..000000000 --- a/third_party/jvm/com/google/code/findbugs/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "jsr305", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/code/findbugs/jsr305", - ], -) diff --git a/third_party/jvm/com/google/code/gson/BUILD b/third_party/jvm/com/google/code/gson/BUILD deleted file mode 100644 index 7132c4f4d..000000000 --- a/third_party/jvm/com/google/code/gson/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "gson", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/code/gson/gson", - ], -) diff --git a/third_party/jvm/com/google/dagger/BUILD b/third_party/jvm/com/google/dagger/BUILD deleted file mode 100644 index 56446df89..000000000 --- a/third_party/jvm/com/google/dagger/BUILD +++ /dev/null @@ -1,75 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "dagger", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/dagger/dagger", - ], - runtime_deps = [ - "//third_party/jvm/javax/inject:javax_inject", - ], -) - -java_library( - name = "dagger_compiler", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/dagger/dagger_compiler", - ], - runtime_deps = [ - ":dagger", - ":dagger_producers", - ":dagger_spi", - "//third_party/jvm/com/google/googlejavaformat:google_java_format", - "//third_party/jvm/com/google/guava", - "//third_party/jvm/com/google/guava:failureaccess", - "//third_party/jvm/com/google/protobuf:protobuf_java", - "//third_party/jvm/com/squareup:javapoet", - "//third_party/jvm/javax/annotation:jsr250_api", - "//third_party/jvm/javax/inject:javax_inject", - "//third_party/jvm/net/ltgt/gradle/incap", - "//third_party/jvm/org/checkerframework:checker_compat_qual", - ], -) - -java_library( - name = "dagger_producers", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/dagger/dagger_producers", - ], - runtime_deps = [ - ":dagger", - "//third_party/jvm/com/google/guava", - "//third_party/jvm/com/google/guava:failureaccess", - "//third_party/jvm/javax/inject:javax_inject", - "//third_party/jvm/org/checkerframework:checker_compat_qual", - ], -) - -java_library( - name = "dagger_spi", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/dagger/dagger_spi", - ], - runtime_deps = [ - ":dagger", - ":dagger_producers", - "//third_party/jvm/com/google/guava", - "//third_party/jvm/com/google/guava:failureaccess", - "//third_party/jvm/com/squareup:javapoet", - "//third_party/jvm/javax/inject:javax_inject", - ], -) diff --git a/third_party/jvm/com/google/errorprone/BUILD b/third_party/jvm/com/google/errorprone/BUILD deleted file mode 100644 index 05ce5d004..000000000 --- a/third_party/jvm/com/google/errorprone/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "error_prone_annotations", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/errorprone/error_prone_annotations", - ], -) - -java_library( - name = "javac_shaded", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/errorprone/javac_shaded", - ], -) diff --git a/third_party/jvm/com/google/googlejavaformat/BUILD b/third_party/jvm/com/google/googlejavaformat/BUILD deleted file mode 100644 index 5368a3860..000000000 --- a/third_party/jvm/com/google/googlejavaformat/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "google_java_format", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/googlejavaformat/google_java_format", - ], - runtime_deps = [ - "//third_party/jvm/com/google/errorprone:javac_shaded", - "//third_party/jvm/com/google/guava", - ], -) diff --git a/third_party/jvm/com/google/guava/BUILD b/third_party/jvm/com/google/guava/BUILD deleted file mode 100644 index 8339049ce..000000000 --- a/third_party/jvm/com/google/guava/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "failureaccess", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/guava/failureaccess", - ], -) - -java_library( - name = "guava", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/guava/guava", - ], - runtime_deps = [ - ":failureaccess", - ":listenablefuture", - "//third_party/jvm/com/google/code/findbugs:jsr305", - "//third_party/jvm/com/google/errorprone:error_prone_annotations", - "//third_party/jvm/com/google/j2objc:j2objc_annotations", - "//third_party/jvm/org/checkerframework:checker_qual", - "//third_party/jvm/org/codehaus/mojo:animal_sniffer_annotations", - ], -) - -java_library( - name = "listenablefuture", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/guava/listenablefuture", - ], -) diff --git a/third_party/jvm/com/google/j2objc/BUILD b/third_party/jvm/com/google/j2objc/BUILD deleted file mode 100644 index b22b0bb87..000000000 --- a/third_party/jvm/com/google/j2objc/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "j2objc_annotations", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/j2objc/j2objc_annotations", - ], -) diff --git a/third_party/jvm/com/google/protobuf/BUILD b/third_party/jvm/com/google/protobuf/BUILD deleted file mode 100644 index 65a2a5d1c..000000000 --- a/third_party/jvm/com/google/protobuf/BUILD +++ /dev/null @@ -1,28 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "protobuf_java", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/protobuf/protobuf_java", - ], -) - -java_library( - name = "protobuf_java_util", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/protobuf/protobuf_java_util", - ], - runtime_deps = [ - ":protobuf_java", - "//third_party/jvm/com/google/code/gson", - "//third_party/jvm/com/google/guava", - ], -) diff --git a/third_party/jvm/com/google/truth/BUILD b/third_party/jvm/com/google/truth/BUILD deleted file mode 100644 index 84e5fe6fc..000000000 --- a/third_party/jvm/com/google/truth/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "truth", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/google/truth/truth", - ], - runtime_deps = [ - "//third_party/jvm/com/google/auto/value:auto_value_annotations", - "//third_party/jvm/com/google/errorprone:error_prone_annotations", - "//third_party/jvm/com/google/guava", - "//third_party/jvm/com/googlecode/java_diff_utils:diffutils", - "//third_party/jvm/junit", - "//third_party/jvm/org/checkerframework:checker_compat_qual", - ], -) diff --git a/third_party/jvm/com/googlecode/java_diff_utils/BUILD b/third_party/jvm/com/googlecode/java_diff_utils/BUILD deleted file mode 100644 index e02c2ad3c..000000000 --- a/third_party/jvm/com/googlecode/java_diff_utils/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "diffutils", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/googlecode/java_diff_utils/diffutils", - ], -) diff --git a/third_party/jvm/com/squareup/BUILD b/third_party/jvm/com/squareup/BUILD deleted file mode 100644 index 0c949346a..000000000 --- a/third_party/jvm/com/squareup/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "javapoet", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_com/squareup/javapoet", - ], -) diff --git a/third_party/jvm/javax/annotation/BUILD b/third_party/jvm/javax/annotation/BUILD deleted file mode 100644 index 728f91322..000000000 --- a/third_party/jvm/javax/annotation/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "jsr250_api", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_javax/annotation/jsr250_api", - ], -) diff --git a/third_party/jvm/javax/enterprise/BUILD b/third_party/jvm/javax/enterprise/BUILD deleted file mode 100644 index 71ea88690..000000000 --- a/third_party/jvm/javax/enterprise/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "cdi_api", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_javax/enterprise/cdi_api", - ], - runtime_deps = [ - "//third_party/jvm/javax/annotation:jsr250_api", - "//third_party/jvm/javax/inject:javax_inject", - ], -) diff --git a/third_party/jvm/javax/inject/BUILD b/third_party/jvm/javax/inject/BUILD deleted file mode 100644 index 6ada6c9c4..000000000 --- a/third_party/jvm/javax/inject/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "javax_inject", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_javax/inject/javax_inject", - ], -) diff --git a/third_party/jvm/junit/BUILD b/third_party/jvm/junit/BUILD deleted file mode 100644 index 6fa39df42..000000000 --- a/third_party/jvm/junit/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "junit", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_junit/junit", - ], - runtime_deps = [ - "//third_party/jvm/org/hamcrest:hamcrest_core", - ], -) diff --git a/third_party/jvm/net/ltgt/gradle/incap/BUILD b/third_party/jvm/net/ltgt/gradle/incap/BUILD deleted file mode 100644 index 2030dc700..000000000 --- a/third_party/jvm/net/ltgt/gradle/incap/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "incap", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_net/ltgt/gradle/incap/incap", - ], -) diff --git a/third_party/jvm/org/apache/ant/BUILD b/third_party/jvm/org/apache/ant/BUILD deleted file mode 100644 index 5ed5ff2c1..000000000 --- a/third_party/jvm/org/apache/ant/BUILD +++ /dev/null @@ -1,26 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "ant", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/apache/ant/ant", - ], - runtime_deps = [ - ":ant_launcher", - ], -) - -java_library( - name = "ant_launcher", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/apache/ant/ant_launcher", - ], -) diff --git a/third_party/jvm/org/apache/commons/BUILD b/third_party/jvm/org/apache/commons/BUILD deleted file mode 100644 index 901886c3b..000000000 --- a/third_party/jvm/org/apache/commons/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "commons_lang3", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/apache/commons/commons_lang3", - ], -) diff --git a/third_party/jvm/org/apache/maven/BUILD b/third_party/jvm/org/apache/maven/BUILD deleted file mode 100644 index b05c3c1b3..000000000 --- a/third_party/jvm/org/apache/maven/BUILD +++ /dev/null @@ -1,46 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "maven_artifact", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/apache/maven/maven_artifact", - ], - runtime_deps = [ - "//third_party/jvm/org/apache/commons:commons_lang3", - "//third_party/jvm/org/codehaus/plexus:plexus_utils", - ], -) - -java_library( - name = "maven_model", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/apache/maven/maven_model", - ], - runtime_deps = [ - "//third_party/jvm/org/apache/commons:commons_lang3", - "//third_party/jvm/org/codehaus/plexus:plexus_utils", - ], -) - -java_library( - name = "maven_plugin_api", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/apache/maven/maven_plugin_api", - ], - runtime_deps = [ - ":maven_artifact", - ":maven_model", - "//third_party/jvm/org/eclipse/sisu:org_eclipse_sisu_plexus", - ], -) diff --git a/third_party/jvm/org/checkerframework/BUILD b/third_party/jvm/org/checkerframework/BUILD deleted file mode 100644 index fea35efe4..000000000 --- a/third_party/jvm/org/checkerframework/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "checker_compat_qual", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/checkerframework/checker_compat_qual", - ], -) - -java_library( - name = "checker_qual", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/checkerframework/checker_qual", - ], -) diff --git a/third_party/jvm/org/codehaus/mojo/BUILD b/third_party/jvm/org/codehaus/mojo/BUILD deleted file mode 100644 index 89f3b8696..000000000 --- a/third_party/jvm/org/codehaus/mojo/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "animal_sniffer_annotations", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/codehaus/mojo/animal_sniffer_annotations", - ], -) diff --git a/third_party/jvm/org/codehaus/plexus/BUILD b/third_party/jvm/org/codehaus/plexus/BUILD deleted file mode 100644 index a7e9d65d4..000000000 --- a/third_party/jvm/org/codehaus/plexus/BUILD +++ /dev/null @@ -1,33 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "plexus_classworlds", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/codehaus/plexus/plexus_classworlds", - ], -) - -java_library( - name = "plexus_component_annotations", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/codehaus/plexus/plexus_component_annotations", - ], -) - -java_library( - name = "plexus_utils", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/codehaus/plexus/plexus_utils", - ], -) diff --git a/third_party/jvm/org/eclipse/sisu/BUILD b/third_party/jvm/org/eclipse/sisu/BUILD deleted file mode 100644 index 9a6e27c88..000000000 --- a/third_party/jvm/org/eclipse/sisu/BUILD +++ /dev/null @@ -1,30 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "org_eclipse_sisu_inject", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/eclipse/sisu/org_eclipse_sisu_inject", - ], -) - -java_library( - name = "org_eclipse_sisu_plexus", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/eclipse/sisu/org_eclipse_sisu_plexus", - ], - runtime_deps = [ - ":org_eclipse_sisu_inject", - "//third_party/jvm/javax/enterprise:cdi_api", - "//third_party/jvm/org/codehaus/plexus:plexus_classworlds", - "//third_party/jvm/org/codehaus/plexus:plexus_component_annotations", - "//third_party/jvm/org/codehaus/plexus:plexus_utils", - ], -) diff --git a/third_party/jvm/org/hamcrest/BUILD b/third_party/jvm/org/hamcrest/BUILD deleted file mode 100644 index 5adbd74b3..000000000 --- a/third_party/jvm/org/hamcrest/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "hamcrest_core", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/hamcrest/hamcrest_core", - ], -) diff --git a/third_party/jvm/org/jetbrains/BUILD b/third_party/jvm/org/jetbrains/BUILD deleted file mode 100644 index 4048991f0..000000000 --- a/third_party/jvm/org/jetbrains/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "annotations", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/jetbrains/annotations", - ], -) diff --git a/third_party/jvm/org/jetbrains/kotlin/BUILD b/third_party/jvm/org/jetbrains/kotlin/BUILD deleted file mode 100644 index 7615cb378..000000000 --- a/third_party/jvm/org/jetbrains/kotlin/BUILD +++ /dev/null @@ -1,43 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "kotlin_reflect", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "@com_github_jetbrains_kotlin//:kotlin-reflect", - ], -) - -java_library( - name = "kotlin_script_runtime", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "@com_github_jetbrains_kotlin//:kotlin-script-runtime", - ], -) - -java_library( - name = "kotlin_stdlib", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "@com_github_jetbrains_kotlin//:kotlin-stdlib", - ], -) - -java_library( - name = "kotlin_stdlib_common", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/jetbrains/kotlin/kotlin_stdlib_common", - ], -) diff --git a/third_party/jvm/org/jetbrains/kotlinx/BUILD b/third_party/jvm/org/jetbrains/kotlinx/BUILD deleted file mode 100644 index 6559384e4..000000000 --- a/third_party/jvm/org/jetbrains/kotlinx/BUILD +++ /dev/null @@ -1,30 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "kotlinx_coroutines_core", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/jetbrains/kotlinx/kotlinx_coroutines_core", - ], - runtime_deps = [ - ":kotlinx_coroutines_core_common", - "//third_party/jvm/org/jetbrains/kotlin:kotlin_stdlib", - ], -) - -java_library( - name = "kotlinx_coroutines_core_common", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/jetbrains/kotlinx/kotlinx_coroutines_core_common", - ], - runtime_deps = [ - "//third_party/jvm/org/jetbrains/kotlin:kotlin_stdlib_common", - ], -) diff --git a/third_party/jvm/org/ow2/asm/BUILD b/third_party/jvm/org/ow2/asm/BUILD deleted file mode 100644 index cec329863..000000000 --- a/third_party/jvm/org/ow2/asm/BUILD +++ /dev/null @@ -1,54 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "asm", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/ow2/asm/asm", - ], -) - -java_library( - name = "asm_analysis", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/ow2/asm/asm_analysis", - ], - runtime_deps = [ - ":asm_tree", - ], -) - -java_library( - name = "asm_commons", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/ow2/asm/asm_commons", - ], - runtime_deps = [ - ":asm", - ":asm_analysis", - ":asm_tree", - ], -) - -java_library( - name = "asm_tree", - visibility = [ - "//third_party/jvm:__subpackages__", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/ow2/asm/asm_tree", - ], - runtime_deps = [ - ":asm", - ], -) diff --git a/third_party/jvm/org/pantsbuild/BUILD b/third_party/jvm/org/pantsbuild/BUILD deleted file mode 100644 index 44f0d904b..000000000 --- a/third_party/jvm/org/pantsbuild/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_library") - -licenses(["notice"]) - -java_library( - name = "jarjar", - visibility = [ - "//visibility:public", - ], - exports = [ - "//external:jar/io_bazel_rules_kotlin_org/pantsbuild/jarjar", - ], - runtime_deps = [ - "//third_party/jvm/org/apache/ant", - "//third_party/jvm/org/apache/maven:maven_plugin_api", - "//third_party/jvm/org/ow2/asm", - "//third_party/jvm/org/ow2/asm:asm_commons", - ], -) diff --git a/third_party/jvm/workspace.bzl b/third_party/jvm/workspace.bzl deleted file mode 100644 index 8655cbb69..000000000 --- a/third_party/jvm/workspace.bzl +++ /dev/null @@ -1,150 +0,0 @@ -# Do not edit. bazel-deps autogenerates this file from third_party/dependencies.yaml. -def _jar_artifact_impl(ctx): - jar_name = "%s.jar" % ctx.name - ctx.download( - output = ctx.path("jar/%s" % jar_name), - url = ctx.attr.urls, - sha256 = ctx.attr.sha256, - executable = False, - ) - src_name = "%s-sources.jar" % ctx.name - srcjar_attr = "" - has_sources = len(ctx.attr.src_urls) != 0 - if has_sources: - ctx.download( - output = ctx.path("jar/%s" % src_name), - url = ctx.attr.src_urls, - sha256 = ctx.attr.src_sha256, - executable = False, - ) - srcjar_attr = '\n srcjar = ":%s",' % src_name - - build_file_contents = """ -load("@rules_java//java:defs.bzl", "java_import") -package(default_visibility = ['//visibility:public']) -java_import( - name = 'jar', - tags = ['maven_coordinates={artifact}'], - jars = ['{jar_name}'],{srcjar_attr} -) -filegroup( - name = 'file', - srcs = [ - '{jar_name}', - '{src_name}' - ], - visibility = ['//visibility:public'] -)\n""".format(artifact = ctx.attr.artifact, jar_name = jar_name, src_name = src_name, srcjar_attr = srcjar_attr) - ctx.file(ctx.path("jar/BUILD"), build_file_contents, False) - return None - -jar_artifact = repository_rule( - attrs = { - "artifact": attr.string(mandatory = True), - "sha256": attr.string(mandatory = True), - "urls": attr.string_list(mandatory = True), - "src_sha256": attr.string(mandatory = False, default = ""), - "src_urls": attr.string_list(mandatory = False, default = []), - }, - implementation = _jar_artifact_impl, -) - -def jar_artifact_callback(hash): - src_urls = [] - src_sha256 = "" - source = hash.get("source", None) - if source != None: - src_urls = [source["url"]] - src_sha256 = source["sha256"] - jar_artifact( - artifact = hash["artifact"], - name = hash["name"], - urls = [hash["url"]], - sha256 = hash["sha256"], - src_urls = src_urls, - src_sha256 = src_sha256, - ) - native.bind(name = hash["bind"], actual = hash["actual"]) - -def list_dependencies(): - return [ - {"artifact": "com.google.auto.service:auto-service-annotations:1.0-rc5", "lang": "java", "sha1": "6ea999af2b6262a7179a09c51a3d54e7b40a3833", "sha256": "61e29be1b2a154c3a089e50d8c3e2198243085bfdf8e010081c8831be01da28b", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/auto/service/auto-service-annotations/1.0-rc5/auto-service-annotations-1.0-rc5.jar", "source": {"sha1": "a2e50e3ba1f9a88f89142e7ea9a0f5380574f4e4", "sha256": "d69c145d636e25743ae9b360f01f29609dd23b671259755064855006f1f20aed", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/auto/service/auto-service-annotations/1.0-rc5/auto-service-annotations-1.0-rc5-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_auto_service_auto_service_annotations", "actual": "@io_bazel_rules_kotlin_com_google_auto_service_auto_service_annotations//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/auto/service/auto_service_annotations"}, - {"artifact": "com.google.auto.service:auto-service:1.0-rc5", "lang": "java", "sha1": "d25246bae325b4bcc63b55d6d782515fac32215a", "sha256": "d7e3ba5a373797949081dbea0f2634241a30cce9bc6e6f7ef8208547e83b6286", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/auto/service/auto-service/1.0-rc5/auto-service-1.0-rc5.jar", "source": {"sha1": "76bf7fbfc5a924f13115005a134546c4e2d1b245", "sha256": "ac72bd9ee0ded6cfdcf60f16d9842d7ca6134fe199b5c4c8ac4ffac68ed66275", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/auto/service/auto-service/1.0-rc5/auto-service-1.0-rc5-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_auto_service_auto_service", "actual": "@io_bazel_rules_kotlin_com_google_auto_service_auto_service//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/auto/service/auto_service"}, - {"artifact": "com.google.auto.value:auto-value-annotations:1.6.5", "lang": "java", "sha1": "c3dad10377f0e2242c9a4b88e9704eaf79103679", "sha256": "3677f725f5b1b6cd6a4cc8aa8cf8f5fd2b76d170205cbdc3e9bfd9b58f934b3b", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-annotations/1.6.5/auto-value-annotations-1.6.5.jar", "source": {"sha1": "3499fd80025705c502699d1154c4b9631cb7a95e", "sha256": "f55b4c071128b6887ca1aaccc3946c84ca27cea29d2df71ed333744451fbc7dc", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-annotations/1.6.5/auto-value-annotations-1.6.5-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_auto_value_auto_value_annotations", "actual": "@io_bazel_rules_kotlin_com_google_auto_value_auto_value_annotations//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/auto/value/auto_value_annotations"}, - {"artifact": "com.google.auto.value:auto-value:1.6.5", "lang": "java", "sha1": "816872c85048f36a67a276ef7a49cc2e4595711c", "sha256": "ed5f69ef035b5367f1f0264f843b988908e36e155845880b29d79b7c8855adf3", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value/1.6.5/auto-value-1.6.5.jar", "source": {"sha1": "bfc251753f9bbdd8855825361d5f8c7fec8a1471", "sha256": "1fb0b04edb49060628a0a32970d85116222117feb8e334862e543c0ec39b609e", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value/1.6.5/auto-value-1.6.5-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_auto_value_auto_value", "actual": "@io_bazel_rules_kotlin_com_google_auto_value_auto_value//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/auto/value/auto_value"}, - {"artifact": "com.google.auto:auto-common:0.10", "lang": "java", "sha1": "c8f153ebe04a17183480ab4016098055fb474364", "sha256": "b876b5fddaceeba7d359667f6c4fb8c6f8658da1ab902ffb79ec9a415deede5f", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/auto/auto-common/0.10/auto-common-0.10.jar", "source": {"sha1": "913c8de9604380c6e135086132adb26c77fa6c53", "sha256": "e227d5aa864a9d59d8196540ee90995204f3458201138a638df9b0af609aef17", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/auto/auto-common/0.10/auto-common-0.10-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_auto_auto_common", "actual": "@io_bazel_rules_kotlin_com_google_auto_auto_common//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/auto/auto_common"}, - {"artifact": "com.google.code.findbugs:jsr305:3.0.2", "lang": "java", "sha1": "25ea2e8b0c338a877313bd4672d3fe056ea78f0d", "sha256": "766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar", "source": {"sha1": "b19b5927c2c25b6c70f093767041e641ae0b1b35", "sha256": "1c9e85e272d0708c6a591dc74828c71603053b48cc75ae83cce56912a2aa063b", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_code_findbugs_jsr305", "actual": "@io_bazel_rules_kotlin_com_google_code_findbugs_jsr305//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/code/findbugs/jsr305"}, - {"artifact": "com.google.code.gson:gson:2.7", "lang": "java", "sha1": "751f548c85fa49f330cecbb1875893f971b33c4e", "sha256": "2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/code/gson/gson/2.7/gson-2.7.jar", "source": {"sha1": "bbb63ca253b483da8ee53a50374593923e3de2e2", "sha256": "2d3220d5d936f0a26258aa3b358160741a4557e046a001251e5799c2db0f0d74", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/code/gson/gson/2.7/gson-2.7-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_code_gson_gson", "actual": "@io_bazel_rules_kotlin_com_google_code_gson_gson//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/code/gson/gson"}, - {"artifact": "com.google.dagger:dagger-compiler:2.23.1", "lang": "java", "sha1": "e5382ddad77a93df8d7fc2713a19074528547831", "sha256": "71d35b859bd7707ab5bfcdde8080a45de464156ffe10be8da2e1a2784b0457ff", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/dagger/dagger-compiler/2.23.1/dagger-compiler-2.23.1.jar", "source": {"sha1": "b916b832e806707d0097bb574fc88f14eded199c", "sha256": "40e877863521d033bcc917545f908c34900eec4620142174c0c7ced1488d808c", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/dagger/dagger-compiler/2.23.1/dagger-compiler-2.23.1-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_dagger_dagger_compiler", "actual": "@io_bazel_rules_kotlin_com_google_dagger_dagger_compiler//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/dagger/dagger_compiler"}, - {"artifact": "com.google.dagger:dagger-producers:2.23.1", "lang": "java", "sha1": "d9b09b989c5742290270f4a17409177831c028b4", "sha256": "7087ecaa89f090bc63cd5d7ab7f0e3fa1e8f9445c45378a6f57fc017a349b9f4", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/dagger/dagger-producers/2.23.1/dagger-producers-2.23.1.jar", "source": {"sha1": "8bbd77ba9a9666791a865857343b4fe60aa8f9c5", "sha256": "37e614ec27efe1b7c92ae44ddbe4dc890f57db59c96b5a3da902bb367e214308", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/dagger/dagger-producers/2.23.1/dagger-producers-2.23.1-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_dagger_dagger_producers", "actual": "@io_bazel_rules_kotlin_com_google_dagger_dagger_producers//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/dagger/dagger_producers"}, - {"artifact": "com.google.dagger:dagger-spi:2.23.1", "lang": "java", "sha1": "d76261eba9807321bac1eef8326cff77e476d082", "sha256": "f1df5d17bb771aeaeae1eb02c303429d22a8ab4209b054b3ba74aefd860a4f89", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/dagger/dagger-spi/2.23.1/dagger-spi-2.23.1.jar", "source": {"sha1": "00b2627c92f55db26f242791a085ad11324b21e9", "sha256": "724459c36b2ca86ce941eccd7dac441a59473c9db59e766bd0cfaa73aed8cb91", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/dagger/dagger-spi/2.23.1/dagger-spi-2.23.1-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_dagger_dagger_spi", "actual": "@io_bazel_rules_kotlin_com_google_dagger_dagger_spi//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/dagger/dagger_spi"}, - {"artifact": "com.google.dagger:dagger:2.23.1", "lang": "java", "sha1": "77041fb1aca9fa6fcc7716cf72330e82f14b4349", "sha256": "f4fe4c0e22e0b3b4fe3b14b7a1c7a381ac1b9c0579ae6d2ae05e28069524b227", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/dagger/dagger/2.23.1/dagger-2.23.1.jar", "source": {"sha1": "8f8f32aa78516111ced35683e3f590d050d202fe", "sha256": "c952182682e2639941315ed8adfd8c2f6e0ed2fc6bbf081c6a94972f314d31b2", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/dagger/dagger/2.23.1/dagger-2.23.1-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_dagger_dagger", "actual": "@io_bazel_rules_kotlin_com_google_dagger_dagger//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/dagger/dagger"}, - # duplicates in com.google.errorprone:error_prone_annotations promoted to 2.3.1 - # - com.google.guava:guava:27.1-jre wanted version 2.2.0 - # - com.google.truth:truth:0.45 wanted version 2.3.1 - {"artifact": "com.google.errorprone:error_prone_annotations:2.3.1", "lang": "java", "sha1": "a6a2b2df72fd13ec466216049b303f206bd66c5d", "sha256": "10a5949aa0f95c8de4fd47edfe20534d2acefd8c224f8afea1f607e112816120", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.3.1/error_prone_annotations-2.3.1.jar", "source": {"sha1": "bbb735b1d3f003adf3572682106a9932f5f35395", "sha256": "0fe3db0b12e624afd1dbeba85421fa58c362f9caf55f1869d7683b8744c53616", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.3.1/error_prone_annotations-2.3.1-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_errorprone_error_prone_annotations", "actual": "@io_bazel_rules_kotlin_com_google_errorprone_error_prone_annotations//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/errorprone/error_prone_annotations"}, - {"artifact": "com.google.errorprone:javac-shaded:9-dev-r4023-3", "lang": "java", "sha1": "72b688efd290280a0afde5f9892b0fde6f362d1d", "sha256": "65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/errorprone/javac-shaded/9-dev-r4023-3/javac-shaded-9-dev-r4023-3.jar", "source": {"sha1": "63214c79029c5d9ff0b8205d2d50e02c4879b4d6", "sha256": "cf0fde1aad77ac6e0e2d36a9f9179193ae1707088ba00ffa91fcfb5269304a6a", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/errorprone/javac-shaded/9-dev-r4023-3/javac-shaded-9-dev-r4023-3-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_errorprone_javac_shaded", "actual": "@io_bazel_rules_kotlin_com_google_errorprone_javac_shaded//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/errorprone/javac_shaded"}, - {"artifact": "com.google.googlejavaformat:google-java-format:1.5", "lang": "java", "sha1": "fba7f130d29061d2d2ea384b4880c10cae92ef73", "sha256": "aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/googlejavaformat/google-java-format/1.5/google-java-format-1.5.jar", "source": {"sha1": "a923662d9d3e11c63844cf4ae308c5a6b0292782", "sha256": "c204b15b3834128d335f17213f7e621ddb2cc5bfff5b8dd035cd1f2affb7fa8f", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/googlejavaformat/google-java-format/1.5/google-java-format-1.5-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_googlejavaformat_google_java_format", "actual": "@io_bazel_rules_kotlin_com_google_googlejavaformat_google_java_format//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/googlejavaformat/google_java_format"}, - {"artifact": "com.google.guava:failureaccess:1.0.1", "lang": "java", "sha1": "1dcf1de382a0bf95a3d8b0849546c88bac1292c9", "sha256": "a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar", "source": {"sha1": "1d064e61aad6c51cc77f9b59dc2cccc78e792f5a", "sha256": "092346eebbb1657b51aa7485a246bf602bb464cc0b0e2e1c7e7201fadce1e98f", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_guava_failureaccess", "actual": "@io_bazel_rules_kotlin_com_google_guava_failureaccess//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/guava/failureaccess"}, - # duplicates in com.google.guava:guava fixed to 27.1-jre - # - com.google.auto.service:auto-service:1.0-rc5 wanted version 27.0.1-jre - # - com.google.auto:auto-common:0.10 wanted version 23.5-jre - # - com.google.dagger:dagger-compiler:2.23.1 wanted version 27.1-jre - # - com.google.dagger:dagger-producers:2.23.1 wanted version 27.1-jre - # - com.google.dagger:dagger-spi:2.23.1 wanted version 27.1-jre - # - com.google.googlejavaformat:google-java-format:1.5 wanted version 22.0 - # - com.google.protobuf:protobuf-java-util:3.6.0 wanted version 19.0 - # - com.google.truth:truth:0.45 wanted version 27.0.1-android - {"artifact": "com.google.guava:guava:27.1-jre", "lang": "java", "sha1": "e47b59c893079b87743cdcfb6f17ca95c08c592c", "sha256": "4a5aa70cc968a4d137e599ad37553e5cfeed2265e8c193476d7119036c536fe7", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/guava/guava/27.1-jre/guava-27.1-jre.jar", "source": {"sha1": "5dfa313690a903560bf27478345780a607bf1e9b", "sha256": "9de05c573971cedfcd53fb85fc7a58a5f453053026a9bf18594cffc79a1d6874", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/guava/guava/27.1-jre/guava-27.1-jre-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_guava_guava", "actual": "@io_bazel_rules_kotlin_com_google_guava_guava//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/guava/guava"}, - {"artifact": "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava", "lang": "java", "sha1": "b421526c5f297295adef1c886e5246c39d4ac629", "sha256": "b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar", "name": "io_bazel_rules_kotlin_com_google_guava_listenablefuture", "actual": "@io_bazel_rules_kotlin_com_google_guava_listenablefuture//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/guava/listenablefuture"}, - {"artifact": "com.google.j2objc:j2objc-annotations:1.1", "lang": "java", "sha1": "ed28ded51a8b1c6b112568def5f4b455e6809019", "sha256": "2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/j2objc/j2objc-annotations/1.1/j2objc-annotations-1.1.jar", "source": {"sha1": "1efdf5b737b02f9b72ebdec4f72c37ec411302ff", "sha256": "2cd9022a77151d0b574887635cdfcdf3b78155b602abc89d7f8e62aba55cfb4f", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/j2objc/j2objc-annotations/1.1/j2objc-annotations-1.1-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_j2objc_j2objc_annotations", "actual": "@io_bazel_rules_kotlin_com_google_j2objc_j2objc_annotations//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/j2objc/j2objc_annotations"}, - {"artifact": "com.google.protobuf:protobuf-java-util:3.6.0", "lang": "java", "sha1": "3680d0042d4fe0b95ada844ff24da0698a7f0773", "sha256": "ad7f8d67674906ce88077fbb233b427b7068991a61af42ce9301990bdf8f3605", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java-util/3.6.0/protobuf-java-util-3.6.0.jar", "source": {"sha1": "1ac9d14befa9c98d382529dafa562a2dd4650011", "sha256": "a2959842caed6f0b1dbecfaf0e73ef03117416f967c0532c32d092b6e2b98d60", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java-util/3.6.0/protobuf-java-util-3.6.0-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_protobuf_protobuf_java_util", "actual": "@io_bazel_rules_kotlin_com_google_protobuf_protobuf_java_util//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/protobuf/protobuf_java_util"}, - # duplicates in com.google.protobuf:protobuf-java fixed to 3.6.0 - # - com.google.dagger:dagger-compiler:2.23.1 wanted version 3.7.0 - # - com.google.protobuf:protobuf-java-util:3.6.0 wanted version 3.6.0 - {"artifact": "com.google.protobuf:protobuf-java:3.6.0", "lang": "java", "sha1": "5333f7e422744d76840c08a106e28e519fbe3acd", "sha256": "8c8a65be83e75ccdcaa21417e303025f1708ea01e8c0a05d6c770e64b6c09ea1", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/3.6.0/protobuf-java-3.6.0.jar", "source": {"sha1": "6013b3453e0c102a8bd330d37f8e6918ce431882", "sha256": "88411bb0333725b27bf53ed4d95785f6f4b541e22e1e27c60c2be8b3115fc5c4", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/3.6.0/protobuf-java-3.6.0-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_protobuf_protobuf_java", "actual": "@io_bazel_rules_kotlin_com_google_protobuf_protobuf_java//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/protobuf/protobuf_java"}, - {"artifact": "com.google.truth:truth:0.45", "lang": "java", "sha1": "e16683346f6a6887b1f140a2984e60c73c66c40a", "sha256": "0f7dced2a16e55a77e44fc3ff9c5be98d4bf4bb30abc18d78ffd735df950a69f", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/truth/truth/0.45/truth-0.45.jar", "source": {"sha1": "59827b0d5d93ceedd22b025172a2c672b4565a2c", "sha256": "42c9b62ded52cd85a664217e116fd425f0e4c949b96c8ccde4c4cd0bb0ebe2de", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/google/truth/truth/0.45/truth-0.45-sources.jar"}, "name": "io_bazel_rules_kotlin_com_google_truth_truth", "actual": "@io_bazel_rules_kotlin_com_google_truth_truth//jar", "bind": "jar/io_bazel_rules_kotlin_com/google/truth/truth"}, - {"artifact": "com.googlecode.java-diff-utils:diffutils:1.3.0", "lang": "java", "sha1": "7e060dd5b19431e6d198e91ff670644372f60fbd", "sha256": "61ba4dc49adca95243beaa0569adc2a23aedb5292ae78aa01186fa782ebdc5c2", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/googlecode/java-diff-utils/diffutils/1.3.0/diffutils-1.3.0.jar", "source": {"sha1": "90b4aaa9530827fe6ad2b6684389c86999e861a3", "sha256": "7f4d40e97827f8a3285c3e47e8d28797ecfd45fb2ff94bd12cb6a83760a5f427", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/googlecode/java-diff-utils/diffutils/1.3.0/diffutils-1.3.0-sources.jar"}, "name": "io_bazel_rules_kotlin_com_googlecode_java_diff_utils_diffutils", "actual": "@io_bazel_rules_kotlin_com_googlecode_java_diff_utils_diffutils//jar", "bind": "jar/io_bazel_rules_kotlin_com/googlecode/java_diff_utils/diffutils"}, - {"artifact": "com.squareup:javapoet:1.11.1", "lang": "java", "sha1": "210e69f58dfa76c5529a303913b4a30c2bfeb76b", "sha256": "9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/squareup/javapoet/1.11.1/javapoet-1.11.1.jar", "source": {"sha1": "8da7f5aaa62c6e22f53d360b2d0e21f6fa35ef32", "sha256": "63d3187d924582b1afe9eb171e725d27a7e15603513890de0f8804a7fc07e9ac", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/com/squareup/javapoet/1.11.1/javapoet-1.11.1-sources.jar"}, "name": "io_bazel_rules_kotlin_com_squareup_javapoet", "actual": "@io_bazel_rules_kotlin_com_squareup_javapoet//jar", "bind": "jar/io_bazel_rules_kotlin_com/squareup/javapoet"}, - {"artifact": "javax.annotation:jsr250-api:1.0", "lang": "java", "sha1": "5025422767732a1ab45d93abfea846513d742dcf", "sha256": "a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/javax/annotation/jsr250-api/1.0/jsr250-api-1.0.jar", "source": {"sha1": "9b1fba77edd118e13c42bda43d3c993dadd52c25", "sha256": "025c47d76c60199381be07012a0c5f9e74661aac5bd67f5aec847741c5b7f838", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/javax/annotation/jsr250-api/1.0/jsr250-api-1.0-sources.jar"}, "name": "io_bazel_rules_kotlin_javax_annotation_jsr250_api", "actual": "@io_bazel_rules_kotlin_javax_annotation_jsr250_api//jar", "bind": "jar/io_bazel_rules_kotlin_javax/annotation/jsr250_api"}, - {"artifact": "javax.enterprise:cdi-api:1.0", "lang": "java", "sha1": "44c453f60909dfc223552ace63e05c694215156b", "sha256": "1f10b2204cc77c919301f20ff90461c3df1b6e6cb148be1c2d22107f4851d423", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/javax/enterprise/cdi-api/1.0/cdi-api-1.0.jar", "source": {"sha1": "3a3b9c3e5a1ec04c0c8b82e249cee7aeb4a96f9a", "sha256": "0e7c351dfe05759f84dc3eddaac1da4ef72578b494b53338829d34b12271374f", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/javax/enterprise/cdi-api/1.0/cdi-api-1.0-sources.jar"}, "name": "io_bazel_rules_kotlin_javax_enterprise_cdi_api", "actual": "@io_bazel_rules_kotlin_javax_enterprise_cdi_api//jar", "bind": "jar/io_bazel_rules_kotlin_javax/enterprise/cdi_api"}, - {"artifact": "javax.inject:javax.inject:1", "lang": "java", "sha1": "6975da39a7040257bd51d21a231b76c915872d38", "sha256": "91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/javax/inject/javax.inject/1/javax.inject-1.jar", "source": {"sha1": "a00123f261762a7c5e0ec916a2c7c8298d29c400", "sha256": "c4b87ee2911c139c3daf498a781967f1eb2e75bc1a8529a2e7b328a15d0e433e", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/javax/inject/javax.inject/1/javax.inject-1-sources.jar"}, "name": "io_bazel_rules_kotlin_javax_inject_javax_inject", "actual": "@io_bazel_rules_kotlin_javax_inject_javax_inject//jar", "bind": "jar/io_bazel_rules_kotlin_javax/inject/javax_inject"}, - {"artifact": "junit:junit:4.13-beta-3", "lang": "java", "sha1": "24e695de7450859f58dcfb2d818af908aee93e36", "sha256": "ea84a0558309da51dbd9d958917cd27b0fc42e2b5940942fd4c5df527e3356f4", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/junit/junit/4.13-beta-3/junit-4.13-beta-3.jar", "source": {"sha1": "8c935ccfbc74f560aed6fb24ce52c7d177327a52", "sha256": "e18a61e69e4899942c91b7e2d5c68f65e9aabc303036f878cb341dea31194ac4", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/junit/junit/4.13-beta-3/junit-4.13-beta-3-sources.jar"}, "name": "io_bazel_rules_kotlin_junit_junit", "actual": "@io_bazel_rules_kotlin_junit_junit//jar", "bind": "jar/io_bazel_rules_kotlin_junit/junit"}, - {"artifact": "net.ltgt.gradle.incap:incap:0.2", "lang": "java", "sha1": "0c73e3db9bee414d6ee27995d951fcdbee09acad", "sha256": "b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/net/ltgt/gradle/incap/incap/0.2/incap-0.2.jar", "source": {"sha1": "5cf72f18b924fcfd7fd452025c890e7e7151a840", "sha256": "15c3cd213a214c94ef7ed262e00ab10c75d1680b0b9203b47801e7068de1cf5c", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/net/ltgt/gradle/incap/incap/0.2/incap-0.2-sources.jar"}, "name": "io_bazel_rules_kotlin_net_ltgt_gradle_incap_incap", "actual": "@io_bazel_rules_kotlin_net_ltgt_gradle_incap_incap//jar", "bind": "jar/io_bazel_rules_kotlin_net/ltgt/gradle/incap/incap"}, - {"artifact": "org.apache.ant:ant-launcher:1.9.9", "lang": "java", "sha1": "c5841b18f5299f17fc53223c3a378e08278a5ef7", "sha256": "02cbe010ceec4acab059acfa48a16dc7b7c430200f2561b6b7c75bcab48f4044", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/apache/ant/ant-launcher/1.9.9/ant-launcher-1.9.9.jar", "source": {"sha1": "5c470dae95c8e07d3e163519e2cbce806e0448e3", "sha256": "ba0f51943f94c3a107f1aff983f180e08e3bc2093643feacfa6d1af025190ae8", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/apache/ant/ant-launcher/1.9.9/ant-launcher-1.9.9-sources.jar"}, "name": "io_bazel_rules_kotlin_org_apache_ant_ant_launcher", "actual": "@io_bazel_rules_kotlin_org_apache_ant_ant_launcher//jar", "bind": "jar/io_bazel_rules_kotlin_org/apache/ant/ant_launcher"}, - {"artifact": "org.apache.ant:ant:1.9.9", "lang": "java", "sha1": "9dc55233d8c0809e57b2ec7f78376da3f32872bd", "sha256": "d81254bcb2e170c9ea16cd418050f3340da1736380a02415c8ddda9a0a0b8a1b", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/apache/ant/ant/1.9.9/ant-1.9.9.jar", "source": {"sha1": "10007efe7eabbe71f8c722313269d37856fe1515", "sha256": "369708c550831c8a1a4c1a333e51db30ad69bbcd674f8545b6bce6a4290a9f5e", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/apache/ant/ant/1.9.9/ant-1.9.9-sources.jar"}, "name": "io_bazel_rules_kotlin_org_apache_ant_ant", "actual": "@io_bazel_rules_kotlin_org_apache_ant_ant//jar", "bind": "jar/io_bazel_rules_kotlin_org/apache/ant/ant"}, - {"artifact": "org.apache.commons:commons-lang3:3.4", "lang": "java", "sha1": "5fe28b9518e58819180a43a850fbc0dd24b7c050", "sha256": "734c8356420cc8e30c795d64fd1fcd5d44ea9d90342a2cc3262c5158fbc6d98b", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/apache/commons/commons-lang3/3.4/commons-lang3-3.4.jar", "source": {"sha1": "b49dafc9cfef24c356827f322e773e7c26725dd2", "sha256": "4709f16a9e0f8fd83ae155083d63044e23045aac8f6f0183a2db09f492491b12", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/apache/commons/commons-lang3/3.4/commons-lang3-3.4-sources.jar"}, "name": "io_bazel_rules_kotlin_org_apache_commons_commons_lang3", "actual": "@io_bazel_rules_kotlin_org_apache_commons_commons_lang3//jar", "bind": "jar/io_bazel_rules_kotlin_org/apache/commons/commons_lang3"}, - {"artifact": "org.apache.maven:maven-artifact:3.3.9", "lang": "java", "sha1": "0f43afa184555fbc6e36b3334b17246c39b30f6e", "sha256": "1f702928f2233c6ecdf308fbd8f2932ea287c7062183d3c8364b0db7e9c4445d", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/apache/maven/maven-artifact/3.3.9/maven-artifact-3.3.9.jar", "source": {"sha1": "0dccabdddd892d97f181788c63d30f10df9cc85d", "sha256": "8985ed687dc682ff0fef32fb449005cc02eb47f860e36bf8b38b3be3cfa81ef6", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/apache/maven/maven-artifact/3.3.9/maven-artifact-3.3.9-sources.jar"}, "name": "io_bazel_rules_kotlin_org_apache_maven_maven_artifact", "actual": "@io_bazel_rules_kotlin_org_apache_maven_maven_artifact//jar", "bind": "jar/io_bazel_rules_kotlin_org/apache/maven/maven_artifact"}, - {"artifact": "org.apache.maven:maven-model:3.3.9", "lang": "java", "sha1": "6efde8cbcb4de4c47f7e9c2a3ab2806022b5c70f", "sha256": "15abde67fa7ea1e573e1f68c34921e995f0971351aaf1fb96790688ff510efcd", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/apache/maven/maven-model/3.3.9/maven-model-3.3.9.jar", "source": {"sha1": "590902cc3f932ced5ce51282b74bf62571a82c14", "sha256": "9caac5f1fafe59db3b68f3c78dc6f3511720e59b190d3c1de939ce4fefc1bea6", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/apache/maven/maven-model/3.3.9/maven-model-3.3.9-sources.jar"}, "name": "io_bazel_rules_kotlin_org_apache_maven_maven_model", "actual": "@io_bazel_rules_kotlin_org_apache_maven_maven_model//jar", "bind": "jar/io_bazel_rules_kotlin_org/apache/maven/maven_model"}, - {"artifact": "org.apache.maven:maven-plugin-api:3.3.9", "lang": "java", "sha1": "aa706ea7ca23776861b4eb2cea97cf345e791496", "sha256": "14cae18fd7125901b12fc914e30ea26ad9bd43dbd399dd6e8fcbc6c754ef2c9c", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/apache/maven/maven-plugin-api/3.3.9/maven-plugin-api-3.3.9.jar", "source": {"sha1": "26efdb80ee74e458d589719df3f85656ccaeb326", "sha256": "5f26fcbf2634be46e9b55a7c95d92e916fc14c55aca96ad29384a0912476bb9e", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/apache/maven/maven-plugin-api/3.3.9/maven-plugin-api-3.3.9-sources.jar"}, "name": "io_bazel_rules_kotlin_org_apache_maven_maven_plugin_api", "actual": "@io_bazel_rules_kotlin_org_apache_maven_maven_plugin_api//jar", "bind": "jar/io_bazel_rules_kotlin_org/apache/maven/maven_plugin_api"}, - # duplicates in org.checkerframework:checker-compat-qual promoted to 2.5.5 - # - com.google.dagger:dagger-compiler:2.23.1 wanted version 2.5.3 - # - com.google.dagger:dagger-producers:2.23.1 wanted version 2.5.3 - # - com.google.truth:truth:0.45 wanted version 2.5.5 - {"artifact": "org.checkerframework:checker-compat-qual:2.5.5", "lang": "java", "sha1": "435dc33e3019c9f019e15f01aa111de9d6b2b79c", "sha256": "11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/checkerframework/checker-compat-qual/2.5.5/checker-compat-qual-2.5.5.jar", "source": {"sha1": "54d4253d4d8723096a95b7551bd5639e7e2affba", "sha256": "7c63a4a46b2ef903f941aeac63da87dd345be3243b472796aa945fa715bf3ca9", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/checkerframework/checker-compat-qual/2.5.5/checker-compat-qual-2.5.5-sources.jar"}, "name": "io_bazel_rules_kotlin_org_checkerframework_checker_compat_qual", "actual": "@io_bazel_rules_kotlin_org_checkerframework_checker_compat_qual//jar", "bind": "jar/io_bazel_rules_kotlin_org/checkerframework/checker_compat_qual"}, - {"artifact": "org.checkerframework:checker-qual:2.5.2", "lang": "java", "sha1": "cea74543d5904a30861a61b4643a5f2bb372efc4", "sha256": "64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/2.5.2/checker-qual-2.5.2.jar", "source": {"sha1": "ebb8ebccd42218434674f3e1d9022c13df1c19f8", "sha256": "821c5c63a6f156a3bb498c5bbb613580d9d8f4134131a5627d330fc4018669d2", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/2.5.2/checker-qual-2.5.2-sources.jar"}, "name": "io_bazel_rules_kotlin_org_checkerframework_checker_qual", "actual": "@io_bazel_rules_kotlin_org_checkerframework_checker_qual//jar", "bind": "jar/io_bazel_rules_kotlin_org/checkerframework/checker_qual"}, - {"artifact": "org.codehaus.mojo:animal-sniffer-annotations:1.17", "lang": "java", "sha1": "f97ce6decaea32b36101e37979f8b647f00681fb", "sha256": "92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/codehaus/mojo/animal-sniffer-annotations/1.17/animal-sniffer-annotations-1.17.jar", "source": {"sha1": "8fb5b5ad9c9723951b9fccaba5bb657fa6064868", "sha256": "2571474a676f775a8cdd15fb9b1da20c4c121ed7f42a5d93fca0e7b6e2015b40", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/codehaus/mojo/animal-sniffer-annotations/1.17/animal-sniffer-annotations-1.17-sources.jar"}, "name": "io_bazel_rules_kotlin_org_codehaus_mojo_animal_sniffer_annotations", "actual": "@io_bazel_rules_kotlin_org_codehaus_mojo_animal_sniffer_annotations//jar", "bind": "jar/io_bazel_rules_kotlin_org/codehaus/mojo/animal_sniffer_annotations"}, - {"artifact": "org.codehaus.plexus:plexus-classworlds:2.5.2", "lang": "java", "sha1": "4abb111bfdace5b8167db4c0ef74644f3f88f142", "sha256": "b2931d41740490a8d931cbe0cfe9ac20deb66cca606e679f52522f7f534c9fd7", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-classworlds/2.5.2/plexus-classworlds-2.5.2.jar", "source": {"sha1": "8aea177d48dd9bdafe7c3b4116a604e8b3b1b52e", "sha256": "d087c4c0ff02b035111bb72c72603b2851d126c43da39cc3c73ff45139125bec", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-classworlds/2.5.2/plexus-classworlds-2.5.2-sources.jar"}, "name": "io_bazel_rules_kotlin_org_codehaus_plexus_plexus_classworlds", "actual": "@io_bazel_rules_kotlin_org_codehaus_plexus_plexus_classworlds//jar", "bind": "jar/io_bazel_rules_kotlin_org/codehaus/plexus/plexus_classworlds"}, - {"artifact": "org.codehaus.plexus:plexus-component-annotations:1.5.5", "lang": "java", "sha1": "c72f2660d0cbed24246ddb55d7fdc4f7374d2078", "sha256": "4df7a6a7be64b35bbccf60b5c115697f9ea3421d22674ae67135dde375fcca1f", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-component-annotations/1.5.5/plexus-component-annotations-1.5.5.jar", "source": {"sha1": "b10462efcf1ac1915797958d479c724d1bd5008d", "sha256": "527768d357304e0ad56b74ca77f27ba28b4a456680450ef45a30bfaf613469e6", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-component-annotations/1.5.5/plexus-component-annotations-1.5.5-sources.jar"}, "name": "io_bazel_rules_kotlin_org_codehaus_plexus_plexus_component_annotations", "actual": "@io_bazel_rules_kotlin_org_codehaus_plexus_plexus_component_annotations//jar", "bind": "jar/io_bazel_rules_kotlin_org/codehaus/plexus/plexus_component_annotations"}, - # duplicates in org.codehaus.plexus:plexus-utils promoted to 3.0.22 - # - org.apache.maven:maven-artifact:3.3.9 wanted version 3.0.22 - # - org.apache.maven:maven-model:3.3.9 wanted version 3.0.22 - # - org.eclipse.sisu:org.eclipse.sisu.plexus:0.3.2 wanted version 3.0.17 - {"artifact": "org.codehaus.plexus:plexus-utils:3.0.22", "lang": "java", "sha1": "764f26e0ab13a87c48fe55f525dfb6a133b7a92f", "sha256": "0f31c44b275f87e56d46a582ce96d03b9e2ab344cf87c4e268b34d3ad046beab", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-utils/3.0.22/plexus-utils-3.0.22.jar", "source": {"sha1": "cf8b05bbaac563b52c02d396dfe4233a4dbae7bd", "sha256": "8fb619ac58aaa2a27f9cefce866a9689d41e15a120c2efe0f781b6bcad88caf3", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-utils/3.0.22/plexus-utils-3.0.22-sources.jar"}, "name": "io_bazel_rules_kotlin_org_codehaus_plexus_plexus_utils", "actual": "@io_bazel_rules_kotlin_org_codehaus_plexus_plexus_utils//jar", "bind": "jar/io_bazel_rules_kotlin_org/codehaus/plexus/plexus_utils"}, - {"artifact": "org.eclipse.sisu:org.eclipse.sisu.inject:0.3.2", "lang": "java", "sha1": "59044b92ec27cc6fda7a2d24b2cd6cec23f31d5b", "sha256": "66e87705a818da44eb080a7bb1fc431de987754b4f92aa85f69991bfc677d40d", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/eclipse/sisu/org.eclipse.sisu.inject/0.3.2/org.eclipse.sisu.inject-0.3.2.jar", "source": {"sha1": "40ee2c0df44216015c6af02f68632e97f6255b95", "sha256": "739d7228920a97892b9c6b6e4d16799930e8d2439543e71fa7a7c849a39cc8a1", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/eclipse/sisu/org.eclipse.sisu.inject/0.3.2/org.eclipse.sisu.inject-0.3.2-sources.jar"}, "name": "io_bazel_rules_kotlin_org_eclipse_sisu_org_eclipse_sisu_inject", "actual": "@io_bazel_rules_kotlin_org_eclipse_sisu_org_eclipse_sisu_inject//jar", "bind": "jar/io_bazel_rules_kotlin_org/eclipse/sisu/org_eclipse_sisu_inject"}, - {"artifact": "org.eclipse.sisu:org.eclipse.sisu.plexus:0.3.2", "lang": "java", "sha1": "cd84cb43788de23847eec2999070f64381bdb495", "sha256": "f5cfe0d88e8276971db4ecff0e4186d5f2ec5fdb1b6bb8c2f359fdc4b43eb8b2", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/eclipse/sisu/org.eclipse.sisu.plexus/0.3.2/org.eclipse.sisu.plexus-0.3.2.jar", "source": {"sha1": "19f14348517bfb751b0e49ba3f67e907ce997139", "sha256": "d8091fc791e3027dd72e51f0dabcd387f27dba8fffa79511edea29f33213a8a8", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/eclipse/sisu/org.eclipse.sisu.plexus/0.3.2/org.eclipse.sisu.plexus-0.3.2-sources.jar"}, "name": "io_bazel_rules_kotlin_org_eclipse_sisu_org_eclipse_sisu_plexus", "actual": "@io_bazel_rules_kotlin_org_eclipse_sisu_org_eclipse_sisu_plexus//jar", "bind": "jar/io_bazel_rules_kotlin_org/eclipse/sisu/org_eclipse_sisu_plexus"}, - {"artifact": "org.hamcrest:hamcrest-core:1.3", "lang": "java", "sha1": "42a25dc3219429f0e5d060061f71acb49bf010a0", "sha256": "66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar", "source": {"sha1": "1dc37250fbc78e23a65a67fbbaf71d2e9cbc3c0b", "sha256": "e223d2d8fbafd66057a8848cc94222d63c3cedd652cc48eddc0ab5c39c0f84df", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar"}, "name": "io_bazel_rules_kotlin_org_hamcrest_hamcrest_core", "actual": "@io_bazel_rules_kotlin_org_hamcrest_hamcrest_core//jar", "bind": "jar/io_bazel_rules_kotlin_org/hamcrest/hamcrest_core"}, - {"artifact": "org.jetbrains.kotlin:kotlin-stdlib-common:1.3.20", "lang": "java", "sha1": "7d7934e26ce34da1a0a8d00e38038d7cf3375e89", "sha256": "06bdd8aeda347ef6ef3e4e9d88a01254ccdb70784b697495f6a421fd663ab649", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.3.20/kotlin-stdlib-common-1.3.20.jar", "source": {"sha1": "60070a2fbed969e9b73f214cb41072eabedf299a", "sha256": "186e6977750701be15fd16a92b9a349f1af90dc9ae80d566bb384f9e2326d78b", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.3.20/kotlin-stdlib-common-1.3.20-sources.jar"}, "name": "io_bazel_rules_kotlin_org_jetbrains_kotlin_kotlin_stdlib_common", "actual": "@io_bazel_rules_kotlin_org_jetbrains_kotlin_kotlin_stdlib_common//jar", "bind": "jar/io_bazel_rules_kotlin_org/jetbrains/kotlin/kotlin_stdlib_common"}, - {"artifact": "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.1.1", "lang": "java", "sha1": "7ed04382bdf0c89c5d87ac462aa4935ae8e85243", "sha256": "033732168fd3a68a7d788294321106ae13536eae8459382a85cc1f17f88572e7", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-common/1.1.1/kotlinx-coroutines-core-common-1.1.1.jar", "source": {"sha1": "113450f5f2a971252086c89dd26cde062455fbe8", "sha256": "597ac321b2d56e42251e9caf4d166264c4db3c89d3bee7d9f5ec6e1f2c5297bd", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-common/1.1.1/kotlinx-coroutines-core-common-1.1.1-sources.jar"}, "name": "io_bazel_rules_kotlin_org_jetbrains_kotlinx_kotlinx_coroutines_core_common", "actual": "@io_bazel_rules_kotlin_org_jetbrains_kotlinx_kotlinx_coroutines_core_common//jar", "bind": "jar/io_bazel_rules_kotlin_org/jetbrains/kotlinx/kotlinx_coroutines_core_common"}, - {"artifact": "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1", "lang": "java", "sha1": "3d2b7321cdef9ebf9cb7729ea4f75a6f6457df86", "sha256": "ac423f8a0aa4b4e74529696ff82c0171f81a8c8ab182a1965dff25e69c1f7844", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.1.1/kotlinx-coroutines-core-1.1.1.jar", "source": {"sha1": "7fa353579a38ee5bc873511455e4cca65d930b52", "sha256": "064111d361fffb0091583821de0f5fc7b4549089db2a9e024f62cae5a79b0bc1", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.1.1/kotlinx-coroutines-core-1.1.1-sources.jar"}, "name": "io_bazel_rules_kotlin_org_jetbrains_kotlinx_kotlinx_coroutines_core", "actual": "@io_bazel_rules_kotlin_org_jetbrains_kotlinx_kotlinx_coroutines_core//jar", "bind": "jar/io_bazel_rules_kotlin_org/jetbrains/kotlinx/kotlinx_coroutines_core"}, - {"artifact": "org.jetbrains:annotations:13.0", "lang": "java", "sha1": "919f0dfe192fb4e063e7dacadee7f8bb9a2672a9", "sha256": "ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.jar", "source": {"sha1": "5991ca87ef1fb5544943d9abc5a9a37583fabe03", "sha256": "42a5e144b8e81d50d6913d1007b695e62e614705268d8cf9f13dbdc478c2c68e", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0-sources.jar"}, "name": "io_bazel_rules_kotlin_org_jetbrains_annotations", "actual": "@io_bazel_rules_kotlin_org_jetbrains_annotations//jar", "bind": "jar/io_bazel_rules_kotlin_org/jetbrains/annotations"}, - {"artifact": "org.ow2.asm:asm-analysis:7.0", "lang": "java", "sha1": "4b310d20d6f1c6b7197a75f1b5d69f169bc8ac1f", "sha256": "e981f8f650c4d900bb033650b18e122fa6b161eadd5f88978d08751f72ee8474", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/ow2/asm/asm-analysis/7.0/asm-analysis-7.0.jar", "source": {"sha1": "70608c6f4ee3c2073ccd43f1e4a359783334f86f", "sha256": "57bdf5b407dc122b8f4118e2fbf686719c81f6b7c97598e17ce7a456ea151866", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/ow2/asm/asm-analysis/7.0/asm-analysis-7.0-sources.jar"}, "name": "io_bazel_rules_kotlin_org_ow2_asm_asm_analysis", "actual": "@io_bazel_rules_kotlin_org_ow2_asm_asm_analysis//jar", "bind": "jar/io_bazel_rules_kotlin_org/ow2/asm/asm_analysis"}, - {"artifact": "org.ow2.asm:asm-commons:7.0", "lang": "java", "sha1": "478006d07b7c561ae3a92ddc1829bca81ae0cdd1", "sha256": "fed348ef05958e3e846a3ac074a12af5f7936ef3d21ce44a62c4fa08a771927d", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/ow2/asm/asm-commons/7.0/asm-commons-7.0.jar", "source": {"sha1": "06a7ca89b189929d4eb4349c6f075fc345b055e0", "sha256": "7076b9f1cd3fdae003447b9fd546290b9ab76e34f147b2bf0b981ddae86f7053", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/ow2/asm/asm-commons/7.0/asm-commons-7.0-sources.jar"}, "name": "io_bazel_rules_kotlin_org_ow2_asm_asm_commons", "actual": "@io_bazel_rules_kotlin_org_ow2_asm_asm_commons//jar", "bind": "jar/io_bazel_rules_kotlin_org/ow2/asm/asm_commons"}, - {"artifact": "org.ow2.asm:asm-tree:7.0", "lang": "java", "sha1": "29bc62dcb85573af6e62e5b2d735ef65966c4180", "sha256": "cfd7a0874f9de36a999c127feeadfbfe6e04d4a71ee954d7af3d853f0be48a6c", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/ow2/asm/asm-tree/7.0/asm-tree-7.0.jar", "source": {"sha1": "6064bf57bbce12aebc8ab96f32efe3f1c6cdd5fc", "sha256": "8888c88a9889b1b413d90e440b6b9c894e8d31632a473bd70e683645aba382dd", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/ow2/asm/asm-tree/7.0/asm-tree-7.0-sources.jar"}, "name": "io_bazel_rules_kotlin_org_ow2_asm_asm_tree", "actual": "@io_bazel_rules_kotlin_org_ow2_asm_asm_tree//jar", "bind": "jar/io_bazel_rules_kotlin_org/ow2/asm/asm_tree"}, - {"artifact": "org.ow2.asm:asm:7.0", "lang": "java", "sha1": "d74d4ba0dee443f68fb2dcb7fcdb945a2cd89912", "sha256": "b88ef66468b3c978ad0c97fd6e90979e56155b4ac69089ba7a44e9aa7ffe9acf", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/ow2/asm/asm/7.0/asm-7.0.jar", "source": {"sha1": "1e0eab03ec196dea229ea637e523b9c016e66b42", "sha256": "51a538468a788fa543e80e6bccbe05d2a738fa0da553b710a1fd8ed574504982", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/ow2/asm/asm/7.0/asm-7.0-sources.jar"}, "name": "io_bazel_rules_kotlin_org_ow2_asm_asm", "actual": "@io_bazel_rules_kotlin_org_ow2_asm_asm//jar", "bind": "jar/io_bazel_rules_kotlin_org/ow2/asm/asm"}, - {"artifact": "org.pantsbuild:jarjar:1.7.2", "lang": "java", "sha1": "8e258f158b4572d40598d7f4793cfbfe84a7cc70", "sha256": "0706a455e17b67718abe212e3a77688bbe8260852fc74e3e836d9f2e76d91c27", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/pantsbuild/jarjar/1.7.2/jarjar-1.7.2.jar", "source": {"sha1": "7493bcc6977a9c1f117dc894a6408689b06911cd", "sha256": "69e0182465b18189294c6a3e3808595ad820b0b5bc2170324b2f6bb37fb1499a", "repository": "https://repo.maven.apache.org/maven2/", "url": "https://repo.maven.apache.org/maven2/org/pantsbuild/jarjar/1.7.2/jarjar-1.7.2-sources.jar"}, "name": "io_bazel_rules_kotlin_org_pantsbuild_jarjar", "actual": "@io_bazel_rules_kotlin_org_pantsbuild_jarjar//jar", "bind": "jar/io_bazel_rules_kotlin_org/pantsbuild/jarjar"}, - ] - -def maven_dependencies(callback = jar_artifact_callback): - for hash in list_dependencies(): - callback(hash) From 9b1fb3d3e92b8d723998e354ec9aee3a0ae98ae5 Mon Sep 17 00:00:00 2001 From: Christian Edward Gruber Date: Tue, 18 Feb 2020 17:46:32 -0500 Subject: [PATCH 04/16] Update readme so the dev instructions highlight using a local clone (#283) * Update readme so the dev instructions highlight using a local clone * Typo and make a faux-path. --- README.md | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 5c972078e..691a653ff 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Current release: ***`legacy-1.3.0`***
Main branch: `master` # News! +* Feb 18, 2020. Changes to how the rules are consumed are live (prefer the release tarball or use development instructions, as stated in the readme). * Feb 9, 2020. Released version [1.3.0](https://github.com/bazelbuild/rules_kotlin/releases/tag/legacy-1.3.0). (No changes from `legacy-1.3.0-rc4`) * Jan 15, 2020. Released version [1.3.0-rc4](https://github.com/bazelbuild/rules_kotlin/releases/tag/legacy-1.3.0-rc4). * Jan 15, 2020. Bug fixes and tweaks (#255, #257). @@ -146,21 +147,15 @@ To use the rules directly from the rules_kotlin workspace (i.e. not the release In the project's `WORKSPACE`, change the setup: ```python -load("//kotlin:dependencies.bzl", "kt_download_local_dev_dependencies") -kt_download_local_dev_dependencies() - - -rules_kotlin_version = "legacy-1.3.0-rc4" -rules_kotlin_sha = "fe32ced5273bcc2f9e41cea65a28a9184a77f3bc30fea8a5c47b3d3bfc801dff" -http_archive( +# Use local check-out of repo rules (or a commit-archive from github via http_archive or git_repository) +local_repository( name = "io_bazel_rules_kotlin", - urls = ["https://github.com/bazelbuild/rules_kotlin/archive/%s.zip" % rules_kotlin_version], - type = "zip", - strip_prefix = "rules_kotlin-%s" % rules_kotlin_version, - sha256 = rules_kotlin_sha, + path = "../path/to/rules_kotlin_clone", ) +load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_download_local_dev_dependencies") +kt_download_local_dev_dependencies() load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kotlin_repositories", "kt_register_toolchains") kotlin_repositories() # if you want the default. Otherwise see custom kotlinc distribution below kt_register_toolchains() # to use the default toolchain, otherwise see toolchains below From 526efa9a997d16ea69ede2d630a0d98cac6aa321 Mon Sep 17 00:00:00 2001 From: Justin Wei Date: Mon, 24 Feb 2020 13:56:16 -0800 Subject: [PATCH 05/16] Filter non-kotlin code out of generated sources (#263) * Filter non-kotlin code out of generated sources * Single-pass filter and vague android sdk * Add test for filtering generated source files --- WORKSPACE | 2 +- kotlin/internal/jvm/impl.bzl | 3 ++ .../bazel/kotlin/builder/tasks/BazelWorker.kt | 9 +++- .../tasks/jvm/KotlinJvmTaskExecutor.kt | 46 ++++++++--------- src/test/kotlin/io/bazel/kotlin/builder/BUILD | 7 +++ .../builder/KotlinAbstractTestBuilder.java | 14 ++++-- .../kotlin/builder/KotlinJvmTestBuilder.java | 4 +- .../tasks/jvm/KotlinJvmTaskExecutorTest.kt | 50 +++++++++++++++++++ 8 files changed, 105 insertions(+), 30 deletions(-) create mode 100644 src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutorTest.kt diff --git a/WORKSPACE b/WORKSPACE index 2dde36617..09b905cca 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -29,4 +29,4 @@ rbe_autoconfig( ) android_sdk_repository(name = "androidsdk") -android_ndk_repository(name = "androidndk") \ No newline at end of file +android_ndk_repository(name = "androidndk") diff --git a/kotlin/internal/jvm/impl.bzl b/kotlin/internal/jvm/impl.bzl index fa86a71e0..6b84e2a69 100644 --- a/kotlin/internal/jvm/impl.bzl +++ b/kotlin/internal/jvm/impl.bzl @@ -62,6 +62,9 @@ def _write_launcher_action(ctx, rjars, main_class, jvm_flags, args = "", wrapper "%javabin%": javabin, "%jvm_flags%": jvm_flags, "%set_jacoco_metadata%": "", + "%set_jacoco_main_class%": "", + "%set_jacoco_java_runfiles_root%": "", + "%set_java_coverage_new_implementation%": "", "%workspace_prefix%": ctx.workspace_name + "/", }, is_executable = True, diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/BazelWorker.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/BazelWorker.kt index b5f8638f2..2f865a132 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/BazelWorker.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/BazelWorker.kt @@ -82,13 +82,20 @@ class BazelWorker( val exitCode = try { delegate.apply(loadArguments(request.argumentsList, true)) } catch (e: RuntimeException) { - return if (wasInterrupted(e)) INTERUPTED_STATUS + val innerExitCode = if (wasInterrupted(e)) INTERUPTED_STATUS else ERROR_STATUS.also { System.err.println( "ERROR: Worker threw uncaught exception with args: ${request.argumentsList.joinToString(" ")}" ) e.printStackTrace(System.err) } + WorkerProtocol.WorkResponse.newBuilder() + .setOutput(buffer.toString()) + .setExitCode(innerExitCode) + .build() + .writeDelimitedTo(realStdOut) + realStdOut.flush() + return innerExitCode } WorkerProtocol.WorkResponse.newBuilder() diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt index 8cb75f760..c326fd977 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt @@ -201,31 +201,31 @@ class KotlinJvmTaskExecutor @Inject internal constructor( it.execute() }.sourcesList.iterator() ) +} - /** - * Create a new [JvmCompilationTask] with sources found in the generatedSources directory. This should be run after - * annotation processors have been run. - */ - private fun JvmCompilationTask.expandWithGeneratedSources(): JvmCompilationTask = - expandWithSources( - File(directories.generatedSources).walkTopDown() - .filter { it.isFile } - .map { it.path } - .iterator() - ) - - private fun JvmCompilationTask.expandWithSources(sources: Iterator): JvmCompilationTask = - updateBuilder { builder -> - sources.partitionJvmSources( +/** + * Create a new [JvmCompilationTask] with sources found in the generatedSources directory. This should be run after + * annotation processors have been run. + */ +fun JvmCompilationTask.expandWithGeneratedSources(): JvmCompilationTask = + expandWithSources( + File(directories.generatedSources).walkTopDown() + .filter { it.isFile && IS_JVM_SOURCE_FILE.test(it.name) } + .map { it.path } + .iterator() + ) + +fun JvmCompilationTask.expandWithSources(sources: Iterator): JvmCompilationTask = + updateBuilder { builder -> + sources.partitionJvmSources( { builder.inputsBuilder.addKotlinSources(it) }, { builder.inputsBuilder.addJavaSources(it) }) - } + } - private fun JvmCompilationTask.updateBuilder( +fun JvmCompilationTask.updateBuilder( block: (JvmCompilationTask.Builder) -> Unit - ): JvmCompilationTask = - toBuilder().let { - block(it) - it.build() - } -} +): JvmCompilationTask = + toBuilder().let { + block(it) + it.build() + } \ No newline at end of file diff --git a/src/test/kotlin/io/bazel/kotlin/builder/BUILD b/src/test/kotlin/io/bazel/kotlin/builder/BUILD index 37db8ff13..25c745f22 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/BUILD +++ b/src/test/kotlin/io/bazel/kotlin/builder/BUILD @@ -67,6 +67,12 @@ kt_rules_test( srcs = ["tasks/jvm/KotlinBuilderJvmBasicTest.java"], ) +kt_rules_test( + name = "KotlinJvmTaskExecutorTest", + srcs = ["tasks/jvm/KotlinJvmTaskExecutorTest.kt"], + deps = ["@com_github_jetbrains_kotlin//:kotlin-test"], +) + # TODO(bazelbuild/rules_kotlin/issues/275): Remove full jar reference when the kt_rules_test handles jvm_import data better. _MAVEN_CENTRAL_PREFIX = "@kotlin_rules_maven//:v1/https/maven-central.storage.googleapis.com/repos/central/data" _AUTO_VALUE_PREFIX = "%s/com/google/auto/value" % _MAVEN_CENTRAL_PREFIX @@ -98,6 +104,7 @@ test_suite( ":KotlinBuilderJsTest", ":KotlinBuilderJvmBasicTest", ":KotlinBuilderJvmKaptTest", + ":KotlinJvmTaskExecutorTest", ":SourceJarCreatorTest", ], visibility = ["//visibility:public"], diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java index bcf18ab5d..3cab60cec 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java @@ -63,7 +63,7 @@ public final List outLines() { return outLines; } - final void resetForNext() { + public final void resetForNext() { outLines = null; label = "a_test_" + counter.incrementAndGet(); infoBuilder @@ -96,8 +96,8 @@ public final void setDebugTags(String... tags) { infoBuilder.addAllDebug(Arrays.asList(tags)); } - final Path writeSourceFile(String filename, String[] lines) { - Path path = directory(DirectoryType.SOURCES).resolve(filename).toAbsolutePath(); + final Path writeFile(DirectoryType dirType, String filename, String[] lines) { + Path path = directory(dirType).resolve(filename).toAbsolutePath(); try (FileOutputStream fos = new FileOutputStream(path.toFile())) { fos.write(String.join("\n", lines).getBytes(UTF_8)); } catch (IOException e) { @@ -106,6 +106,14 @@ final Path writeSourceFile(String filename, String[] lines) { return path; } + public final Path writeSourceFile(String filename, String[] lines) { + return writeFile(DirectoryType.SOURCES, filename, lines); + } + + public final Path writeGeneratedSourceFile(String filename, String[] lines) { + return writeFile(DirectoryType.SOURCE_GEN, filename, lines); + } + private R runCompileTask( CompilationTaskInfo info, T task, BiFunction operation) { String curDir = System.getProperty("user.dir"); diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java index 56c38a727..051cb3660 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java @@ -82,12 +82,12 @@ void setupForNext(CompilationTaskInfo.Builder taskInfo) { } @Override - JvmCompilationTask buildTask() { + public JvmCompilationTask buildTask() { return taskBuilder.build(); } public class TaskBuilder { - TaskBuilder() {} + public TaskBuilder() {} public void setLabel(String label) { taskBuilder.getInfoBuilder().setLabel(label); diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutorTest.kt b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutorTest.kt new file mode 100644 index 000000000..96f7a2758 --- /dev/null +++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutorTest.kt @@ -0,0 +1,50 @@ +package io.bazel.kotlin.builder.tasks.jvm + +import io.bazel.kotlin.builder.KotlinJsTestBuilder +import io.bazel.kotlin.builder.KotlinJvmTestBuilder +import io.bazel.kotlin.model.JvmCompilationTask +import org.junit.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertNotNull +import kotlin.test.assertTrue + +class KotlinJvmTaskExecutorTest { + + private val ctx = KotlinJvmTestBuilder() + + @Test + fun testSimpleGeneratedNonJvmSourcesIgnored() { + ctx.resetForNext() + ctx.writeGeneratedSourceFile( + "AGenClass.kt", + arrayOf("package something.gen;", "class AGenClass{}")) + ctx.writeGeneratedSourceFile( + "AnotherGenClass.java", + arrayOf("package something.gen;", "class AnotherGenClass{}")) + ctx.writeGeneratedSourceFile( + "ignore-me.txt", + arrayOf("contents do not matter")) + ctx.writeSourceFile( + "ignore-me-regular-src.kt", + arrayOf("contents do not matter")) + ctx.writeSourceFile( + "ignore-me-another-regular-src.java", + arrayOf("contents do not matter")) + val compileTask = ctx.buildTask() + + assertFalse(compileTask.hasInputs()) + + val expandedCompileTask = compileTask.expandWithGeneratedSources() + + assertFalse(compileTask.hasInputs()) + + assertTrue(expandedCompileTask.hasInputs()) + assertNotNull(expandedCompileTask.inputs.javaSourcesList.find { + path -> path.endsWith("a_test_1/generated_sources/AnotherGenClass.java") }) + assertEquals(expandedCompileTask.inputs.javaSourcesCount, 1) + assertNotNull(expandedCompileTask.inputs.kotlinSourcesList.find { + path -> path.endsWith("a_test_1/generated_sources/AGenClass.kt") }) + assertEquals(expandedCompileTask.inputs.kotlinSourcesCount, 1) + } +} \ No newline at end of file From 3ae7902dfaf5c4b43919b4e3221315ae63db84c2 Mon Sep 17 00:00:00 2001 From: factuno-db Date: Thu, 27 Feb 2020 01:03:29 +0100 Subject: [PATCH 06/16] Update README.md (#285) kt_download_local_dev_dependencies is exported via dependencies.bzl, not via kotlin.bzl --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 691a653ff..3b23dcc5f 100644 --- a/README.md +++ b/README.md @@ -154,7 +154,7 @@ local_repository( path = "../path/to/rules_kotlin_clone", ) -load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_download_local_dev_dependencies") +load("@io_bazel_rules_kotlin//kotlin:dependencies.bzl", "kt_download_local_dev_dependencies") kt_download_local_dev_dependencies() load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kotlin_repositories", "kt_register_toolchains") kotlin_repositories() # if you want the default. Otherwise see custom kotlinc distribution below From ffcd2b2e7ea787eca1ab5bf09f296b06f9fe933f Mon Sep 17 00:00:00 2001 From: Corbin McNeely-Smith <58151731+restingbull@users.noreply.github.com> Date: Thu, 27 Feb 2020 10:16:52 -0500 Subject: [PATCH 07/16] Cleanup src tree (#288) * Move CompilationTaskContext to toolchain, as it doesn't really belong in utils. * Move KotlinCompilerPluginArgsEncoder to toolchain. Temporary placement, new location TBD * Isolate the utils package * Move toolchain into a separate compilation unit. Causes some issues with inlining. * Split apart test packages. * Split apart test packages. * Split apart test packages. * add bazel version for development * factor out JvmCompilationTask extensions to reuse in abi generation * move compiler to source package. add .bazelversion for development --- .bazelproject | 8 +- .bazelrc | 2 +- .bazelversion | 1 + src/main/kotlin/BUILD | 17 +- src/main/kotlin/io/bazel/kotlin/builder/BUILD | 24 +- .../builder/KotlinBuilderComponent.java | 2 +- .../io/bazel/kotlin/builder/tasks/BUILD.bazel | 34 +++ .../kotlin/builder/tasks/KotlinBuilder.kt | 1 + .../builder/tasks/js/Kotlin2JsTaskExecutor.kt | 3 +- .../kotlin/builder/tasks/jvm/JavaCompiler.kt | 2 +- .../tasks/jvm/KotlinJvmTaskExecutor.kt | 211 ++-------------- .../builder/tasks/jvm/compilation_task.kt | 236 ++++++++++++++++++ .../kotlin/builder/toolchain/BUILD.bazel | 30 +++ .../CompilationTaskContext.kt | 10 +- .../KotlinCompilerPluginArgsEncoder.kt | 4 +- .../builder/toolchain/KotlinToolchain.kt | 200 +++++++-------- .../io/bazel/kotlin/builder/utils/BUILD.bazel | 31 +++ .../io/bazel/kotlin/compiler/BUILD.bazel | 27 ++ src/test/kotlin/io/bazel/kotlin/builder/BUILD | 59 +---- .../builder/KotlinAbstractTestBuilder.java | 2 +- .../io/bazel/kotlin/builder/tasks/BUILD.bazel | 56 +++++ .../io/bazel/kotlin/builder/utils/BUILD.bazel | 25 ++ 22 files changed, 584 insertions(+), 401 deletions(-) create mode 100644 .bazelversion create mode 100644 src/main/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel create mode 100644 src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt create mode 100644 src/main/kotlin/io/bazel/kotlin/builder/toolchain/BUILD.bazel rename src/main/kotlin/io/bazel/kotlin/builder/{utils => toolchain}/CompilationTaskContext.kt (95%) rename src/main/kotlin/io/bazel/kotlin/builder/{utils => toolchain}/KotlinCompilerPluginArgsEncoder.kt (98%) create mode 100644 src/main/kotlin/io/bazel/kotlin/builder/utils/BUILD.bazel create mode 100644 src/main/kotlin/io/bazel/kotlin/compiler/BUILD.bazel create mode 100644 src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel create mode 100644 src/test/kotlin/io/bazel/kotlin/builder/utils/BUILD.bazel diff --git a/.bazelproject b/.bazelproject index b5daf792e..0be2b5a76 100644 --- a/.bazelproject +++ b/.bazelproject @@ -26,8 +26,10 @@ targets: //examples/dagger/... # These targets are built for the ide only. Primary purpose is to ensure the builder can build the targets, but it's # also a good way of testing the intellij plugin. - //src/main/kotlin/io/bazel/kotlin/builder:builder_kt_for_ide - //src/main/kotlin:compiler_lib_for_ide + //src/main/kotlin/io/bazel/kotlin/builder/tasks:tasks_for_ide + //src/main/kotlin/io/bazel/kotlin/builder/utils:utils_for_ide + //src/main/kotlin/io/bazel/kotlin/builder/toolchain:toolchain_for_ide + //src/main/kotlin/io/bazel/kotlin/compiler:compiler_for_ide test_sources: src/test/* @@ -36,4 +38,4 @@ additional_languages: kotlin import_run_configurations: - src/test/Bazel_all_local_tests.xml \ No newline at end of file + src/test/Bazel_all_local_tests.xml diff --git a/.bazelrc b/.bazelrc index e75318b3a..6858b6449 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,4 +1,4 @@ build --strategy=KotlinCompile=worker -build --test_output=errors +build --test_output=all build --verbose_failures diff --git a/.bazelversion b/.bazelversion new file mode 100644 index 000000000..227cea215 --- /dev/null +++ b/.bazelversion @@ -0,0 +1 @@ +2.0.0 diff --git a/src/main/kotlin/BUILD b/src/main/kotlin/BUILD index da083be62..7fd6f1c2f 100644 --- a/src/main/kotlin/BUILD +++ b/src/main/kotlin/BUILD @@ -12,23 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. load("@rules_java//java:defs.bzl", "java_binary") -load("//src/main/kotlin:bootstrap.bzl", "kt_bootstrap_library") load("//kotlin:kotlin.bzl", "kt_jvm_library") load("//third_party:jarjar.bzl", "jar_jar") load("//kotlin/internal/utils:packager.bzl", "release_archive") -# The compiler library, this is co-located in the kotlin compiler classloader. -kt_bootstrap_library( - name = "compiler_lib", - srcs = glob(["io/bazel/kotlin/compiler/*.kt"]), - neverlink_deps = [ - "@com_github_jetbrains_kotlin//:kotlin-compiler", - "@com_github_jetbrains_kotlin//:kotlin-annotation-processing", - "@com_github_jetbrains_kotlin//:kotlin-script-runtime", - ], - visibility = ["//src/test/kotlin/io/bazel/kotlin/builder:__subpackages__"], -) - java_binary( name = "builder_raw", create_executable = False, @@ -46,7 +33,7 @@ jar_jar( java_binary( name = "builder", data = [ - ":compiler_lib.jar", + "//src/main/kotlin/io/bazel/kotlin/compiler:compiler", "@com_github_jetbrains_kotlin//:lib/kotlin-compiler.jar", ], jvm_flags = [ @@ -63,7 +50,7 @@ java_binary( release_archive( name = "pkg", srcs = [ - ":compiler_lib.jar", + "//src/main/kotlin/io/bazel/kotlin/compiler:compiler", ], package_dir = "src/main/kotlin", # explicitly set the package directory, as there are no parent release_archives. src_map = { diff --git a/src/main/kotlin/io/bazel/kotlin/builder/BUILD b/src/main/kotlin/io/bazel/kotlin/builder/BUILD index 385295d17..527161266 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/BUILD +++ b/src/main/kotlin/io/bazel/kotlin/builder/BUILD @@ -12,37 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. load("@rules_java//java:defs.bzl", "java_library") -load("//src/main/kotlin:bootstrap.bzl", "kt_bootstrap_library") - -kt_bootstrap_library( - name = "builder_kt", - srcs = glob([ - "toolchain/*.kt", - "tasks/**/*.kt", - "utils/**/*.kt", - ]), - deps = [ - "//src/main/protobuf:deps_java_proto", - "//src/main/protobuf:kotlin_model_java_proto", - "//src/main/protobuf:worker_protocol_java_proto", - "@com_github_jetbrains_kotlin//:kotlin-preloader", - "@kotlin_rules_maven//:com_google_protobuf_protobuf_java", - "@kotlin_rules_maven//:com_google_protobuf_protobuf_java_util", - "@kotlin_rules_maven//:javax_inject_javax_inject", - ], -) java_library( name = "builder", srcs = glob(["*.java"]), visibility = ["//src:__subpackages__"], - exports = [":builder_kt"], runtime_deps = [ "@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk7", "@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk8", ], deps = [ - ":builder_kt", "//src/main/protobuf:deps_java_proto", "//src/main/protobuf:kotlin_model_java_proto", "//src/main/protobuf:worker_protocol_java_proto", @@ -50,5 +29,8 @@ java_library( "@com_github_jetbrains_kotlin//:annotations", "@com_github_jetbrains_kotlin//:kotlin-stdlib", "@kotlin_rules_maven//:javax_inject_javax_inject", + "//src/main/kotlin/io/bazel/kotlin/builder/utils:utils", + "//src/main/kotlin/io/bazel/kotlin/builder/toolchain:toolchain", + "//src/main/kotlin/io/bazel/kotlin/builder/tasks:tasks", ], ) diff --git a/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java b/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java index 88dc8d390..a3f0daac3 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java +++ b/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java @@ -23,7 +23,7 @@ import io.bazel.kotlin.builder.tasks.js.Kotlin2JsTaskExecutor; import io.bazel.kotlin.builder.tasks.jvm.KotlinJvmTaskExecutor; import io.bazel.kotlin.builder.toolchain.KotlinToolchain; -import io.bazel.kotlin.builder.utils.KotlinCompilerPluginArgsEncoder; +import io.bazel.kotlin.builder.toolchain.KotlinCompilerPluginArgsEncoder; import javax.inject.Singleton; import java.io.PrintStream; diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel b/src/main/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel new file mode 100644 index 000000000..d8c7d501a --- /dev/null +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel @@ -0,0 +1,34 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed 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. + +load("//src/main/kotlin:bootstrap.bzl", "kt_bootstrap_library") + +kt_bootstrap_library( + name = "tasks", + srcs = glob([ + "**/*.kt", + ]), + visibility = ["//src:__subpackages__"], + deps = [ + "//src/main/protobuf:deps_java_proto", + "//src/main/protobuf:kotlin_model_java_proto", + "//src/main/protobuf:worker_protocol_java_proto", + "@com_github_jetbrains_kotlin//:kotlin-preloader", + "@kotlin_rules_maven//:com_google_protobuf_protobuf_java", + "@kotlin_rules_maven//:com_google_protobuf_protobuf_java_util", + "@kotlin_rules_maven//:javax_inject_javax_inject", + "//src/main/kotlin/io/bazel/kotlin/builder/utils:utils", + "//src/main/kotlin/io/bazel/kotlin/builder/toolchain:toolchain", + ], +) \ No newline at end of file diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt index 339699f51..3cc5c1637 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt @@ -18,6 +18,7 @@ package io.bazel.kotlin.builder.tasks import io.bazel.kotlin.builder.tasks.js.Kotlin2JsTaskExecutor import io.bazel.kotlin.builder.tasks.jvm.KotlinJvmTaskExecutor import io.bazel.kotlin.builder.toolchain.CompilationStatusException +import io.bazel.kotlin.builder.toolchain.CompilationTaskContext import io.bazel.kotlin.builder.utils.* import io.bazel.kotlin.model.* import java.io.PrintStream diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt index 028130b24..fa5dc45e8 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt @@ -2,12 +2,11 @@ package io.bazel.kotlin.builder.tasks.js import io.bazel.kotlin.builder.toolchain.CompilationException import io.bazel.kotlin.builder.toolchain.KotlinToolchain -import io.bazel.kotlin.builder.utils.CompilationTaskContext +import io.bazel.kotlin.builder.toolchain.CompilationTaskContext import io.bazel.kotlin.builder.utils.addAll import io.bazel.kotlin.builder.utils.jars.JarCreator import io.bazel.kotlin.builder.utils.jars.SourceJarCreator import io.bazel.kotlin.builder.utils.resolveTwinVerified -import io.bazel.kotlin.builder.utils.verifiedPath import io.bazel.kotlin.model.JsCompilationTask import java.io.FileOutputStream import java.nio.file.Files diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt index 606f644fd..d006026fa 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt @@ -16,7 +16,7 @@ package io.bazel.kotlin.builder.tasks.jvm import io.bazel.kotlin.builder.toolchain.KotlinToolchain -import io.bazel.kotlin.builder.utils.CompilationTaskContext +import io.bazel.kotlin.builder.toolchain.CompilationTaskContext import io.bazel.kotlin.builder.utils.addAll import io.bazel.kotlin.builder.utils.joinedClasspath import io.bazel.kotlin.model.JvmCompilationTask diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt index c326fd977..293520725 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt @@ -15,16 +15,10 @@ */ package io.bazel.kotlin.builder.tasks.jvm -import io.bazel.kotlin.builder.toolchain.CompilationStatusException +import io.bazel.kotlin.builder.toolchain.CompilationTaskContext +import io.bazel.kotlin.builder.toolchain.KotlinCompilerPluginArgsEncoder import io.bazel.kotlin.builder.toolchain.KotlinToolchain -import io.bazel.kotlin.builder.utils.* -import io.bazel.kotlin.builder.utils.jars.JarCreator -import io.bazel.kotlin.builder.utils.jars.SourceJarCreator -import io.bazel.kotlin.builder.utils.jars.SourceJarExtractor import io.bazel.kotlin.model.JvmCompilationTask -import java.io.File -import java.nio.file.Files -import java.nio.file.Paths import javax.inject.Inject import javax.inject.Singleton @@ -36,196 +30,19 @@ const val X_FRIENDS_PATH_SEPARATOR = "," @Singleton class KotlinJvmTaskExecutor @Inject internal constructor( - private val compiler: KotlinToolchain.KotlincInvoker, - private val pluginArgsEncoder: KotlinCompilerPluginArgsEncoder, - private val javaCompiler: JavaCompiler, - private val jDepsGenerator: JDepsGenerator + private val compiler: KotlinToolchain.KotlincInvoker, + private val pluginArgsEncoder: KotlinCompilerPluginArgsEncoder, + private val javaCompiler: JavaCompiler, + private val jDepsGenerator: JDepsGenerator ) { - fun execute(context: CompilationTaskContext, task: JvmCompilationTask) { - val preprocessedTask = task.preProcessingSteps(context) - context.execute("compile classes") { preprocessedTask.compileAll(context) } - context.execute("create jar") { preprocessedTask.createOutputJar() } - context.execute("produce src jar") { preprocessedTask.produceSourceJar() } - context.execute("generate jdeps") { jDepsGenerator.generateJDeps(preprocessedTask) } + fun execute(context: CompilationTaskContext, task: JvmCompilationTask) { + val preprocessedTask = task.preProcessingSteps(context, pluginArgsEncoder, compiler) + context.execute("compile classes") { + preprocessedTask.compileAll(context, compiler, javaCompiler) } - private fun JvmCompilationTask.preProcessingSteps(context: CompilationTaskContext): JvmCompilationTask { - ensureDirectories( - directories.temp, - directories.generatedSources, - directories.generatedClasses - ) - val taskWithAdditionalSources = context.execute("expand sources") { expandWithSourceJarSources() } - return context.execute({ - "kapt (${inputs.processorsList.joinToString(", ")})" - }) { taskWithAdditionalSources.runAnnotationProcessors(context) } - } - - private fun JvmCompilationTask.produceSourceJar() { - Paths.get(outputs.srcjar).also { sourceJarPath -> - Files.createFile(sourceJarPath) - SourceJarCreator( - sourceJarPath - ).also { creator -> - // This check asserts that source jars were unpacked if present. - check( - inputs.sourceJarsList.isEmpty() || - Files.exists(Paths.get(directories.temp).resolve("_srcjars")) - ) - listOf( - // Any (input) source jars should already have been expanded so do not add them here. - inputs.javaSourcesList.stream(), - inputs.kotlinSourcesList.stream() - ).stream() - .flatMap { it.map { p -> Paths.get(p) } } - .also { creator.addSources(it) } - creator.execute() - } - } - } - - private fun JvmCompilationTask.runAnnotationProcessor( - context: CompilationTaskContext, - printOnSuccess: Boolean = true - ): List { - check(inputs.processorsList.isNotEmpty()) { "method called without annotation processors" } - return getCommonArgs().let { args -> - args.addAll(pluginArgsEncoder.encode(context, this)) - args.addAll(inputs.kotlinSourcesList) - args.addAll(inputs.javaSourcesList) - context.executeCompilerTask(args, compiler::compile, printOnSuccess = printOnSuccess) - } - } - - /** - * Return a list with the common arguments. - */ - private fun JvmCompilationTask.getCommonArgs(): MutableList { - val args = mutableListOf() - val friendPaths = info.friendPathsList.map { Paths.get(it).toAbsolutePath() } - val cp = inputs.joinedClasspath - .split(File.pathSeparator) - .map { Paths.get(it).toAbsolutePath() } - .joinToString(File.pathSeparator) - args.addAll( - "-cp", cp, - "-api-version", info.toolchainInfo.common.apiVersion, - "-language-version", info.toolchainInfo.common.languageVersion, - "-jvm-target", info.toolchainInfo.jvm.jvmTarget, - "-Xfriend-paths=${friendPaths.joinToString(X_FRIENDS_PATH_SEPARATOR)}" - ) - args - .addAll("-module-name", info.moduleName) - .addAll("-d", directories.classes) - - info.passthroughFlags?.takeIf { it.isNotBlank() }?.also { args.addAll(it.split(" ")) } - return args - } - - private fun JvmCompilationTask.runAnnotationProcessors( - context: CompilationTaskContext - ): JvmCompilationTask = - if (inputs.processorsList.isEmpty()) { - this - } else { - runAnnotationProcessor(context, printOnSuccess = !context.isTracing).let { outputLines -> - // if tracing is enabled the output should be formatted in a special way, if we aren't tracing then any - // compiler output would make it's way to the console as is. - if (context.isTracing) { - context.printLines("kapt output", outputLines) - } - expandWithGeneratedSources() - } - } - - /** - * Produce the primary output jar. - */ - private fun JvmCompilationTask.createOutputJar() = - JarCreator( - path = Paths.get(outputs.jar), - normalize = true, - verbose = false - ).also { - it.addDirectory(Paths.get(directories.classes)) - it.addDirectory(Paths.get(directories.generatedClasses)) - it.setJarOwner(info.label, info.bazelRuleKind) - it.execute() - } - - private fun JvmCompilationTask.compileAll(context: CompilationTaskContext) { - ensureDirectories( - directories.classes - ) - var kotlinError: CompilationStatusException? = null - var result: List? = null - context.execute("kotlinc") { - result = try { - compileKotlin(context, printOnFail = false) - } catch (ex: CompilationStatusException) { - kotlinError = ex - ex.lines - } - } - try { - context.execute("javac") { javaCompiler.compile(context, this) } - } finally { - checkNotNull(result).also(context::printCompilerOutput) - kotlinError?.also { throw it } - } - } - - /** - * Compiles Kotlin sources to classes. Does not compile Java sources. - */ - private fun JvmCompilationTask.compileKotlin(context: CompilationTaskContext, printOnFail: Boolean = true) = - getCommonArgs().let { args -> - args.addAll(inputs.javaSourcesList) - args.addAll(inputs.kotlinSourcesList) - context.executeCompilerTask(args, compiler::compile, printOnFail = printOnFail) - } - - /** - * If any srcjars were provided expand the jars sources and create a new [JvmCompilationTask] with the - * Java and Kotlin sources merged in. - */ - private fun JvmCompilationTask.expandWithSourceJarSources(): JvmCompilationTask = - if (inputs.sourceJarsList.isEmpty()) - this - else expandWithSources( - SourceJarExtractor( - destDir = Paths.get(directories.temp).resolve("_srcjars"), - fileMatcher = IS_JVM_SOURCE_FILE - ).also { - it.jarFiles.addAll(inputs.sourceJarsList.map { p -> Paths.get(p) }) - it.execute() - }.sourcesList.iterator() - ) + context.execute("create jar") { preprocessedTask.createOutputJar() } + context.execute("produce src jar") { preprocessedTask.produceSourceJar() } + context.execute("generate jdeps") { jDepsGenerator.generateJDeps(preprocessedTask) } + } } - -/** - * Create a new [JvmCompilationTask] with sources found in the generatedSources directory. This should be run after - * annotation processors have been run. - */ -fun JvmCompilationTask.expandWithGeneratedSources(): JvmCompilationTask = - expandWithSources( - File(directories.generatedSources).walkTopDown() - .filter { it.isFile && IS_JVM_SOURCE_FILE.test(it.name) } - .map { it.path } - .iterator() - ) - -fun JvmCompilationTask.expandWithSources(sources: Iterator): JvmCompilationTask = - updateBuilder { builder -> - sources.partitionJvmSources( - { builder.inputsBuilder.addKotlinSources(it) }, - { builder.inputsBuilder.addJavaSources(it) }) - } - -fun JvmCompilationTask.updateBuilder( - block: (JvmCompilationTask.Builder) -> Unit -): JvmCompilationTask = - toBuilder().let { - block(it) - it.build() - } \ No newline at end of file diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt new file mode 100644 index 000000000..d9dcbfb2f --- /dev/null +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt @@ -0,0 +1,236 @@ +/* + * Copyright 2020 The Bazel Authors. All rights reserved. + * + * Licensed 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. + */ + +// Provides extensions for the JvmCompilationTask protocol buffer. +package io.bazel.kotlin.builder.tasks.jvm + +import io.bazel.kotlin.builder.toolchain.CompilationStatusException +import io.bazel.kotlin.builder.toolchain.CompilationTaskContext +import io.bazel.kotlin.builder.toolchain.KotlinCompilerPluginArgsEncoder +import io.bazel.kotlin.builder.toolchain.KotlinToolchain +import io.bazel.kotlin.builder.utils.IS_JVM_SOURCE_FILE +import io.bazel.kotlin.builder.utils.addAll +import io.bazel.kotlin.builder.utils.bazelRuleKind +import io.bazel.kotlin.builder.utils.ensureDirectories +import io.bazel.kotlin.builder.utils.jars.JarCreator +import io.bazel.kotlin.builder.utils.jars.SourceJarCreator +import io.bazel.kotlin.builder.utils.jars.SourceJarExtractor +import io.bazel.kotlin.builder.utils.joinedClasspath +import io.bazel.kotlin.builder.utils.partitionJvmSources +import io.bazel.kotlin.model.JvmCompilationTask +import java.io.File +import java.nio.file.Files +import java.nio.file.Paths + +/** + * Return a list with the common arguments. + */ +internal fun JvmCompilationTask.getCommonArgs(): MutableList { + val args = mutableListOf() + val friendPaths = info.friendPathsList.map { Paths.get(it).toAbsolutePath() } + val cp = inputs.joinedClasspath + .split(File.pathSeparator) + .map { Paths.get(it).toAbsolutePath() } + .joinToString(File.pathSeparator) + args.addAll( + "-cp", cp, + "-api-version", info.toolchainInfo.common.apiVersion, + "-language-version", info.toolchainInfo.common.languageVersion, + "-jvm-target", info.toolchainInfo.jvm.jvmTarget, + "-Xfriend-paths=${friendPaths.joinToString(X_FRIENDS_PATH_SEPARATOR)}" + ) + args + .addAll("-module-name", info.moduleName) + .addAll("-d", directories.classes) + + info.passthroughFlags?.takeIf { it.isNotBlank() }?.also { args.addAll(it.split(" ")) } + return args +} + +internal fun JvmCompilationTask.preProcessingSteps( + context: CompilationTaskContext, + pluginArgsEncoder: KotlinCompilerPluginArgsEncoder, + compiler: KotlinToolchain.KotlincInvoker +): JvmCompilationTask { + ensureDirectories( + directories.temp, + directories.generatedSources, + directories.generatedClasses + ) + val taskWithAdditionalSources = context.execute("expand sources") { expandWithSourceJarSources() } + return context.execute({ + "kapt (${inputs.processorsList.joinToString(", ")})" + }) { taskWithAdditionalSources.runAnnotationProcessors(context, pluginArgsEncoder, compiler) } +} + +internal fun JvmCompilationTask.produceSourceJar() { + Paths.get(outputs.srcjar).also { sourceJarPath -> + Files.createFile(sourceJarPath) + SourceJarCreator( + sourceJarPath + ).also { creator -> + // This check asserts that source jars were unpacked if present. + check( + inputs.sourceJarsList.isEmpty() || + Files.exists(Paths.get(directories.temp).resolve("_srcjars")) + ) + listOf( + // Any (input) source jars should already have been expanded so do not add them here. + inputs.javaSourcesList.stream(), + inputs.kotlinSourcesList.stream() + ).stream() + .flatMap { it.map { p -> Paths.get(p) } } + .also { creator.addSources(it) } + creator.execute() + } + } +} + +internal fun JvmCompilationTask.runAnnotationProcessor( + context: CompilationTaskContext, + pluginArgsEncoder: KotlinCompilerPluginArgsEncoder, + compiler: KotlinToolchain.KotlincInvoker, + printOnSuccess: Boolean = true +): List { + check(inputs.processorsList.isNotEmpty()) { "method called without annotation processors" } + return getCommonArgs().let { args -> + args.addAll(pluginArgsEncoder.encode(context, this)) + args.addAll(inputs.kotlinSourcesList) + args.addAll(inputs.javaSourcesList) + context.executeCompilerTask(args, compiler::compile, printOnSuccess = printOnSuccess) + } +} + +internal fun JvmCompilationTask.runAnnotationProcessors( + context: CompilationTaskContext, + pluginArgsEncoder: KotlinCompilerPluginArgsEncoder, + compiler: KotlinToolchain.KotlincInvoker +): JvmCompilationTask = + if (inputs.processorsList.isEmpty()) { + this + } else { + runAnnotationProcessor( + context, + pluginArgsEncoder, + compiler, + printOnSuccess = context.whenTracing { false } ?: true).let { outputLines -> + // if tracing is enabled the output should be formatted in a special way, if we aren't tracing then any + // compiler output would make it's way to the console as is. + context.whenTracing { + printLines("kapt output", outputLines) + } + expandWithGeneratedSources() + } + } + +/** + * Produce the primary output jar. + */ +internal fun JvmCompilationTask.createOutputJar() = + JarCreator( + path = Paths.get(outputs.jar), + normalize = true, + verbose = false + ).also { + it.addDirectory(Paths.get(directories.classes)) + it.addDirectory(Paths.get(directories.generatedClasses)) + it.setJarOwner(info.label, info.bazelRuleKind) + it.execute() + } + +internal fun JvmCompilationTask.compileAll( + context: CompilationTaskContext, + compiler: KotlinToolchain.KotlincInvoker, + javaCompiler: JavaCompiler +) { + ensureDirectories( + directories.classes + ) + var kotlinError: CompilationStatusException? = null + var result: List? = null + context.execute("kotlinc") { + result = try { + compileKotlin(context, compiler, printOnFail = false) + } catch (ex: CompilationStatusException) { + kotlinError = ex + ex.lines + } + } + try { + context.execute("javac") { javaCompiler.compile(context, this) } + } finally { + checkNotNull(result).also(context::printCompilerOutput) + kotlinError?.also { throw it } + } +} + +/** + * Compiles Kotlin sources to classes. Does not compile Java sources. + */ +internal fun JvmCompilationTask.compileKotlin( + context: CompilationTaskContext, + compiler: KotlinToolchain.KotlincInvoker, + printOnFail: Boolean = true +) = + getCommonArgs().let { args -> + args.addAll(inputs.javaSourcesList) + args.addAll(inputs.kotlinSourcesList) + context.executeCompilerTask(args, compiler::compile, printOnFail = printOnFail) + } + +/** + * If any srcjars were provided expand the jars sources and create a new [JvmCompilationTask] with the + * Java and Kotlin sources merged in. + */ +internal fun JvmCompilationTask.expandWithSourceJarSources(): JvmCompilationTask = + if (inputs.sourceJarsList.isEmpty()) + this + else expandWithSources( + SourceJarExtractor( + destDir = Paths.get(directories.temp).resolve("_srcjars"), + fileMatcher = IS_JVM_SOURCE_FILE + ).also { + it.jarFiles.addAll(inputs.sourceJarsList.map { p -> Paths.get(p) }) + it.execute() + }.sourcesList.iterator() + ) + +/** + * Create a new [JvmCompilationTask] with sources found in the generatedSources directory. This should be run after + * annotation processors have been run. + */ +internal fun JvmCompilationTask.expandWithGeneratedSources(): JvmCompilationTask = + expandWithSources( + File(directories.generatedSources).walkTopDown() + .filter { it.isFile } + .map { it.path } + .iterator() + ) + +internal fun JvmCompilationTask.expandWithSources(sources: Iterator): JvmCompilationTask = + updateBuilder { builder -> + sources.partitionJvmSources( + { builder.inputsBuilder.addKotlinSources(it) }, + { builder.inputsBuilder.addJavaSources(it) }) + } + +internal fun JvmCompilationTask.updateBuilder( + block: (JvmCompilationTask.Builder) -> Unit +): JvmCompilationTask = + toBuilder().let { + block(it) + it.build() + } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/BUILD.bazel b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/BUILD.bazel new file mode 100644 index 000000000..b9c66dc22 --- /dev/null +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/BUILD.bazel @@ -0,0 +1,30 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed 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 + +load("//src/main/kotlin:bootstrap.bzl", "kt_bootstrap_library") + +kt_bootstrap_library( + name = "toolchain", + srcs = glob([ + "*.kt", + ]), + visibility = ["//src:__subpackages__"], + deps = [ + "//src/main/protobuf:kotlin_model_java_proto", + "@com_github_jetbrains_kotlin//:kotlin-preloader", + "@kotlin_rules_maven//:com_google_protobuf_protobuf_java", + "@kotlin_rules_maven//:com_google_protobuf_protobuf_java_util", + "@kotlin_rules_maven//:javax_inject_javax_inject", + "//src/main/kotlin/io/bazel/kotlin/builder/utils:utils", + ], +) diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/CompilationTaskContext.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt similarity index 95% rename from src/main/kotlin/io/bazel/kotlin/builder/utils/CompilationTaskContext.kt rename to src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt index 9d02c202f..42c04a6b1 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/CompilationTaskContext.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.bazel.kotlin.builder.utils +package io.bazel.kotlin.builder.toolchain import com.google.protobuf.MessageOrBuilder import com.google.protobuf.TextFormat -import io.bazel.kotlin.builder.toolchain.CompilationStatusException import io.bazel.kotlin.model.CompilationTaskInfo import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream @@ -32,8 +31,7 @@ class CompilationTaskContext(val info: CompilationTaskInfo, private val out: Pri ).toAbsolutePath().toString() + File.separator private var timings: MutableList? private var level = -1 - @PublishedApi - internal val isTracing: Boolean + private val isTracing: Boolean init { val debugging = info.debugList.toSet() @@ -69,7 +67,7 @@ class CompilationTaskContext(val info: CompilationTaskInfo, private val out: Pri out.println() } - inline fun whenTracing(block: CompilationTaskContext.() -> T): T? { + fun whenTracing(block: CompilationTaskContext.() -> T): T? { return if (isTracing) { block() } else null @@ -105,7 +103,7 @@ class CompilationTaskContext(val info: CompilationTaskInfo, private val out: Pri * for logging it by catching the [CompilationStatusException] exception. * @param compile the compilation method. */ - inline fun executeCompilerTask( + fun executeCompilerTask( args: List, compile: (Array, PrintStream) -> Int, printOnFail: Boolean = true, diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/KotlinCompilerPluginArgsEncoder.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinCompilerPluginArgsEncoder.kt similarity index 98% rename from src/main/kotlin/io/bazel/kotlin/builder/utils/KotlinCompilerPluginArgsEncoder.kt rename to src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinCompilerPluginArgsEncoder.kt index 93eba5998..f141159bc 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/KotlinCompilerPluginArgsEncoder.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinCompilerPluginArgsEncoder.kt @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.bazel.kotlin.builder.utils +package io.bazel.kotlin.builder.toolchain import io.bazel.kotlin.model.JvmCompilationTask import java.io.ByteArrayOutputStream import java.io.ObjectOutputStream -import java.util.* +import java.util.Base64 // TODO(hs) move the kapt specific stuff to the JVM package. class KotlinCompilerPluginArgsEncoder( diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt index 5fbf9e736..d76f48e0b 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt @@ -29,112 +29,116 @@ import javax.inject.Inject import javax.inject.Singleton class KotlinToolchain private constructor( - val kotlinHome: Path, - val classLoader: ClassLoader, - val kotlinStandardLibraries: List = listOf( - "kotlin-stdlib.jar", - "kotlin-stdlib-jdk7.jar", - "kotlin-stdlib-jdk8.jar" - ), - val kapt3Plugin: KotlinToolchain.CompilerPlugin = KotlinToolchain.CompilerPlugin( - kotlinHome.resolveVerified("lib", "kotlin-annotation-processing.jar").absolutePath, - "org.jetbrains.kotlin.kapt3" - ) + val kotlinHome: Path, + val classLoader: ClassLoader, + val kotlinStandardLibraries: List = listOf( + "kotlin-stdlib.jar", + "kotlin-stdlib-jdk7.jar", + "kotlin-stdlib-jdk8.jar" + ), + val kapt3Plugin: KotlinToolchain.CompilerPlugin = KotlinToolchain.CompilerPlugin( + kotlinHome.resolveVerified("lib", "kotlin-annotation-processing.jar").absolutePath, + "org.jetbrains.kotlin.kapt3" + ) ) { - companion object { - internal val NO_ARGS = arrayOf() - - private val isJdk9OrNewer = !System.getProperty("java.version").startsWith("1.") - - private fun createClassLoader(javaHome: Path, baseJars: List): ClassLoader = - ClassPreloadingUtils.preloadClasses( - mutableListOf().also { - it += baseJars - if (!isJdk9OrNewer) { - it += javaHome.resolveVerified("lib", "tools.jar") - } - }, - Preloader.DEFAULT_CLASS_NUMBER_ESTIMATE, - ClassLoader.getSystemClassLoader(), - null - ) - - @JvmStatic - fun createToolchain(): KotlinToolchain { - val javaHome = Paths.get(System.getProperty("java.home")).let { path -> - path.takeIf { !it.endsWith(Paths.get("jre")) } ?: path.parent - } - val kotlinCompilerJar = BazelRunFiles.resolveVerified( - "external", "com_github_jetbrains_kotlin", "lib", "kotlin-compiler.jar") - return KotlinToolchain( - kotlinCompilerJar.toPath().parent.parent, - createClassLoader( - javaHome, - listOf( - kotlinCompilerJar, - BazelRunFiles.resolveVerified( - "io_bazel_rules_kotlin", "src", "main", "kotlin", "compiler_lib.jar") - ) - ) - ) - } + companion object { + internal val NO_ARGS = arrayOf() + + private val isJdk9OrNewer = !System.getProperty("java.version").startsWith("1.") + + private fun createClassLoader(javaHome: Path, baseJars: List): ClassLoader = + ClassPreloadingUtils.preloadClasses( + mutableListOf().also { + it += baseJars + if (!isJdk9OrNewer) { + it += javaHome.resolveVerified("lib", "tools.jar") + } + }, + Preloader.DEFAULT_CLASS_NUMBER_ESTIMATE, + ClassLoader.getSystemClassLoader(), + null + ) + + @JvmStatic + fun createToolchain(): KotlinToolchain { + val javaHome = Paths.get(System.getProperty("java.home")).let { path -> + path.takeIf { !it.endsWith(Paths.get("jre")) } ?: path.parent + } + val kotlinCompilerJar = BazelRunFiles.resolveVerified( + "external", "com_github_jetbrains_kotlin", "lib", "kotlin-compiler.jar") + return KotlinToolchain( + kotlinCompilerJar.toPath().parent.parent, + createClassLoader( + javaHome, + listOf( + kotlinCompilerJar, + BazelRunFiles.resolveVerified( + "io_bazel_rules_kotlin", + "src", "main", "kotlin", "io", "bazel", "kotlin", "compiler", + "compiler.jar") + ) + ) + ) } - - data class CompilerPlugin(val jarPath: String, val id: String) - - @Singleton - class JavacInvoker @Inject constructor(toolchain: KotlinToolchain) { - private val c = toolchain.classLoader.loadClass("com.sun.tools.javac.Main") - private val m = c.getMethod("compile", Array::class.java) - private val mPw = c.getMethod("compile", Array::class.java, PrintWriter::class.java) - fun compile(args: Array) = m.invoke(c, args) as Int - fun compile(args: Array, out: PrintWriter) = mPw.invoke(c, args, out) as Int - } - - @Singleton - class JDepsInvoker @Inject constructor(toolchain: KotlinToolchain) { - private val clazz = toolchain.classLoader.loadClass("com.sun.tools.jdeps.Main") - private val method = clazz.getMethod("run", Array::class.java, PrintWriter::class.java) - fun run(args: Array, out: PrintWriter): Int = method.invoke(clazz, args, out) as Int + } + + data class CompilerPlugin(val jarPath: String, val id: String) + + @Singleton + class JavacInvoker @Inject constructor(toolchain: KotlinToolchain) { + private val c = toolchain.classLoader.loadClass("com.sun.tools.javac.Main") + private val m = c.getMethod("compile", Array::class.java) + private val mPw = c.getMethod("compile", Array::class.java, PrintWriter::class.java) + fun compile(args: Array) = m.invoke(c, args) as Int + fun compile(args: Array, out: PrintWriter) = mPw.invoke(c, args, out) as Int + } + + @Singleton + class JDepsInvoker @Inject constructor(toolchain: KotlinToolchain) { + private val clazz = toolchain.classLoader.loadClass("com.sun.tools.jdeps.Main") + private val method = clazz.getMethod("run", Array::class.java, PrintWriter::class.java) + fun run(args: Array, out: PrintWriter): Int = method.invoke(clazz, args, out) as Int + } + + open class KotlinCliToolInvoker internal constructor( + toolchain: KotlinToolchain, + clazz: String + ) { + private val compiler: Any + private val execMethod: Method + private val getCodeMethod: Method + + init { + val compilerClass = toolchain.classLoader.loadClass(clazz) + val exitCodeClass = + toolchain.classLoader.loadClass("org.jetbrains.kotlin.cli.common.ExitCode") + + compiler = compilerClass.getConstructor().newInstance() + execMethod = + compilerClass.getMethod("exec", PrintStream::class.java, Array::class.java) + getCodeMethod = exitCodeClass.getMethod("getCode") } - open class KotlinCliToolInvoker internal constructor( - toolchain: KotlinToolchain, - clazz: String - ) { - private val compiler: Any - private val execMethod: Method - private val getCodeMethod: Method - - init { - val compilerClass = toolchain.classLoader.loadClass(clazz) - val exitCodeClass = toolchain.classLoader.loadClass("org.jetbrains.kotlin.cli.common.ExitCode") - - compiler = compilerClass.getConstructor().newInstance() - execMethod = compilerClass.getMethod("exec", PrintStream::class.java, Array::class.java) - getCodeMethod = exitCodeClass.getMethod("getCode") - } - - // Kotlin error codes: - // 1 is a standard compilation error - // 2 is an internal error - // 3 is the script execution error - fun compile(args: Array, out: PrintStream): Int { - val exitCodeInstance = execMethod.invoke(compiler, out, args) - return getCodeMethod.invoke(exitCodeInstance, *NO_ARGS) as Int - } + // Kotlin error codes: + // 1 is a standard compilation error + // 2 is an internal error + // 3 is the script execution error + fun compile(args: Array, out: PrintStream): Int { + val exitCodeInstance = execMethod.invoke(compiler, out, args) + return getCodeMethod.invoke(exitCodeInstance, *NO_ARGS) as Int } + } - @Singleton - class KotlincInvoker @Inject constructor( - toolchain: KotlinToolchain - ) : KotlinCliToolInvoker(toolchain, "io.bazel.kotlin.compiler.BazelK2JVMCompiler") + @Singleton + class KotlincInvoker @Inject constructor( + toolchain: KotlinToolchain + ) : KotlinCliToolInvoker(toolchain, "io.bazel.kotlin.compiler.BazelK2JVMCompiler") - @Singleton - class K2JSCompilerInvoker @Inject constructor( - toolchain: KotlinToolchain - ) : KotlinCliToolInvoker(toolchain, "org.jetbrains.kotlin.cli.js.K2JSCompiler") + @Singleton + class K2JSCompilerInvoker @Inject constructor( + toolchain: KotlinToolchain + ) : KotlinCliToolInvoker(toolchain, "org.jetbrains.kotlin.cli.js.K2JSCompiler") } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/BUILD.bazel b/src/main/kotlin/io/bazel/kotlin/builder/utils/BUILD.bazel new file mode 100644 index 000000000..f82e208c3 --- /dev/null +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/BUILD.bazel @@ -0,0 +1,31 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed 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. +load("@rules_java//java:defs.bzl", "java_library") +load("//src/main/kotlin:bootstrap.bzl", "kt_bootstrap_library") + +kt_bootstrap_library( + name = "utils", + visibility = ["//src:__subpackages__",], + srcs = glob([ + "*.kt", + "**/*.kt", + ]), + deps = [ + "//src/main/protobuf:deps_java_proto", + "//src/main/protobuf:kotlin_model_java_proto", + "//src/main/protobuf:worker_protocol_java_proto", + "@kotlin_rules_maven//:com_google_protobuf_protobuf_java", + "@kotlin_rules_maven//:com_google_protobuf_protobuf_java_util", + ], +) diff --git a/src/main/kotlin/io/bazel/kotlin/compiler/BUILD.bazel b/src/main/kotlin/io/bazel/kotlin/compiler/BUILD.bazel new file mode 100644 index 000000000..d997f18ef --- /dev/null +++ b/src/main/kotlin/io/bazel/kotlin/compiler/BUILD.bazel @@ -0,0 +1,27 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed 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. + +load("//src/main/kotlin:bootstrap.bzl", "kt_bootstrap_library") + +# The compiler library, this is co-located in the kotlin compiler classloader. +kt_bootstrap_library( + name = "compiler", + srcs = glob(["*.kt"]), + visibility = ["//src:__subpackages__"], + neverlink_deps = [ + "@com_github_jetbrains_kotlin//:kotlin-compiler", + "@com_github_jetbrains_kotlin//:kotlin-annotation-processing", + "@com_github_jetbrains_kotlin//:kotlin-script-runtime", + ], +) diff --git a/src/test/kotlin/io/bazel/kotlin/builder/BUILD b/src/test/kotlin/io/bazel/kotlin/builder/BUILD index 25c745f22..9c366abfb 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/BUILD +++ b/src/test/kotlin/io/bazel/kotlin/builder/BUILD @@ -11,13 +11,15 @@ # 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. -package(default_visibility = ["//visibility:private"]) +package(default_visibility = ["//src:__subpackages__"]) load("@rules_java//java:defs.bzl", "java_library") load("//src/test/kotlin/io/bazel/kotlin:defs.bzl", "kt_rules_test") _COMMON_DEPS = [ "//src/main/kotlin/io/bazel/kotlin/builder", + "//src/main/kotlin/io/bazel/kotlin/builder/toolchain", + "//src/main/kotlin/io/bazel/kotlin/builder/utils:utils", "//src/main/protobuf:kotlin_model_java_proto", "//src/main/protobuf:deps_java_proto", "@kotlin_rules_maven//:com_google_truth_truth", @@ -37,7 +39,7 @@ java_library( "KotlinJvmTestBuilder.java", ], data = [ - "//src/main/kotlin:compiler_lib", + "//src/main/kotlin/io/bazel/kotlin/compiler", "@com_github_jetbrains_kotlin//:home", ], exports = _COMMON_DEPS + [ @@ -52,60 +54,11 @@ java_library( ], ) -kt_rules_test( - name = "SourceJarCreatorTest", - srcs = ["utils/jars/SourceJarCreatorTest.java"], -) - -kt_rules_test( - name = "JdepsParserTest", - srcs = ["tasks/jvm/JdepsParserTest.java"], -) - -kt_rules_test( - name = "KotlinBuilderJvmBasicTest", - srcs = ["tasks/jvm/KotlinBuilderJvmBasicTest.java"], -) - -kt_rules_test( - name = "KotlinJvmTaskExecutorTest", - srcs = ["tasks/jvm/KotlinJvmTaskExecutorTest.kt"], - deps = ["@com_github_jetbrains_kotlin//:kotlin-test"], -) - -# TODO(bazelbuild/rules_kotlin/issues/275): Remove full jar reference when the kt_rules_test handles jvm_import data better. -_MAVEN_CENTRAL_PREFIX = "@kotlin_rules_maven//:v1/https/maven-central.storage.googleapis.com/repos/central/data" -_AUTO_VALUE_PREFIX = "%s/com/google/auto/value" % _MAVEN_CENTRAL_PREFIX -_AUTO_VALUE_JAR = _AUTO_VALUE_PREFIX+ "/auto-value/1.6.5/auto-value-1.6.5.jar" -_AUTO_VALUE_ANNOTATIONS_JAR = _AUTO_VALUE_PREFIX+ "/auto-value-annotations/1.6.5/auto-value-annotations-1.6.5.jar" - -kt_rules_test( - name = "KotlinBuilderJvmKaptTest", - srcs = ["tasks/jvm/KotlinBuilderJvmKaptTest.java"], - data = [ - _AUTO_VALUE_JAR, - _AUTO_VALUE_ANNOTATIONS_JAR, - ], - jvm_flags = [ - "-Dauto_value=$(location %s)" % _AUTO_VALUE_JAR, - "-Dauto_value_annotations=$(location %s)" % _AUTO_VALUE_ANNOTATIONS_JAR, - ], -) - -kt_rules_test( - name = "KotlinBuilderJsTest", - srcs = ["tasks/js/KotlinBuilderJsTest.java"], -) - test_suite( name = "builder_tests", tests = [ - ":JdepsParserTest", - ":KotlinBuilderJsTest", - ":KotlinBuilderJvmBasicTest", - ":KotlinBuilderJvmKaptTest", - ":KotlinJvmTaskExecutorTest", - ":SourceJarCreatorTest", + "//src/test/kotlin/io/bazel/kotlin/builder/utils", + "//src/test/kotlin/io/bazel/kotlin/builder/tasks", ], visibility = ["//visibility:public"], ) diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java index 3cab60cec..ab0e5e03e 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java @@ -16,7 +16,7 @@ package io.bazel.kotlin.builder; import io.bazel.kotlin.builder.toolchain.CompilationStatusException; -import io.bazel.kotlin.builder.utils.CompilationTaskContext; +import io.bazel.kotlin.builder.toolchain.CompilationTaskContext; import io.bazel.kotlin.model.*; import java.io.*; diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel b/src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel new file mode 100644 index 000000000..7da6e958b --- /dev/null +++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel @@ -0,0 +1,56 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed 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. + +load("//src/test/kotlin/io/bazel/kotlin:defs.bzl", "kt_rules_test") + +kt_rules_test( + name = "JdepsParserTest", + srcs = ["jvm/JdepsParserTest.java"], + deps = [ + "//src/main/kotlin/io/bazel/kotlin/builder/tasks", + ] +) + +kt_rules_test( + name = "KotlinBuilderJvmBasicTest", + srcs = ["jvm/KotlinBuilderJvmBasicTest.java"], +) + +# TODO(bazelbuild/rules_kotlin/issues/275): Remove full jar reference when the kt_rules_test handles jvm_import data better. +_MAVEN_CENTRAL_PREFIX = "@kotlin_rules_maven//:v1/https/maven-central.storage.googleapis.com/repos/central/data" +_AUTO_VALUE_PREFIX = "%s/com/google/auto/value" % _MAVEN_CENTRAL_PREFIX +_AUTO_VALUE_JAR = _AUTO_VALUE_PREFIX+ "/auto-value/1.6.5/auto-value-1.6.5.jar" +_AUTO_VALUE_ANNOTATIONS_JAR = _AUTO_VALUE_PREFIX+ "/auto-value-annotations/1.6.5/auto-value-annotations-1.6.5.jar" + +kt_rules_test( + name = "KotlinBuilderJvmKaptTest", + srcs = ["jvm/KotlinBuilderJvmKaptTest.java"], + data = [ + _AUTO_VALUE_JAR, + _AUTO_VALUE_ANNOTATIONS_JAR, + ], + jvm_flags = [ + "-Dauto_value=$(location %s)" % _AUTO_VALUE_JAR, + "-Dauto_value_annotations=$(location %s)" % _AUTO_VALUE_ANNOTATIONS_JAR, + ], +) + +kt_rules_test( + name = "KotlinBuilderJsTest", + srcs = ["js/KotlinBuilderJsTest.java"], +) + +test_suite( + name = "tasks", +) \ No newline at end of file diff --git a/src/test/kotlin/io/bazel/kotlin/builder/utils/BUILD.bazel b/src/test/kotlin/io/bazel/kotlin/builder/utils/BUILD.bazel new file mode 100644 index 000000000..7390cabed --- /dev/null +++ b/src/test/kotlin/io/bazel/kotlin/builder/utils/BUILD.bazel @@ -0,0 +1,25 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed 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. +package(default_visibility = ["//src:__subpackages__"]) + +load("//src/test/kotlin/io/bazel/kotlin:defs.bzl", "kt_rules_test") + +kt_rules_test( + name = "SourceJarCreatorTest", + srcs = ["jars/SourceJarCreatorTest.java"], +) + +test_suite( + name = "utils", +) From f5b824e588b6950484a308aa8f5a19275ed30344 Mon Sep 17 00:00:00 2001 From: Corbin McNeely-Smith <58151731+restingbull@users.noreply.github.com> Date: Thu, 27 Feb 2020 12:44:27 -0500 Subject: [PATCH 08/16] Remove tree artifacts (#287) remove the generation of unused tree artifacts from the compile step. Tree artifacts, (created by declare_directory) are only useful when an action produces an unknown number of outputs. It this case, this would only result in extra overhead of bundling the produced directories in archives with ever using them. Co-authored-by: Christian Edward Gruber --- kotlin/internal/jvm/compile.bzl | 24 ++++---- .../repositories/nomaven_repositories.bzl | 57 +++++++++++++++++++ 2 files changed, 67 insertions(+), 14 deletions(-) create mode 100644 kotlin/internal/repositories/nomaven_repositories.bzl diff --git a/kotlin/internal/jvm/compile.bzl b/kotlin/internal/jvm/compile.bzl index 671109533..0c63b89db 100644 --- a/kotlin/internal/jvm/compile.bzl +++ b/kotlin/internal/jvm/compile.bzl @@ -114,8 +114,8 @@ def _build_resourcejar_action(ctx): return resources_jar_output # MAIN ACTIONS ######################################################################################################### -def _declare_output_directory(ctx, aspect, dir_name): - return ctx.actions.declare_directory("_kotlinc/%s_%s/%s_%s" % (ctx.label.name, aspect, ctx.label.name, dir_name)) +def _output_dir_path(ctx, aspect, dir_name): + return "_kotlinc/%s_%s/%s_%s" % (ctx.label.name, aspect, ctx.label.name, dir_name) def _partition_srcs(srcs): """Partition sources for the jvm aspect.""" @@ -173,17 +173,17 @@ def kt_jvm_compile_action(ctx, rule_kind, output_jar): else: fail("only one friend is possible") - classes_directory = _declare_output_directory(ctx, "jvm", "classes") - generated_classes_directory = _declare_output_directory(ctx, "jvm", "generated_classes") - sourcegen_directory = _declare_output_directory(ctx, "jvm", "sourcegenfiles") - temp_directory = _declare_output_directory(ctx, "jvm", "temp") + classes_directory = _output_dir_path(ctx, "jvm", "classes") + generated_classes_directory = _output_dir_path(ctx, "jvm", "generated_classes") + sourcegen_directory = _output_dir_path(ctx, "jvm", "sourcegenfiles") + temp_directory = _output_dir_path(ctx, "jvm", "temp") args = _utils.init_args(ctx, rule_kind, module_name) - args.add("--classdir", classes_directory.path) - args.add("--sourcegendir", sourcegen_directory.path) - args.add("--tempdir", temp_directory.path) - args.add("--kotlin_generated_classdir", generated_classes_directory.path) + args.add("--classdir", classes_directory) + args.add("--sourcegendir", sourcegen_directory) + args.add("--tempdir", temp_directory) + args.add("--kotlin_generated_classdir", generated_classes_directory) args.add("--output", output_jar) args.add("--kotlin_output_jdeps", ctx.outputs.jdeps) @@ -222,10 +222,6 @@ def kt_jvm_compile_action(ctx, rule_kind, output_jar): output_jar, ctx.outputs.jdeps, ctx.outputs.srcjar, - sourcegen_directory, - classes_directory, - temp_directory, - generated_classes_directory, ], executable = toolchain.kotlinbuilder.files_to_run.executable, execution_requirements = {"supports-workers": "1"}, diff --git a/kotlin/internal/repositories/nomaven_repositories.bzl b/kotlin/internal/repositories/nomaven_repositories.bzl new file mode 100644 index 000000000..0232c85dc --- /dev/null +++ b/kotlin/internal/repositories/nomaven_repositories.bzl @@ -0,0 +1,57 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed 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. +"""This file contains the Kotlin compiler repository definitions. It should not be loaded directly by client workspaces. +""" + +load( + "//kotlin/internal:defs.bzl", + _KT_COMPILER_REPO = "KT_COMPILER_REPO", +) +load( + "@bazel_tools//tools/build_defs/repo:http.bzl", + _http_archive = "http_archive", + _http_file = "http_file", +) + +BAZEL_JAVA_LAUNCHER_VERSION = "0.28.1" + +KOTLIN_CURRENT_COMPILER_RELEASE = { + "urls": [ + "https://github.com/JetBrains/kotlin/releases/download/v1.3.50/kotlin-compiler-1.3.50.zip", + ], + "sha256": "69424091a6b7f52d93eed8bba2ace921b02b113dbb71388d704f8180a6bdc6ec", +} + +def kotlin_repositories(compiler_release = KOTLIN_CURRENT_COMPILER_RELEASE): + """Call this in the WORKSPACE file to setup the Kotlin rules. + + Args: + compiler_release: (internal) dict containing "urls" and "sha256" for the Kotlin compiler. + """ + _http_archive( + name = _KT_COMPILER_REPO, + urls = compiler_release["urls"], + sha256 = compiler_release["sha256"], + build_file = "@io_bazel_rules_kotlin//kotlin/internal/repositories:BUILD.com_github_jetbrains_kotlin", + strip_prefix = "kotlinc", + ) + + _http_file( + name = "kt_java_stub_template", + urls = [("https://raw.githubusercontent.com/bazelbuild/bazel/" + + BAZEL_JAVA_LAUNCHER_VERSION + + "/src/main/java/com/google/devtools/build/lib/bazel/rules/java/" + + "java_stub_template.txt")], + sha256 = "e6531a6539ec1e38fec5e20523ff4bfc883e1cc0209eb658fe82eb918eb49657", + ) From 2896b0ab7052bc4bbec5cd8fef2f42ac286f1aa9 Mon Sep 17 00:00:00 2001 From: Yannic Date: Thu, 27 Feb 2020 19:09:30 +0100 Subject: [PATCH 09/16] Update Protobuf to 3.11.3 (#286) * Update Protobuf to 3.11.3 This should make rules_kotlin compatible with --incompatible_load_proto_rules_from_bzl. https://buildkite.com/bazel/bazelisk-plus-incompatible-flags/builds/417#b46d72d2-c746-41b7-9251-b1227f9283c0/516 * That's what you get for editing files using GitHub's UI :/ --- kotlin/internal/repositories/download.bzl | 26 ++++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/kotlin/internal/repositories/download.bzl b/kotlin/internal/repositories/download.bzl index 99d90f2b5..5769ffe8a 100644 --- a/kotlin/internal/repositories/download.bzl +++ b/kotlin/internal/repositories/download.bzl @@ -23,8 +23,8 @@ BAZEL_TOOLCHAINS_SHA = "5962fe677a43226c409316fcb321d668fc4b7fa97cb1f9ef45e7dc26 SKYLIB_VERSION = "0.8.0" SKYLIB_SHA = "2ea8a5ed2b448baf4a6855d3ce049c4c452a6470b1efd1504fdb7c1c134d220a" -PROTOBUF_GIT_COMMIT = "09745575a923640154bcf307fba8aedff47f240a" # v3.8.0, as of 2019-05-28 -PROTOBUF_SHA = "76ee4ba47dec6146872b6cd051ae5bd12897ef0b1523d5aeb56d81a5a4ca885a" +PROTOBUF_VERSION = "3.11.3" +PROTOBUF_SHA = "cf754718b0aa945b00550ed7962ddc167167bd922b842199eeb6505e6f344852" BAZEL_DEPS_VERSION = "0.1.0" BAZEL_DEPS_SHA = "05498224710808be9687f5b9a906d11dd29ad592020246d4cd1a26eeaed0735e" @@ -32,6 +32,9 @@ BAZEL_DEPS_SHA = "05498224710808be9687f5b9a906d11dd29ad592020246d4cd1a26eeaed073 RULES_JVM_EXTERNAL_TAG = "2.7" RULES_JVM_EXTERNAL_SHA = "f04b1466a00a2845106801e0c5cec96841f49ea4e7d1df88dc8e4bf31523df74" +RULES_PROTO_GIT_COMMIT = "f6b8d89b90a7956f6782a4a3609b2f0eee3ce965" +RULES_PROTO_SHA = "4d421d51f9ecfe9bf96ab23b55c6f2b809cbaf0eea24952683e397decfbd0dd0" + def kt_download_local_dev_dependencies(): """ Downloads all necessary http_* artifacts for rules_kotlin dev configuration. @@ -39,21 +42,24 @@ def kt_download_local_dev_dependencies(): Must be called before setup_dependencies in the WORKSPACE. """ maybe( - http_archive, + http_archive, name = "com_google_protobuf", - sha256 = "b404fe166de66e9a5e6dab43dc637070f950cdba2a8a4c9ed9add354ed4f6525", - strip_prefix = "protobuf-b4f193788c9f0f05d7e0879ea96cd738630e5d51", - url = "https://github.com/protocolbuffers/protobuf/archive/b4f193788c9f0f05d7e0879ea96cd738630e5d51.zip", + sha256 = PROTOBUF_SHA, + strip_prefix = "protobuf-%s" % PROTOBUF_VERSION, + urls = [ + "https://mirror.bazel.build/github.com/protocolbuffers/protobuf/archive/v%s.tar.gz" % PROTOBUF_VERSION, + "https://github.com/protocolbuffers/protobuf/archive/v%s.tar.gz" % PROTOBUF_VERSION, + ], ) maybe( http_archive, name = "rules_proto", - sha256 = "602e7161d9195e50246177e7c55b2f39950a9cf7366f74ed5f22fd45750cd208", - strip_prefix = "rules_proto-97d8af4dc474595af3900dd85cb3a29ad28cc313", + sha256 = RULES_PROTO_SHA, + strip_prefix = "rules_proto-%s" % RULES_PROTO_GIT_COMMIT, urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/97d8af4dc474595af3900dd85cb3a29ad28cc313.tar.gz", - "https://github.com/bazelbuild/rules_proto/archive/97d8af4dc474595af3900dd85cb3a29ad28cc313.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/%s.tar.gz" % RULES_PROTO_GIT_COMMIT, + "https://github.com/bazelbuild/rules_proto/archive/%s.tar.gz" % RULES_PROTO_GIT_COMMIT, ], ) From f291380f2d79a82fc69ec938c9cbb444fe01ce9a Mon Sep 17 00:00:00 2001 From: Christian Edward Gruber Date: Fri, 28 Feb 2020 16:26:32 -0500 Subject: [PATCH 10/16] Add Corbin to the codeowners. (#293) --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 0556305cb..206bfe73e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1 @@ -* @ahumesky @cgruber @djwhang @jin @timpeut +* @ahumesky @cgruber @djwhang @jin @timpeut @restingbull From 2cb1be9f43e1232fa5a1603b1e7a25e87e0bacd1 Mon Sep 17 00:00:00 2001 From: Corbin McNeely-Smith <58151731+restingbull@users.noreply.github.com> Date: Fri, 28 Feb 2020 16:30:32 -0500 Subject: [PATCH 11/16] Change plugins to use depsets, as opposed to lists. (#292) Fixes #289 --- kotlin/internal/jvm/compile.bzl | 23 ++++++++++++--------- kotlin/internal/jvm/plugins.bzl | 36 +++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/kotlin/internal/jvm/compile.bzl b/kotlin/internal/jvm/compile.bzl index 0c63b89db..b1344bd6b 100644 --- a/kotlin/internal/jvm/compile.bzl +++ b/kotlin/internal/jvm/compile.bzl @@ -19,6 +19,7 @@ load( load( "//kotlin/internal/jvm:plugins.bzl", _merge_plugin_infos = "merge_plugin_infos", + _plugin_mappers = "mappers", ) load( "//kotlin/internal/utils:utils.bzl", @@ -196,15 +197,19 @@ def kt_jvm_compile_action(ctx, rule_kind, output_jar): args.add_all("--source_jars", srcs.src_jars, omit_if_empty = True) # Collect and prepare plugin descriptor for the worker. - plugin_info = _merge_plugin_infos(ctx.attr.plugins + ctx.attr.deps) - if len(plugin_info.annotation_processors) > 0: - processors = [] - processorpath = [] - for p in plugin_info.annotation_processors: - processors += [p.processor_class] - processorpath += p.classpath - args.add_all("--processors", processors) - args.add_all("--processorpath", processorpath) + plugins = _plugin_mappers.targets_to_kt_plugins(ctx.attr.plugins + ctx.attr.deps) + args.add_all( + "--processors", + plugins, + map_each = _plugin_mappers.kt_plugin_to_processor, + omit_if_empty = True, + ) + args.add_all( + "--processorpath", + plugins, + map_each = _plugin_mappers.kt_plugin_to_processorpath, + omit_if_empty = True, + ) progress_message = "Compiling Kotlin to JVM %s { kt: %d, java: %d, srcjars: %d }" % ( ctx.label, diff --git a/kotlin/internal/jvm/plugins.bzl b/kotlin/internal/jvm/plugins.bzl index 986aaf837..beaa4fe67 100644 --- a/kotlin/internal/jvm/plugins.bzl +++ b/kotlin/internal/jvm/plugins.bzl @@ -19,25 +19,35 @@ load( KtJvmPluginInfo = provider( doc = "This provider contains the plugin info for the JVM aspect", fields = { - "annotation_processors": "a serializeable list of structs containing annotation processor definitions", + "annotation_processors": "depset of structs containing annotation processor definitions", }, ) -_EMPTY_PLUGIN_INFO = [KtJvmPluginInfo(annotation_processors = [])] +_EMPTY_PLUGIN_INFO = [KtJvmPluginInfo(annotation_processors = depset())] + +# Mapping functions for args.add_all. +# These preserve the transitive depsets until needed. +def _kt_plugin_to_processor(processor): + return processor.processor_class + +def _kt_plugin_to_processorpath(processor): + return [j.path for j in processor.classpath.to_list()] + +def _targets_to_kt_plugins(targets): + return depset(transitive = [t[KtJvmPluginInfo].annotation_processors for t in targets if t[KtJvmPluginInfo]]) + +mappers = struct( + targets_to_kt_plugins = _targets_to_kt_plugins, + kt_plugin_to_processor = _kt_plugin_to_processor, + kt_plugin_to_processorpath = _kt_plugin_to_processorpath, +) def merge_plugin_infos(attrs): """Merge all of the plugin infos found in the provided sequence of attributes. Returns: A KtJvmPluginInfo provider, Each of the entries is serializable.""" - tally = {} - annotation_processors = [] - for info in [a[KtJvmPluginInfo] for a in attrs]: - for p in info.annotation_processors: - if p.label not in tally: - tally[p.label] = True - annotation_processors.append(p) return KtJvmPluginInfo( - annotation_processors = annotation_processors, + annotation_processors = _targets_to_kt_plugins(attrs), ) def _kt_jvm_plugin_aspect_impl(target, ctx): @@ -45,14 +55,14 @@ def _kt_jvm_plugin_aspect_impl(target, ctx): processor = ctx.rule.attr merged_deps = java_common.merge([j[JavaInfo] for j in processor.deps]) return [KtJvmPluginInfo( - annotation_processors = [ + annotation_processors = depset([ struct( label = _utils.restore_label(ctx.label), processor_class = processor.processor_class, - classpath = [cp.path for cp in merged_deps.transitive_runtime_jars.to_list()], + classpath = merged_deps.transitive_runtime_jars, generates_api = processor.generates_api, ), - ], + ]), )] elif ctx.rule.kind == "java_library": return [merge_plugin_infos(ctx.rule.attr.exported_plugins)] From 226b56a1817258b98569d2cef4623fbba1abbf8b Mon Sep 17 00:00:00 2001 From: Corbin McNeely-Smith <58151731+restingbull@users.noreply.github.com> Date: Mon, 2 Mar 2020 15:47:42 -0500 Subject: [PATCH 12/16] Optional outputs (#291) * Convert all Dep dependencies to be addressable by label at test time. * Add files explicitly to runfiles from the data attribute. This is more explicit and resilient that using collect_default. * New output scheme for the JvmCompilationTask, if an output isn't requested do not create it. * Break apart compileAll to allow stage independent compilations. Make jdeps optional, as it is not currently consumed so we shouldn't do the work. Update test framework to handle the output scheme. If kotlin srcs are absent, skip kotlin compilation. * Introduce CompilationArgs to improve compilation argument readability Issue: bazelbuild/rules_kotlin/issues/232 --- kotlin/internal/jvm/compile.bzl | 227 +++++++----- kotlin/internal/jvm/impl.bzl | 4 + .../kotlin/builder/tasks/KotlinBuilder.kt | 348 +++++++++--------- .../builder/tasks/jvm/CompilationArgs.kt | 68 ++++ .../tasks/jvm/KotlinJvmTaskExecutor.kt | 32 +- .../builder/tasks/jvm/compilation_task.kt | 148 +++----- .../io/bazel/kotlin/builder/utils/ArgMap.kt | 134 ++++--- .../kotlin/io/bazel/kotlin/builder/Deps.java | 42 ++- .../builder/KotlinAbstractTestBuilder.java | 20 +- .../kotlin/builder/KotlinJvmTestBuilder.java | 106 +++--- .../tasks/jvm/KotlinBuilderJvmBasicTest.java | 74 ++-- .../tasks/jvm/KotlinBuilderJvmKaptTest.java | 86 ++--- src/test/kotlin/io/bazel/kotlin/defs.bzl | 26 +- 13 files changed, 790 insertions(+), 525 deletions(-) create mode 100644 src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationArgs.kt diff --git a/kotlin/internal/jvm/compile.bzl b/kotlin/internal/jvm/compile.bzl index b1344bd6b..ded6c9317 100644 --- a/kotlin/internal/jvm/compile.bzl +++ b/kotlin/internal/jvm/compile.bzl @@ -28,7 +28,7 @@ load( # INTERNAL ACTIONS ##################################################################################################### def _fold_jars_action(ctx, rule_kind, output_jar, input_jars): - """Set up an action to Fold the input jars into a normalized ouput jar.""" + """Set up an action to Fold the input jars into a normalized output jar.""" args = ctx.actions.args() args.add_all([ "--normalize", @@ -114,12 +114,8 @@ def _build_resourcejar_action(ctx): ) return resources_jar_output -# MAIN ACTIONS ######################################################################################################### -def _output_dir_path(ctx, aspect, dir_name): - return "_kotlinc/%s_%s/%s_%s" % (ctx.label.name, aspect, ctx.label.name, dir_name) - -def _partition_srcs(srcs): - """Partition sources for the jvm aspect.""" +def _partitioned_srcs(srcs): + """Creates a struct of srcs sorted by extension. Fails if there are no sources.""" kt_srcs = [] java_srcs = [] src_jars = [] @@ -132,72 +128,156 @@ def _partition_srcs(srcs): elif f.path.endswith(".srcjar"): src_jars.append(f) + if not kt_srcs and not java_srcs and not src_jars: + fail("no sources provided") + return struct( - kt = depset(kt_srcs), - java = depset(java_srcs), - all_srcs = depset(kt_srcs + java_srcs), - src_jars = depset(src_jars), + kt = kt_srcs, + java = java_srcs, + all_srcs = kt_srcs + java_srcs, + src_jars = src_jars, ) -def kt_jvm_compile_action(ctx, rule_kind, output_jar): - """This macro sets up a compile action for a Kotlin jar. +def _output_dir_path(ctx, aspect, dir_name): + return "_kotlinc/%s_%s/%s_%s" % (ctx.label.name, aspect, ctx.label.name, dir_name) - Args: - rule_kind: The rule kind --e.g., `kt_jvm_library`. - output_jar: The jar file that this macro will use as the output. - Returns: - A struct containing the providers JavaInfo (`java`) and `kt` (KtJvmInfo). This struct is not intended to be - used as a legacy provider -- rather the caller should transform the result. - """ - toolchain = ctx.toolchains[_TOOLCHAIN_TYPE] +def _compiler_directories(ctx): + """Creates a dict of the necessary compiler directories for generating compile actions""" + return dict( + classdir = _output_dir_path(ctx, "jvm", "classes"), + kotlin_generated_classdir = _output_dir_path(ctx, "jvm", "generated_classes"), + sourcegendir = _output_dir_path(ctx, "jvm", "sourcegenfiles"), + tempdir = _output_dir_path(ctx, "jvm", "temp"), + ) - srcs = _partition_srcs(ctx.files.srcs) - if not srcs.kt and not srcs.java and not srcs.src_jars: - fail("no sources provided") +def _compiler_toolchains(ctx): + """Creates a struct of the relevant compilation toolchains""" + return struct( + kt = ctx.toolchains[_TOOLCHAIN_TYPE], + ) - # TODO extract and move this into common. Need to make it generic first. - friends = getattr(ctx.attr, "friends", []) - deps = [d[JavaInfo] for d in friends + ctx.attr.deps] + [toolchain.jvm_stdlibs] - compile_jars = java_common.merge(deps).transitive_compile_time_jars +def _compiler_friends(ctx, friends): + """Creates a struct of friends meta data""" + # TODO extract and move this into common. Need to make it generic first. if len(friends) == 0: - module_name = _utils.derive_module_name(ctx) - friend_paths = depset() + return struct( + targets = [], + module_name = _utils.derive_module_name(ctx), + paths = [], + ) elif len(friends) == 1: if friends[0][_KtJvmInfo] == None: fail("only kotlin dependencies can be friends") elif ctx.attr.module_name: fail("if friends has been set then module_name cannot be provided") else: - friend_paths = depset([j.path for j in friends[0][JavaInfo].compile_jars.to_list()]) - module_name = friends[0][_KtJvmInfo].module_name + return struct( + targets = friends, + paths = friends[0][JavaInfo].compile_jars, + module_name = friends[0][_KtJvmInfo].module_name, + ) else: fail("only one friend is possible") - classes_directory = _output_dir_path(ctx, "jvm", "classes") - generated_classes_directory = _output_dir_path(ctx, "jvm", "generated_classes") - sourcegen_directory = _output_dir_path(ctx, "jvm", "sourcegenfiles") - temp_directory = _output_dir_path(ctx, "jvm", "temp") +def _compiler_deps(toolchains, friend, deps): + """Encapsulates compiler dependency metadata.""" + dep_infos = [d[JavaInfo] for d in friend.targets + deps] + [toolchains.kt.jvm_stdlibs] + return struct( + deps = dep_infos, + compile_jars = depset( + transitive = [ + d.compile_jars + for d in dep_infos + ] + [ + d.transitive_compile_time_jars + for d in dep_infos + ], + ), + ) - args = _utils.init_args(ctx, rule_kind, module_name) +def _java_info_to_compile_jars(target): + i = target[JavaInfo] + if i == None: + return None + return i.compile_jars - args.add("--classdir", classes_directory) - args.add("--sourcegendir", sourcegen_directory) - args.add("--tempdir", temp_directory) - args.add("--kotlin_generated_classdir", generated_classes_directory) +# MAIN ACTIONS ######################################################################################################### - args.add("--output", output_jar) - args.add("--kotlin_output_jdeps", ctx.outputs.jdeps) - args.add("--kotlin_output_srcjar", ctx.outputs.srcjar) +def kt_jvm_compile_action(ctx, rule_kind, output_jar): + """This macro sets up a compile action for a Kotlin jar. + + Args: + rule_kind: The rule kind --e.g., `kt_jvm_library`. + output_jar: The jar file that this macro will use as the output. + Returns: + A struct containing the providers JavaInfo (`java`) and `kt` (KtJvmInfo). This struct is not intended to be + used as a legacy provider -- rather the caller should transform the result. + """ + toolchains = _compiler_toolchains(ctx) + dirs = _compiler_directories(ctx) + srcs = _partitioned_srcs(ctx.files.srcs) + friend = _compiler_friends(ctx, friends = getattr(ctx.attr, "friends", [])) + compile_deps = _compiler_deps(toolchains, friend, deps = ctx.attr.deps) + plugins = _plugin_mappers.targets_to_kt_plugins(ctx.attr.plugins + ctx.attr.deps) + _run_kt_builder_action( + ctx = ctx, + rule_kind = rule_kind, + toolchains = toolchains, + dirs = dirs, + srcs = srcs, + friend = friend, + compile_deps = compile_deps, + plugins = plugins, + outputs = { + "output": output_jar, + "kotlin_output_jdeps": ctx.outputs.jdeps, + "kotlin_output_srcjar": ctx.outputs.srcjar, + } + ) + + return struct( + java = JavaInfo( + output_jar = ctx.outputs.jar, + compile_jar = ctx.outputs.jar, + source_jar = ctx.outputs.srcjar, + # jdeps = ctx.outputs.jdeps, + deps = compile_deps.deps, + runtime_deps = [d[JavaInfo] for d in ctx.attr.runtime_deps], + exports = [d[JavaInfo] for d in getattr(ctx.attr, "exports", [])], + neverlink = getattr(ctx.attr, "neverlink", False), + ), + kt = _KtJvmInfo( + srcs = ctx.files.srcs, + module_name = friend.module_name, + language_version = toolchains.kt.api_version, + # intellij aspect needs this. + outputs = struct( + jdeps = ctx.outputs.jdeps, + jars = [struct( + class_jar = ctx.outputs.jar, + ijar = None, + source_jars = [ctx.outputs.srcjar], + )], + ), + ), + ) - args.add("--kotlin_friend_paths", "\n".join(friend_paths.to_list())) - args.add_all("--classpath", compile_jars) +def _run_kt_builder_action(ctx, rule_kind, toolchains, dirs, srcs, friend, compile_deps, plugins, outputs): + """Creates a KotlinBuilder action invocation.""" + args = _utils.init_args(ctx, rule_kind, friend.module_name) + + for f, path in dirs.items() + outputs.items(): + args.add("--" + f, path) + + args.add_all("--classpath", compile_deps.compile_jars) args.add_all("--sources", srcs.all_srcs, omit_if_empty = True) args.add_all("--source_jars", srcs.src_jars, omit_if_empty = True) + args.add_joined("--kotlin_friend_paths", friend.paths, join_with = "\n") + # Collect and prepare plugin descriptor for the worker. - plugins = _plugin_mappers.targets_to_kt_plugins(ctx.attr.plugins + ctx.attr.deps) args.add_all( "--processors", plugins, @@ -213,57 +293,34 @@ def kt_jvm_compile_action(ctx, rule_kind, output_jar): progress_message = "Compiling Kotlin to JVM %s { kt: %d, java: %d, srcjars: %d }" % ( ctx.label, - len(srcs.kt.to_list()), - len(srcs.java.to_list()), - len(srcs.src_jars.to_list()), + len(srcs.kt), + len(srcs.java), + len(srcs.src_jars), + ) + + tools, input_manifests = ctx.resolve_tools( + tools = [ + toolchains.kt.kotlinbuilder, + toolchains.kt.kotlin_home, + ], ) - tools, _, input_manifests = ctx.resolve_command(tools = [toolchain.kotlinbuilder, toolchain.kotlin_home]) ctx.actions.run( mnemonic = "KotlinCompile", - inputs = depset(ctx.files.srcs, transitive = [compile_jars]), + inputs = depset(ctx.files.srcs, transitive = [compile_deps.compile_jars]), tools = tools, - outputs = [ - output_jar, - ctx.outputs.jdeps, - ctx.outputs.srcjar, - ], - executable = toolchain.kotlinbuilder.files_to_run.executable, + input_manifests = input_manifests, + outputs = [f for f in outputs.values()], + executable = toolchains.kt.kotlinbuilder.files_to_run.executable, execution_requirements = {"supports-workers": "1"}, arguments = [args], progress_message = progress_message, - input_manifests = input_manifests, env = { "LC_CTYPE": "en_US.UTF-8", # For Java source files }, ) - return struct( - java = JavaInfo( - output_jar = ctx.outputs.jar, - compile_jar = ctx.outputs.jar, - source_jar = ctx.outputs.srcjar, - # jdeps = ctx.outputs.jdeps, - deps = deps, - runtime_deps = [d[JavaInfo] for d in ctx.attr.runtime_deps], - exports = [d[JavaInfo] for d in getattr(ctx.attr, "exports", [])], - neverlink = getattr(ctx.attr, "neverlink", False), - ), - kt = _KtJvmInfo( - srcs = ctx.files.srcs, - module_name = module_name, - language_version = toolchain.api_version, - # intelij aspect needs this. - outputs = struct( - jdeps = ctx.outputs.jdeps, - jars = [struct( - class_jar = ctx.outputs.jar, - ijar = None, - source_jars = [ctx.outputs.srcjar], - )], - ), - ), - ) + def kt_jvm_produce_jar_actions(ctx, rule_kind): """Setup The actions to compile a jar and if any resources or resource_jars were provided to merge these in with the diff --git a/kotlin/internal/jvm/impl.bzl b/kotlin/internal/jvm/impl.bzl index 6b84e2a69..c188812c4 100644 --- a/kotlin/internal/jvm/impl.bzl +++ b/kotlin/internal/jvm/impl.bzl @@ -33,7 +33,11 @@ def _make_providers(ctx, providers, transitive_files = depset(order = "default") DefaultInfo( files = depset([ctx.outputs.jar]), runfiles = ctx.runfiles( + # explicitly include data files, otherwise they appear to be missing + files = ctx.files.data, transitive_files = transitive_files, + # continue to use collect_default until proper transitive data collecting is + # implmented. collect_default = True, ), ), diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt index 3cc5c1637..6263ab0dd 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt @@ -19,8 +19,15 @@ import io.bazel.kotlin.builder.tasks.js.Kotlin2JsTaskExecutor import io.bazel.kotlin.builder.tasks.jvm.KotlinJvmTaskExecutor import io.bazel.kotlin.builder.toolchain.CompilationStatusException import io.bazel.kotlin.builder.toolchain.CompilationTaskContext -import io.bazel.kotlin.builder.utils.* -import io.bazel.kotlin.model.* +import io.bazel.kotlin.builder.utils.ArgMap +import io.bazel.kotlin.builder.utils.ArgMaps +import io.bazel.kotlin.builder.utils.Flag +import io.bazel.kotlin.builder.utils.partitionJvmSources +import io.bazel.kotlin.model.CompilationTaskInfo +import io.bazel.kotlin.model.JsCompilationTask +import io.bazel.kotlin.model.JvmCompilationTask +import io.bazel.kotlin.model.Platform +import io.bazel.kotlin.model.RuleKind import java.io.PrintStream import java.nio.charset.StandardCharsets import java.nio.file.Files @@ -33,88 +40,90 @@ import javax.inject.Singleton @Singleton @Suppress("MemberVisibilityCanBePrivate") class KotlinBuilder @Inject internal constructor( - private val outputProvider: Provider, - private val jvmTaskExecutor: KotlinJvmTaskExecutor, - private val jsTaskExecutor: Kotlin2JsTaskExecutor + private val outputProvider: Provider, + private val jvmTaskExecutor: KotlinJvmTaskExecutor, + private val jsTaskExecutor: Kotlin2JsTaskExecutor ) : CommandLineProgram { - companion object { - @JvmStatic - private val FLAGFILE_RE = Pattern.compile("""^--flagfile=((.*)-(\d+).params)$""").toRegex() - } - - override fun apply(args: List): Int { - val (argMap, context) = buildContext(args) - var success = false - var status = 0 - try { - @Suppress("WHEN_ENUM_CAN_BE_NULL_IN_JAVA") - when (context.info.platform) { - Platform.JVM -> executeJvmTask(context, argMap) - Platform.JS -> executeJsTask(context, argMap) - Platform.UNRECOGNIZED -> throw IllegalStateException("unrecognized platform: ${context.info}") - } - success = true - } catch (ex: CompilationStatusException) { - System.err.println("Compilation failure: ${ex.message}") - status = ex.status - } catch (throwable: Throwable) { - context.reportUnhandledException(throwable) - throw throwable - } finally { - context.finalize(success) - } - return status - } - - private fun buildContext(args: List): Pair { - check(args.isNotEmpty()) { "expected at least a single arg got: ${args.joinToString(" ")}" } - val (flagFileName, primaryOutputPath, _) = - checkNotNull(FLAGFILE_RE.matchEntire(args[0])) { "invalid flagfile ${args[0]}" }.destructured - val argMap = Files.readAllLines(Paths.get(flagFileName), StandardCharsets.UTF_8).let(ArgMaps::from) - val info = buildTaskInfo(argMap).also { - it.primaryOutputPath = primaryOutputPath - }.build() - val context = CompilationTaskContext(info, outputProvider.get()) - return Pair(argMap, context) - } - - /** - * Declares the flags used by the java builder. - */ - private enum class JavaBuilderFlags(override val flag: String) : Flag { - TARGET_LABEL("--target_label"), - CLASSPATH("--classpath"), - JAVAC_OPTS("--javacopts"), - DEPENDENCIES("--dependencies"), - DIRECT_DEPENDENCIES("--direct_dependencies"), - DIRECT_DEPENDENCY("--direct_dependency"), - INDIRECT_DEPENDENCY("--indirect_dependency"), - STRICT_JAVA_DEPS("--strict_java_deps"), - OUTPUT_DEPS_PROTO("--output_deps_proto"), - DEPS_ARTIFACTS("--deps_artifacts"), - REDUCE_CLASSPATH("--reduce_classpath"), - SOURCEGEN_DIR("--sourcegendir"), - GENERATED_SOURCES_OUTPUT("--generated_sources_output"), - OUTPUT_MANIFEST_PROTO("--output_manifest_proto"), - SOURCES("--sources"), - SOURCE_ROOTS("--source_roots"), - SOURCE_JARS("--source_jars"), - SOURCE_PATH("--sourcepath"), - BOOT_CLASSPATH("--bootclasspath"), - PROCESSOR_PATH("--processorpath"), - PROCESSORS("--processors"), - EXT_CLASSPATH("--extclasspath"), - EXT_DIR("--extdir"), - OUTPUT("--output"), - NATIVE_HEADER_OUTPUT("--native_header_output"), - CLASSDIR("--classdir"), - TEMPDIR("--tempdir"), - GENDIR("--gendir"), - POST_PROCESSOR("--post_processor"), - COMPRESS_JAR("--compress_jar"), - RULE_KIND("--rule_kind"), - TEST_ONLY("--testonly"); + companion object { + @JvmStatic + private val FLAGFILE_RE = Pattern.compile("""^--flagfile=((.*)-(\d+).params)$""").toRegex() + } + + override fun apply(args: List): Int { + val (argMap, context) = buildContext(args) + var success = false + var status = 0 + try { + @Suppress("WHEN_ENUM_CAN_BE_NULL_IN_JAVA") + when (context.info.platform) { + Platform.JVM -> executeJvmTask(context, argMap) + Platform.JS -> executeJsTask(context, argMap) + Platform.UNRECOGNIZED -> throw IllegalStateException( + "unrecognized platform: ${context.info}") + } + success = true + } catch (ex: CompilationStatusException) { + System.err.println("Compilation failure: ${ex.message}") + status = ex.status + } catch (throwable: Throwable) { + context.reportUnhandledException(throwable) + } finally { + context.finalize(success) } + return status + } + + private fun buildContext(args: List): Pair { + check(args.isNotEmpty()) { "expected at least a single arg got: ${args.joinToString(" ")}" } + val (flagFileName, primaryOutputPath, _) = + checkNotNull( + FLAGFILE_RE.matchEntire(args[0])) { "invalid flagfile ${args[0]}" }.destructured + val argMap = + Files.readAllLines(Paths.get(flagFileName), StandardCharsets.UTF_8).let(ArgMaps::from) + val info = buildTaskInfo(argMap).also { + it.primaryOutputPath = primaryOutputPath + }.build() + val context = CompilationTaskContext(info, outputProvider.get()) + return Pair(argMap, context) + } + + /** + * Declares the flags used by the java builder. + */ + private enum class JavaBuilderFlags(override val flag: String) : Flag { + TARGET_LABEL("--target_label"), + CLASSPATH("--classpath"), + JAVAC_OPTS("--javacopts"), + DEPENDENCIES("--dependencies"), + DIRECT_DEPENDENCIES("--direct_dependencies"), + DIRECT_DEPENDENCY("--direct_dependency"), + INDIRECT_DEPENDENCY("--indirect_dependency"), + STRICT_JAVA_DEPS("--strict_java_deps"), + OUTPUT_DEPS_PROTO("--output_deps_proto"), + DEPS_ARTIFACTS("--deps_artifacts"), + REDUCE_CLASSPATH("--reduce_classpath"), + SOURCEGEN_DIR("--sourcegendir"), + GENERATED_SOURCES_OUTPUT("--generated_sources_output"), + OUTPUT_MANIFEST_PROTO("--output_manifest_proto"), + SOURCES("--sources"), + SOURCE_ROOTS("--source_roots"), + SOURCE_JARS("--source_jars"), + SOURCE_PATH("--sourcepath"), + BOOT_CLASSPATH("--bootclasspath"), + PROCESSOR_PATH("--processorpath"), + PROCESSORS("--processors"), + EXT_CLASSPATH("--extclasspath"), + EXT_DIR("--extdir"), + OUTPUT("--output"), + NATIVE_HEADER_OUTPUT("--native_header_output"), + CLASSDIR("--classdir"), + TEMPDIR("--tempdir"), + GENDIR("--gendir"), + POST_PROCESSOR("--post_processor"), + COMPRESS_JAR("--compress_jar"), + RULE_KIND("--rule_kind"), + TEST_ONLY("--testonly"); + } private enum class KotlinBuilderFlags(override val flag: String) : Flag { MODULE_NAME("--kotlin_module_name"), @@ -133,97 +142,104 @@ class KotlinBuilder @Inject internal constructor( TASK_ID("--kotlin_task_id"); } - private fun buildTaskInfo(argMap: ArgMap): CompilationTaskInfo.Builder = - with(CompilationTaskInfo.newBuilder()) { - addAllDebug(argMap.mandatory(KotlinBuilderFlags.DEBUG)) - - label = argMap.mandatorySingle(JavaBuilderFlags.TARGET_LABEL) - argMap.mandatorySingle(JavaBuilderFlags.RULE_KIND).split("_").also { - check(it.size == 3 && it[0] == "kt") { "invalid rule kind $it" } - platform = checkNotNull(Platform.valueOf(it[1].toUpperCase())) { - "unrecognized platform ${it[1]}" - } - ruleKind = checkNotNull(RuleKind.valueOf(it[2].toUpperCase())) { - "unrecognized rule kind ${it[2]}" - } - } - moduleName = argMap.mandatorySingle(KotlinBuilderFlags.MODULE_NAME).also { - check(it.isNotBlank()) { "--kotlin_module_name should not be blank" } - } - passthroughFlags = argMap.optionalSingle(KotlinBuilderFlags.PASSTHROUGH_FLAGS) - argMap.optional(KotlinBuilderFlags.FRIEND_PATHS)?.let(::addAllFriendPaths) - toolchainInfoBuilder.commonBuilder.apiVersion = argMap.mandatorySingle(KotlinBuilderFlags.API_VERSION) - toolchainInfoBuilder.commonBuilder.languageVersion = argMap.mandatorySingle(KotlinBuilderFlags.LANGUAGE_VERSION) - this + private fun buildTaskInfo(argMap: ArgMap): CompilationTaskInfo.Builder = + with(CompilationTaskInfo.newBuilder()) { + addAllDebug(argMap.mandatory(KotlinBuilderFlags.DEBUG)) + + label = argMap.mandatorySingle(JavaBuilderFlags.TARGET_LABEL) + argMap.mandatorySingle(JavaBuilderFlags.RULE_KIND).split("_").also { + check(it.size == 3 && it[0] == "kt") { "invalid rule kind $it" } + platform = checkNotNull(Platform.valueOf(it[1].toUpperCase())) { + "unrecognized platform ${it[1]}" + } + ruleKind = checkNotNull(RuleKind.valueOf(it[2].toUpperCase())) { + "unrecognized rule kind ${it[2]}" + } } + moduleName = argMap.mandatorySingle(KotlinBuilderFlags.MODULE_NAME).also { + check(it.isNotBlank()) { "--kotlin_module_name should not be blank" } + } + passthroughFlags = argMap.optionalSingle(KotlinBuilderFlags.PASSTHROUGH_FLAGS) + argMap.optional(KotlinBuilderFlags.FRIEND_PATHS)?.let(::addAllFriendPaths) + toolchainInfoBuilder.commonBuilder.apiVersion = + argMap.mandatorySingle(KotlinBuilderFlags.API_VERSION) + toolchainInfoBuilder.commonBuilder.languageVersion = + argMap.mandatorySingle(KotlinBuilderFlags.LANGUAGE_VERSION) + this + } + + private fun executeJsTask(context: CompilationTaskContext, argMap: ArgMap) = + buildJsTask(context.info, argMap).let { jsTask -> + context.whenTracing { printProto("js task input", jsTask) } + jsTaskExecutor.execute(context, jsTask) + } + + private fun buildJsTask(info: CompilationTaskInfo, argMap: ArgMap): JsCompilationTask = + with(JsCompilationTask.newBuilder()) { + this.info = info + with(inputsBuilder) { + addAllLibraries(argMap.mandatory(KotlinBuilderFlags.JS_LIBRARIES)) + addAllKotlinSources(argMap.mandatory(JavaBuilderFlags.SOURCES)) + } + with(outputsBuilder) { + js = argMap.mandatorySingle(JavaBuilderFlags.OUTPUT) + jar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_JS_JAR) + srcjar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_SRCJAR) + } + addAllPassThroughFlags(argMap.mandatory(KotlinBuilderFlags.JS_PASSTHROUGH_FLAGS)) + build() + } + + private fun executeJvmTask(context: CompilationTaskContext, argMap: ArgMap) { + val task = buildJvmTask(context.info, argMap) + context.whenTracing { + printProto("jvm task message", task) + } + jvmTaskExecutor.execute(context, task) + } - private fun executeJsTask(context: CompilationTaskContext, argMap: ArgMap) = - buildJsTask(context.info, argMap).let { jsTask -> - context.whenTracing { printProto("js task input", jsTask) } - jsTaskExecutor.execute(context, jsTask) + private fun buildJvmTask(info: CompilationTaskInfo, argMap: ArgMap): JvmCompilationTask = + JvmCompilationTask.newBuilder().let { root -> + root.info = info + + with(root.outputsBuilder) { + jar = argMap.mandatorySingle(JavaBuilderFlags.OUTPUT) + srcjar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_SRCJAR) + + argMap.optionalSingle(KotlinBuilderFlags.OUTPUT_JDEPS)?.apply { jdeps = this } } - private fun buildJsTask(info: CompilationTaskInfo, argMap: ArgMap): JsCompilationTask = - with(JsCompilationTask.newBuilder()) { - this.info = info - with(inputsBuilder) { - addAllLibraries(argMap.mandatory(KotlinBuilderFlags.JS_LIBRARIES)) - addAllKotlinSources(argMap.mandatory(JavaBuilderFlags.SOURCES)) - } - with(outputsBuilder) { - js = argMap.mandatorySingle(JavaBuilderFlags.OUTPUT) - jar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_JS_JAR) - srcjar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_SRCJAR) - } - addAllPassThroughFlags(argMap.mandatory(KotlinBuilderFlags.JS_PASSTHROUGH_FLAGS)) - build() + with(root.directoriesBuilder) + { + classes = argMap.mandatorySingle(JavaBuilderFlags.CLASSDIR) + generatedClasses = argMap.mandatorySingle(KotlinBuilderFlags.GENERATED_CLASSDIR) + temp = argMap.mandatorySingle(JavaBuilderFlags.TEMPDIR) + generatedSources = argMap.mandatorySingle(JavaBuilderFlags.SOURCEGEN_DIR) } - private fun executeJvmTask(context: CompilationTaskContext, argMap: ArgMap) { - val task = buildJvmTask(context.info, argMap) - context.whenTracing { - printProto("jvm task message", task) + with(root.inputsBuilder) + { + addAllClasspath(argMap.mandatory(JavaBuilderFlags.CLASSPATH)) + putAllIndirectDependencies(argMap.labelDepMap(JavaBuilderFlags.DIRECT_DEPENDENCY)) + putAllIndirectDependencies(argMap.labelDepMap(JavaBuilderFlags.INDIRECT_DEPENDENCY)) + + addAllProcessors(argMap.optional(JavaBuilderFlags.PROCESSORS) ?: emptyList()) + addAllProcessorpaths(argMap.optional(JavaBuilderFlags.PROCESSOR_PATH) ?: emptyList()) + + argMap.optional(JavaBuilderFlags.SOURCES)?.iterator()?.partitionJvmSources( + { addKotlinSources(it) }, + { addJavaSources(it) } + ) + argMap.optional(JavaBuilderFlags.SOURCE_JARS)?.also { + addAllSourceJars(it) + } } - jvmTaskExecutor.execute(context, task) - } - private fun buildJvmTask(info: CompilationTaskInfo, argMap: ArgMap): JvmCompilationTask = - JvmCompilationTask.newBuilder().let { root -> - root.info = info - - with(root.outputsBuilder) { - jar = argMap.mandatorySingle(JavaBuilderFlags.OUTPUT) - jdeps = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_JDEPS) - srcjar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_SRCJAR) - } - - with(root.directoriesBuilder) { - classes = argMap.mandatorySingle(JavaBuilderFlags.CLASSDIR) - generatedClasses = argMap.mandatorySingle(KotlinBuilderFlags.GENERATED_CLASSDIR) - temp = argMap.mandatorySingle(JavaBuilderFlags.TEMPDIR) - generatedSources = argMap.mandatorySingle(JavaBuilderFlags.SOURCEGEN_DIR) - } - - with(root.inputsBuilder) { - addAllClasspath(argMap.mandatory(JavaBuilderFlags.CLASSPATH)) - putAllIndirectDependencies(argMap.labelDepMap(JavaBuilderFlags.DIRECT_DEPENDENCY)) - putAllIndirectDependencies(argMap.labelDepMap(JavaBuilderFlags.INDIRECT_DEPENDENCY)) - - addAllProcessors(argMap.optional(JavaBuilderFlags.PROCESSORS) ?: emptyList()) - addAllProcessorpaths(argMap.optional(JavaBuilderFlags.PROCESSOR_PATH) ?: emptyList()) - - argMap.optional(JavaBuilderFlags.SOURCES)?.iterator()?.partitionJvmSources( - { addKotlinSources(it) }, - { addJavaSources(it) } - ) - argMap.optional(JavaBuilderFlags.SOURCE_JARS)?.also { - addAllSourceJars(it) - } - } - - with(root.infoBuilder) { - toolchainInfoBuilder.jvmBuilder.jvmTarget = argMap.mandatorySingle(KotlinBuilderFlags.JVM_TARGET) - } - root.build() + with(root.infoBuilder) + { + toolchainInfoBuilder.jvmBuilder.jvmTarget = + argMap.mandatorySingle(KotlinBuilderFlags.JVM_TARGET) } + root.build() + } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationArgs.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationArgs.kt new file mode 100644 index 000000000..7f9d5062c --- /dev/null +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationArgs.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2020 The Bazel Authors. All rights reserved. + * + * Licensed 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. + * + */ + +package io.bazel.kotlin.builder.tasks.jvm + +import java.nio.file.FileSystem +import java.nio.file.FileSystems +import java.nio.file.Path + +/** + * CompilationArgs collects the arguments for executing the Kotlin compiler. + */ +internal class CompilationArgs( + val args: MutableList = mutableListOf(), + private val dfs: FileSystem = FileSystems.getDefault() +) { + + fun givenNotEmpty(value: String, map: (String) -> Collection): CompilationArgs { + if (value.isNotEmpty()) { + return values(map(value)) + } + return this + } + + fun absolutePaths( + paths: Collection, + toArgs: (Sequence) -> String + ): CompilationArgs { + return value(toArgs(paths.asSequence().map { dfs.getPath(it) }.map(Path::toAbsolutePath))) + } + + fun value(value: String): CompilationArgs { + args.add(value) + return this + } + + fun flag(value: String): CompilationArgs { + args.add(value) + return this + } + + fun flag(flag: String, value: String): CompilationArgs { + args.add(flag) + args.add(value) + return this + } + + fun values(values: Collection): CompilationArgs { + args.addAll(values) + return this + } + + fun list(): List = args.toList() +} diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt index 293520725..06f654423 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt @@ -15,6 +15,7 @@ */ package io.bazel.kotlin.builder.tasks.jvm +import io.bazel.kotlin.builder.toolchain.CompilationStatusException import io.bazel.kotlin.builder.toolchain.CompilationTaskContext import io.bazel.kotlin.builder.toolchain.KotlinCompilerPluginArgsEncoder import io.bazel.kotlin.builder.toolchain.KotlinToolchain @@ -36,13 +37,38 @@ class KotlinJvmTaskExecutor @Inject internal constructor( private val jDepsGenerator: JDepsGenerator ) { fun execute(context: CompilationTaskContext, task: JvmCompilationTask) { - val preprocessedTask = task.preProcessingSteps(context, pluginArgsEncoder, compiler) + val preprocessedTask = task + .preProcessingSteps(context) + .runAnnotationProcessors(context, pluginArgsEncoder, compiler) + context.execute("compile classes") { - preprocessedTask.compileAll(context, compiler, javaCompiler) + preprocessedTask.apply { + var kotlinError: CompilationStatusException? = null + var result: List = listOf() + // skip compilation if there are no kt files. + if (inputs.kotlinSourcesCount > 0) { + context.execute("kotlinc") { + result = try { + compileKotlin(context, compiler, printOnFail = false) + } catch (ex: CompilationStatusException) { + kotlinError = ex + ex.lines + } + } + } + try { + context.execute("javac") { javaCompiler.compile(context, this) } + } finally { + result.apply(context::printCompilerOutput) + kotlinError?.also { throw it } + } + } } context.execute("create jar") { preprocessedTask.createOutputJar() } context.execute("produce src jar") { preprocessedTask.produceSourceJar() } - context.execute("generate jdeps") { jDepsGenerator.generateJDeps(preprocessedTask) } + if (preprocessedTask.outputs.jdeps.isNotEmpty()) { + context.execute("generate jdeps") { jDepsGenerator.generateJDeps(preprocessedTask) } + } } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt index d9dcbfb2f..72cb65e3a 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt @@ -17,63 +17,49 @@ // Provides extensions for the JvmCompilationTask protocol buffer. package io.bazel.kotlin.builder.tasks.jvm -import io.bazel.kotlin.builder.toolchain.CompilationStatusException import io.bazel.kotlin.builder.toolchain.CompilationTaskContext import io.bazel.kotlin.builder.toolchain.KotlinCompilerPluginArgsEncoder import io.bazel.kotlin.builder.toolchain.KotlinToolchain import io.bazel.kotlin.builder.utils.IS_JVM_SOURCE_FILE -import io.bazel.kotlin.builder.utils.addAll import io.bazel.kotlin.builder.utils.bazelRuleKind import io.bazel.kotlin.builder.utils.ensureDirectories import io.bazel.kotlin.builder.utils.jars.JarCreator import io.bazel.kotlin.builder.utils.jars.SourceJarCreator import io.bazel.kotlin.builder.utils.jars.SourceJarExtractor -import io.bazel.kotlin.builder.utils.joinedClasspath import io.bazel.kotlin.builder.utils.partitionJvmSources import io.bazel.kotlin.model.JvmCompilationTask import java.io.File import java.nio.file.Files +import java.nio.file.Path import java.nio.file.Paths /** * Return a list with the common arguments. */ -internal fun JvmCompilationTask.getCommonArgs(): MutableList { - val args = mutableListOf() - val friendPaths = info.friendPathsList.map { Paths.get(it).toAbsolutePath() } - val cp = inputs.joinedClasspath - .split(File.pathSeparator) - .map { Paths.get(it).toAbsolutePath() } - .joinToString(File.pathSeparator) - args.addAll( - "-cp", cp, - "-api-version", info.toolchainInfo.common.apiVersion, - "-language-version", info.toolchainInfo.common.languageVersion, - "-jvm-target", info.toolchainInfo.jvm.jvmTarget, - "-Xfriend-paths=${friendPaths.joinToString(X_FRIENDS_PATH_SEPARATOR)}" - ) - args - .addAll("-module-name", info.moduleName) - .addAll("-d", directories.classes) +internal fun JvmCompilationTask.commonArgs(): CompilationArgs = baseArgs() + .absolutePaths(info.friendPathsList) { + "-Xfriend-paths=${it.joinToString(X_FRIENDS_PATH_SEPARATOR)}" + } + .flag("-d", directories.classes) + .givenNotEmpty(info.passthroughFlags) { it.split(" ") } - info.passthroughFlags?.takeIf { it.isNotBlank() }?.also { args.addAll(it.split(" ")) } - return args -} +internal fun JvmCompilationTask.baseArgs(): CompilationArgs = CompilationArgs() + .flag("-cp").absolutePaths(inputs.classpathList) { + it.map(Path::toString).joinToString(File.pathSeparator) + } + .flag("-api-version", info.toolchainInfo.common.apiVersion) + .flag("-language-version", info.toolchainInfo.common.languageVersion) + .flag("-jvm-target", info.toolchainInfo.jvm.jvmTarget) + .flag("-module-name", info.moduleName) -internal fun JvmCompilationTask.preProcessingSteps( - context: CompilationTaskContext, - pluginArgsEncoder: KotlinCompilerPluginArgsEncoder, - compiler: KotlinToolchain.KotlincInvoker -): JvmCompilationTask { +internal fun JvmCompilationTask.preProcessingSteps(context: CompilationTaskContext): JvmCompilationTask { ensureDirectories( directories.temp, directories.generatedSources, - directories.generatedClasses + directories.generatedClasses, + directories.classes ) - val taskWithAdditionalSources = context.execute("expand sources") { expandWithSourceJarSources() } - return context.execute({ - "kapt (${inputs.processorsList.joinToString(", ")})" - }) { taskWithAdditionalSources.runAnnotationProcessors(context, pluginArgsEncoder, compiler) } + return context.execute("expand sources") { expandWithSourceJarSources() } } internal fun JvmCompilationTask.produceSourceJar() { @@ -99,42 +85,35 @@ internal fun JvmCompilationTask.produceSourceJar() { } } -internal fun JvmCompilationTask.runAnnotationProcessor( - context: CompilationTaskContext, - pluginArgsEncoder: KotlinCompilerPluginArgsEncoder, - compiler: KotlinToolchain.KotlincInvoker, - printOnSuccess: Boolean = true -): List { - check(inputs.processorsList.isNotEmpty()) { "method called without annotation processors" } - return getCommonArgs().let { args -> - args.addAll(pluginArgsEncoder.encode(context, this)) - args.addAll(inputs.kotlinSourcesList) - args.addAll(inputs.javaSourcesList) - context.executeCompilerTask(args, compiler::compile, printOnSuccess = printOnSuccess) - } -} - internal fun JvmCompilationTask.runAnnotationProcessors( context: CompilationTaskContext, pluginArgsEncoder: KotlinCompilerPluginArgsEncoder, compiler: KotlinToolchain.KotlincInvoker -): JvmCompilationTask = - if (inputs.processorsList.isEmpty()) { - this - } else { - runAnnotationProcessor( - context, - pluginArgsEncoder, - compiler, - printOnSuccess = context.whenTracing { false } ?: true).let { outputLines -> - // if tracing is enabled the output should be formatted in a special way, if we aren't tracing then any - // compiler output would make it's way to the console as is. - context.whenTracing { - printLines("kapt output", outputLines) - } - expandWithGeneratedSources() - } +): JvmCompilationTask { + if (inputs.processorsList.isEmpty()) { + return this + } else { + return context.execute("kapt (${inputs.processorsList.joinToString(", ")})") + { + commonArgs() + .values(pluginArgsEncoder.encode(context, this)) + .values(inputs.kotlinSourcesList) + .values(inputs.javaSourcesList).list().let { args -> + context.executeCompilerTask( + args, + compiler::compile, + printOnSuccess = context.whenTracing { false } ?: true) + }.let { outputLines -> + // if tracing is enabled the output should be formatted in a special way, if we aren't + // tracing then any compiler output would make it's way to the console as is. + context.whenTracing { + printLines("kapt output", outputLines) + } + return@let expandWithGeneratedSources() + } } + } +} /** * Produce the primary output jar. @@ -151,32 +130,6 @@ internal fun JvmCompilationTask.createOutputJar() = it.execute() } -internal fun JvmCompilationTask.compileAll( - context: CompilationTaskContext, - compiler: KotlinToolchain.KotlincInvoker, - javaCompiler: JavaCompiler -) { - ensureDirectories( - directories.classes - ) - var kotlinError: CompilationStatusException? = null - var result: List? = null - context.execute("kotlinc") { - result = try { - compileKotlin(context, compiler, printOnFail = false) - } catch (ex: CompilationStatusException) { - kotlinError = ex - ex.lines - } - } - try { - context.execute("javac") { javaCompiler.compile(context, this) } - } finally { - checkNotNull(result).also(context::printCompilerOutput) - kotlinError?.also { throw it } - } -} - /** * Compiles Kotlin sources to classes. Does not compile Java sources. */ @@ -185,11 +138,12 @@ internal fun JvmCompilationTask.compileKotlin( compiler: KotlinToolchain.KotlincInvoker, printOnFail: Boolean = true ) = - getCommonArgs().let { args -> - args.addAll(inputs.javaSourcesList) - args.addAll(inputs.kotlinSourcesList) - context.executeCompilerTask(args, compiler::compile, printOnFail = printOnFail) - } + commonArgs() + .values(inputs.javaSourcesList) + .values(inputs.kotlinSourcesList) + .list().let { args -> + return@let context.executeCompilerTask(args, compiler::compile, printOnFail = printOnFail) + } /** * If any srcjars were provided expand the jars sources and create a new [JvmCompilationTask] with the @@ -220,14 +174,14 @@ internal fun JvmCompilationTask.expandWithGeneratedSources(): JvmCompilationTask .iterator() ) -internal fun JvmCompilationTask.expandWithSources(sources: Iterator): JvmCompilationTask = +private fun JvmCompilationTask.expandWithSources(sources: Iterator): JvmCompilationTask = updateBuilder { builder -> sources.partitionJvmSources( { builder.inputsBuilder.addKotlinSources(it) }, { builder.inputsBuilder.addJavaSources(it) }) } -internal fun JvmCompilationTask.updateBuilder( +private fun JvmCompilationTask.updateBuilder( block: (JvmCompilationTask.Builder) -> Unit ): JvmCompilationTask = toBuilder().let { diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/ArgMap.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/ArgMap.kt index 01988d587..3f13d79f7 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/ArgMap.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/ArgMap.kt @@ -19,61 +19,97 @@ package io.bazel.kotlin.builder.utils import java.io.File class ArgMap(private val map: Map>) { - /** - * Get the mandatory single value from a key - */ - fun mandatorySingle(key: String): String = - optionalSingle(key) ?: throw IllegalArgumentException("$key is not optional") - - fun labelDepMap(key: String) = optional(key)?.asSequence()?.windowed(2, 2)?.map { it[0] to it[1] }?.toMap() ?: emptyMap() - - fun optionalSingle(key: String): String? = - optional(key)?.let { - when (it.size) { - 0 -> throw IllegalArgumentException("$key did not have a value") - 1 -> it[0] - else -> throw IllegalArgumentException("$key should have a single value") - } + /** + * Get the mandatory single value from a key + */ + private fun mandatorySingle(key: String): String = + optionalSingle(key) ?: throw IllegalArgumentException("$key is not optional") + + private fun labelDepMap(key: String) = + optional(key) + ?.asSequence() + ?.windowed(2, 2) + ?.map { it[0] to it[1] } + ?.toMap() + ?: emptyMap() + + private fun optionalSingle(key: String): String? = + optional(key)?.let { + when (it.size) { + 0 -> throw IllegalArgumentException("$key did not have a value") + 1 -> it[0] + else -> throw IllegalArgumentException("$key should have a single value") } + } + + private fun optionalSingleIf(key: String, condition: () -> Boolean): String? { + return if (condition()) { + optionalSingle(key) + } else { + mandatorySingle(key) + } + } + + private fun hasAll(keys: Array): Boolean { + return keys.all { optional(it)?.isNotEmpty() ?: false } + } + + private fun hasAny(keys: Array): Boolean { + return keys.any { optional(it)?.isNotEmpty() ?: false } + } + + private fun mandatory(key: String): List = optional(key) + ?: throw IllegalArgumentException( + "$key is not optional") + + private fun optional(key: String): List? = map[key] + + fun mandatorySingle(key: Flag) = mandatorySingle(key.flag) + fun optionalSingle(key: Flag) = optionalSingle(key.flag) + fun optionalSingleIf(key: Flag, condition: () -> Boolean) = + optionalSingleIf(key.flag, condition) + + fun hasAll(vararg keys: Flag) = hasAll(keys.map(Flag::flag).toTypedArray()) + fun hasAny(vararg keys: Flag) = hasAny(keys.map(Flag::flag).toTypedArray()) + fun mandatory(key: Flag) = mandatory(key.flag) + fun optional(key: Flag) = optional(key.flag) + fun labelDepMap(key: Flag) = labelDepMap(key.flag) - fun mandatory(key: String): List = optional(key) ?: throw IllegalArgumentException("$key is not optional") - fun optional(key: String): List? = map[key] } interface Flag { - val flag: String + val flag: String } -fun ArgMap.mandatorySingle(key: Flag) = mandatorySingle(key.flag) -fun ArgMap.optionalSingle(key: Flag) = optionalSingle(key.flag) -fun ArgMap.mandatory(key: Flag) = mandatory(key.flag) -fun ArgMap.optional(key: Flag) = optional(key.flag) -fun ArgMap.labelDepMap(key: Flag) = labelDepMap(key.flag) - object ArgMaps { - @JvmStatic - fun from(args: List): ArgMap = - mutableMapOf>() - .also { argsToMap(args, it) } - .let(::ArgMap) - - @JvmStatic - fun from(file: File): ArgMap = from(file.reader().readLines()) - - private fun argsToMap(args: List, argMap: MutableMap>, isFlag: (String) -> Boolean = { it.startsWith("--") }) { - var currentKey: String = args.first().also { require(isFlag(it)) { "first arg must be a flag" } } - val currentValue = mutableListOf() - val mergeCurrent = { - argMap.computeIfAbsent(currentKey) { mutableListOf() }.addAll(currentValue) - currentValue.clear() - } - args.drop(1).forEach { - if (it.startsWith("--")) { - mergeCurrent() - currentKey = it - } else { - currentValue.add(it) - } - }.also { mergeCurrent() } + @JvmStatic + fun from(args: List): ArgMap = + mutableMapOf>() + .also { argsToMap(args, it) } + .let(::ArgMap) + + @JvmStatic + fun from(file: File): ArgMap = from(file.reader().readLines()) + + private fun argsToMap( + args: List, + argMap: MutableMap>, + isFlag: (String) -> Boolean = { it.startsWith("--") } + ) { + var currentKey: String = + args.first().also { require(isFlag(it)) { "first arg must be a flag" } } + val currentValue = mutableListOf() + val mergeCurrent = { + argMap.computeIfAbsent(currentKey) { mutableListOf() }.addAll(currentValue) + currentValue.clear() } -} \ No newline at end of file + args.drop(1).forEach { + if (it.startsWith("--")) { + mergeCurrent() + currentKey = it + } else { + currentValue.add(it) + } + }.also { mergeCurrent() } + } +} diff --git a/src/test/kotlin/io/bazel/kotlin/builder/Deps.java b/src/test/kotlin/io/bazel/kotlin/builder/Deps.java index 1793879a3..7f754cfe4 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/Deps.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/Deps.java @@ -19,12 +19,13 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import io.bazel.kotlin.builder.utils.BazelRunFiles; - -import javax.annotation.Nullable; import java.util.List; import java.util.Optional; +import java.util.Properties; import java.util.Set; +import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.annotation.Nullable; public final class Deps { @SuppressWarnings({"WeakerAccess", "unused"}) @@ -82,12 +83,16 @@ public Dep build() { } } - /** Collect all of the compile jars of all the dependencies. */ + /** + * Collect all of the compile jars of all the dependencies. + */ public static Stream classpathOf(Dep... dependencies) { return Stream.of(dependencies).flatMap(it -> it.compileJars().stream()); } - /** Import a single dep. Similar to a `kt_jvm_import` or a `kt_js_import`. */ + /** + * Import a single dep. Similar to a `kt_jvm_import` or a `kt_js_import`. + */ public static Dep importJar(String label, String compileJar) { return Dep.builder() .label(label) @@ -95,6 +100,35 @@ public static Dep importJar(String label, String compileJar) { ImmutableList.of(BazelRunFiles.resolveVerified(compileJar).getAbsolutePath())) .build(); } + + /** + * Reads dependency path from jvm_args for a given label, provided that the label has been added + * as a jvm property. + *

+ * See src/test/kotlin/io/bazel/kotlin/defs.bzl for an example of proper label and runfile + * passing. + * + * @param label The label of the resource expected to be included + * @return Dep reprenseting the resource + * @throws IllegalArgumentException if the label does not exist. + */ + protected static Dep fromLabel(String label) { + // jvm properties do not allow slashes or :. + String key = label.replaceAll("/", ".").replaceAll(":", "."); + Properties properties = System.getProperties(); + Preconditions.checkArgument(properties.containsKey(key), + String.format("Unable to find %s in properties:\n%s", key, + properties.keySet() + .stream() + .map(Object::toString) + .collect(Collectors.joining("\n")))); + return Dep.builder() + .label(label) + .compileJars( + ImmutableList.of( + BazelRunFiles.resolveVerified(properties.getProperty(key)).getPath())) + .build(); + } } @AutoValue diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java index ab0e5e03e..0569e975e 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java @@ -17,9 +17,19 @@ import io.bazel.kotlin.builder.toolchain.CompilationStatusException; import io.bazel.kotlin.builder.toolchain.CompilationTaskContext; -import io.bazel.kotlin.model.*; - -import java.io.*; +import io.bazel.kotlin.model.CompilationTaskInfo; +import io.bazel.kotlin.model.KotlinToolchainInfo; +import io.bazel.kotlin.model.Platform; +import io.bazel.kotlin.model.RuleKind; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.io.UncheckedIOException; +import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -38,7 +48,7 @@ abstract class KotlinAbstractTestBuilder { private static final Path BAZEL_TEST_DIR = - Paths.get(Objects.requireNonNull(System.getenv("TEST_TMPDIR"))); + FileSystems.getDefault().getPath(System.getenv("TEST_TMPDIR")); private static final AtomicInteger counter = new AtomicInteger(0); private final CompilationTaskInfo.Builder infoBuilder = CompilationTaskInfo.newBuilder(); @@ -80,7 +90,7 @@ public final void resetForNext() { .setLanguageVersion("1.2")) .setJvm(KotlinToolchainInfo.Jvm.newBuilder().setJvmTarget("1.8"))); try { - this.instanceRoot = Files.createDirectory(BAZEL_TEST_DIR.resolve(Paths.get(label))); + this.instanceRoot = Files.createTempDirectory(BAZEL_TEST_DIR, label); } catch (IOException e) { throw new UncheckedIOException(e); } diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java index 051cb3660..c9c9f66a3 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java @@ -19,39 +19,27 @@ import com.google.common.collect.ImmutableList; import io.bazel.kotlin.builder.Deps.AnnotationProcessor; import io.bazel.kotlin.builder.Deps.Dep; +import io.bazel.kotlin.builder.toolchain.CompilationTaskContext; import io.bazel.kotlin.builder.toolchain.KotlinToolchain; import io.bazel.kotlin.model.CompilationTaskInfo; import io.bazel.kotlin.model.JvmCompilationTask; - import java.util.EnumSet; import java.util.HashSet; +import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; public final class KotlinJvmTestBuilder extends KotlinAbstractTestBuilder { + @SuppressWarnings({"unused", "WeakerAccess"}) public static Dep - KOTLIN_ANNOTATIONS = - Dep.importJar( - "kotlin-annotations", - "external/com_github_jetbrains_kotlin/lib/annotations-13.0.jar"), - KOTLIN_STDLIB = - Dep.importJar( - "kotlin-stdlib", "external/com_github_jetbrains_kotlin/lib/kotlin-stdlib.jar"), - KOTLIN_STDLIB_JDK7 = - Dep.importJar( - "kotlin-stdlib-jdk7", - "external/com_github_jetbrains_kotlin/lib/kotlin-stdlib-jdk7.jar"), - KOTLIN_STDLIB_JDK8 = - Dep.importJar( - "kotlin-stdlib-jdk8", - "external/com_github_jetbrains_kotlin/lib/kotlin-stdlib-jdk8.jar"); + KOTLIN_ANNOTATIONS = Dep.fromLabel("@com_github_jetbrains_kotlin//:annotations"), + KOTLIN_STDLIB = Dep.fromLabel("@com_github_jetbrains_kotlin//:kotlin-stdlib"), + KOTLIN_STDLIB_JDK7 = Dep.fromLabel("@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk7"), + KOTLIN_STDLIB_JDK8 = Dep.fromLabel("@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk8"); private static final JvmCompilationTask.Builder taskBuilder = JvmCompilationTask.newBuilder(); - private static final KotlinBuilderComponent component = - DaggerKotlinBuilderComponent.builder().toolchain(KotlinToolchain.createToolchain()).build(); - private static final EnumSet ALL_DIRECTORY_TYPES = EnumSet.of( DirectoryType.SOURCES, @@ -73,12 +61,6 @@ void setupForNext(CompilationTaskInfo.Builder taskInfo) { .setTemp(directory(DirectoryType.TEMP).toAbsolutePath().toString()) .setGeneratedClasses( directory(DirectoryType.GENERATED_CLASSES).toAbsolutePath().toString()); - - taskBuilder - .getOutputsBuilder() - .setJar(instanceRoot().resolve("jar_file.jar").toAbsolutePath().toString()) - .setJdeps(instanceRoot().resolve("jdeps_file.jdeps").toAbsolutePath().toString()) - .setSrcjar(instanceRoot().resolve("jar_file-sources.jar").toAbsolutePath().toString()); } @Override @@ -86,6 +68,47 @@ public JvmCompilationTask buildTask() { return taskBuilder.build(); } + private TaskBuilder taskBuilderInstance = new TaskBuilder(); + + @SafeVarargs + public final Dep runCompileTask(Consumer... setup) { + return executeTask(component().jvmTaskExecutor()::execute, setup); + } + + private KotlinBuilderComponent component() { + return DaggerKotlinBuilderComponent.builder() + .toolchain(KotlinToolchain.createToolchain()) + .build(); + } + + private Dep executeTask( + BiConsumer executor, + Consumer[] setup) { + resetForNext(); + Stream.of(setup).forEach(it -> it.accept(taskBuilderInstance)); + return runCompileTask( + (taskContext, task) -> { + executor.accept(taskContext, task); + + JvmCompilationTask.Outputs outputs = task.getOutputs(); + assertFilesExist( + Stream.of( + outputs.getJar(), + outputs.getJdeps(), + outputs.getSrcjar()) + .filter(p -> !p.isEmpty()) + .toArray(String[]::new) + ); + + return Dep.builder() + .label(taskBuilder.getInfo().getLabel()) + .compileJars(ImmutableList.of(outputs.getJar())) + .runtimeDeps(ImmutableList.copyOf(taskBuilder.getInputs().getClasspathList())) + .sourceJar(taskBuilder.getOutputs().getSrcjar()) + .build(); + }); + } + public class TaskBuilder { public TaskBuilder() {} @@ -123,24 +146,23 @@ public void addDirectDependencies(Dep... dependencies) { Dep.classpathOf(dependencies) .forEach((dependency) -> taskBuilder.getInputsBuilder().addClasspath(dependency)); } - } - private TaskBuilder taskBuilderInstance = new TaskBuilder(); + public TaskBuilder outputSrcJar() { + taskBuilder.getOutputsBuilder() + .setSrcjar(instanceRoot().resolve("jar_file-sources.jar").toAbsolutePath().toString()); + return this; + } - @SafeVarargs - public final Dep runCompileTask(Consumer... setup) { - resetForNext(); - Stream.of(setup).forEach(it -> it.accept(taskBuilderInstance)); - return runCompileTask( - (taskContext, task) -> { - component.jvmTaskExecutor().execute(taskContext, task); - assertFilesExist(task.getOutputs().getJar(), task.getOutputs().getJdeps()); - return Dep.builder() - .label(taskBuilder.getInfo().getLabel()) - .compileJars(ImmutableList.of(taskBuilder.getOutputs().getJar())) - .runtimeDeps(ImmutableList.copyOf(taskBuilder.getInputs().getClasspathList())) - .sourceJar(taskBuilder.getOutputs().getSrcjar()) - .build(); - }); + public TaskBuilder outputJar() { + taskBuilder.getOutputsBuilder() + .setJar(instanceRoot().resolve("jar_file.jar").toAbsolutePath().toString()); + return this; + } + + public TaskBuilder outputJdeps() { + taskBuilder.getOutputsBuilder() + .setJdeps(instanceRoot().resolve("jdeps_file.jdeps").toAbsolutePath().toString()); + return this; + } } } diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmBasicTest.java b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmBasicTest.java index 75ebc75d6..dc21fafdb 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmBasicTest.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmBasicTest.java @@ -18,16 +18,14 @@ import io.bazel.kotlin.builder.Deps; import io.bazel.kotlin.builder.DirectoryType; import io.bazel.kotlin.builder.KotlinJvmTestBuilder; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.function.Consumer; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; import static com.google.common.truth.Truth.assertThat; @@ -35,22 +33,53 @@ public class KotlinBuilderJvmBasicTest { private static final KotlinJvmTestBuilder ctx = new KotlinJvmTestBuilder(); + private static final Consumer SETUP_NORMALIZATION_TEST_SOURCES = + ctx -> { + ctx.addSource("AClass.kt", "package something;\n" + "class AClass{}"); + ctx.addSource("BClass.kt", "package something;\n" + "class BClass{}"); + ctx.outputJar().outputSrcJar(); + }; + @Test public void testSimpleMixedModeCompile() { ctx.runCompileTask( c -> { c.addSource("AClass.kt", "package something;" + "class AClass{}"); c.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{}"); + c.outputJar().outputSrcJar(); }); ctx.assertFilesExist( DirectoryType.CLASSES, "something/AClass.class", "something/AnotherClass.class"); } + @Test + public void testGeneratesJDeps() { + ctx.runCompileTask( + c -> { + c.addSource("AClass.kt", "package something;" + "class AClass{}"); + c.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{}"); + // declaring outputJdeps also asserts existance after compile. + c.outputJar().outputSrcJar().outputJdeps(); + }); + } + + @Test + public void testKotlinErrorRendering() { + ctx.runFailingCompileTaskAndValidateOutput( + () -> + ctx.runCompileTask( + c -> { + c.addSource("AClass.kt", "package something;" + "class AClass{"); + c.outputJar().outputSrcJar(); + }), + lines -> assertThat(lines.get(0)).startsWith(ctx.toPlatform("sources/AClass"))); + } + @Test public void testMixedBiReferences() { ctx.runCompileTask( - it -> { - it.addSource( + ctx -> { + ctx.addSource( "AClass.java", "package a;", "", @@ -59,7 +88,7 @@ public void testMixedBiReferences() { "public class AClass {", " static BClass b = new BClass();", "}"); - it.addSource( + ctx.addSource( "BClass.kt", "package b", "", @@ -68,17 +97,20 @@ public void testMixedBiReferences() { "class BClass() {", " val a = AClass()", "}"); + ctx.outputSrcJar() + .outputJar(); }); ctx.assertFilesExist(DirectoryType.CLASSES, "a/AClass.class", "b/BClass.class"); } @Test - public void testKotlinErrorRendering() { - ctx.runFailingCompileTaskAndValidateOutput( - () -> - ctx.runCompileTask( - c -> c.addSource("AClass.kt", "package something;" + "class AClass{")), - lines -> assertThat(lines.get(0)).startsWith(ctx.toPlatform("sources/AClass"))); + public void testCompileSingleJavaFile() { + ctx.runCompileTask( + (ctx) -> { + ctx.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{}"); + ctx.outputSrcJar() + .outputJar(); + }); } @Test @@ -89,23 +121,11 @@ public void testJavaErrorRendering() { c -> { c.addSource("AClass.kt", "package something;" + "class AClass{}"); c.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{"); + c.outputJar().outputSrcJar(); }), lines -> assertThat(lines.get(0)).startsWith(ctx.toPlatform("sources/AnotherClass"))); } - @Test - @Ignore("The Kotlin compiler expects a single kotlin file at least.") - public void testCompileSingleJavaFile() { - ctx.runCompileTask( - (c) -> c.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{}")); - } - - private static final Consumer SETUP_NORMALIZATION_TEST_SOURCES = - ctx -> { - ctx.addSource("AClass.kt", "package something;\n" + "class AClass{}"); - ctx.addSource("BClass.kt", "package something;\n" + "class BClass{}"); - }; - @Test public void testCompiledJarIsNormalized() { Deps.Dep previous = ctx.runCompileTask(SETUP_NORMALIZATION_TEST_SOURCES); diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmKaptTest.java b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmKaptTest.java index e68f5b3d9..311c26047 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmKaptTest.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmKaptTest.java @@ -19,35 +19,35 @@ import io.bazel.kotlin.builder.Deps.Dep; import io.bazel.kotlin.builder.DirectoryType; import io.bazel.kotlin.builder.KotlinJvmTestBuilder; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - import java.io.File; import java.util.function.Consumer; import java.util.stream.Collectors; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; import static io.bazel.kotlin.builder.KotlinJvmTestBuilder.KOTLIN_ANNOTATIONS; import static io.bazel.kotlin.builder.KotlinJvmTestBuilder.KOTLIN_STDLIB; @RunWith(JUnit4.class) public class KotlinBuilderJvmKaptTest { - private static final Dep AUTO_VALUE_ANNOTATIONS = - Dep.importJar( - "autovalue_annotations", - System.getProperty("auto_value_annotations") - .replaceFirst("external" + File.separator, "")); - private static final Dep AUTO_VALUE = - Dep.importJar( - "autovalue", - System.getProperty("auto_value") - .replaceFirst("external" + File.separator, "")); - private static final AnnotationProcessor AUTO_VALUE_ANNOTATION_PROCESSOR = - AnnotationProcessor.builder() - .processClass("com.google.auto.value.processor.AutoValueProcessor") - .processorPath( - Dep.classpathOf(AUTO_VALUE_ANNOTATIONS, AUTO_VALUE, KOTLIN_ANNOTATIONS).collect(Collectors.toSet())) - .build(); + private static final Dep AUTO_VALUE_ANNOTATIONS = + Dep.importJar( + "autovalue_annotations", + System.getProperty("auto_value_annotations") + .replaceFirst("external" + File.separator, "")); + private static final Dep AUTO_VALUE = + Dep.importJar( + "autovalue", + System.getProperty("auto_value") + .replaceFirst("external" + File.separator, "")); + private static final AnnotationProcessor AUTO_VALUE_ANNOTATION_PROCESSOR = + AnnotationProcessor.builder() + .processClass("com.google.auto.value.processor.AutoValueProcessor") + .processorPath( + Dep.classpathOf(AUTO_VALUE_ANNOTATIONS, AUTO_VALUE, KOTLIN_ANNOTATIONS) + .collect(Collectors.toSet())) + .build(); private static final KotlinJvmTestBuilder ctx = new KotlinJvmTestBuilder(); @@ -61,24 +61,27 @@ public class KotlinBuilderJvmKaptTest { public void testKaptKt() { ctx.runCompileTask( ADD_AUTO_VALUE_PLUGIN, - c -> - c.addSource( - "TestKtValue.kt", - "package autovalue\n" - + "\n" - + "import com.google.auto.value.AutoValue\n" - + "\n" - + "@AutoValue\n" - + "abstract class TestKtValue {\n" - + " abstract fun name(): String\n" - + " fun builder(): Builder = AutoValue_TestKtValue.Builder()\n" - + "\n" - + " @AutoValue.Builder\n" - + " abstract class Builder {\n" - + " abstract fun setName(name: String): Builder\n" - + " abstract fun build(): TestKtValue\n" - + " }\n" - + "}")); + c -> { + c.addSource( + "TestKtValue.kt", + "package autovalue\n" + + "\n" + + "import com.google.auto.value.AutoValue\n" + + "\n" + + "@AutoValue\n" + + "abstract class TestKtValue {\n" + + " abstract fun name(): String\n" + + " fun builder(): Builder = AutoValue_TestKtValue.Builder()\n" + + "\n" + + " @AutoValue.Builder\n" + + " abstract class Builder {\n" + + " abstract fun setName(name: String): Builder\n" + + " abstract fun build(): TestKtValue\n" + + " }\n" + + "}"); + c.outputJar().outputSrcJar(); + } + ); ctx.assertFilesExist( DirectoryType.CLASSES, @@ -91,8 +94,8 @@ public void testKaptKt() { public void testMixedKaptBiReferences() { ctx.runCompileTask( ADD_AUTO_VALUE_PLUGIN, - it -> { - it.addSource( + ctx -> { + ctx.addSource( "TestKtValue.kt", "package autovalue.a\n" + "\n" @@ -111,7 +114,7 @@ public void testMixedKaptBiReferences() { + " }\n" + "}"); - it.addSource( + ctx.addSource( "TestAutoValue.java", "package autovalue.b;\n" + "\n" @@ -134,6 +137,7 @@ public void testMixedKaptBiReferences() { + " }\n" + "\n" + "}"); + ctx.outputJar().outputSrcJar(); }); ctx.assertFilesExist( DirectoryType.SOURCE_GEN, diff --git a/src/test/kotlin/io/bazel/kotlin/defs.bzl b/src/test/kotlin/io/bazel/kotlin/defs.bzl index badf3b08f..2e4132963 100644 --- a/src/test/kotlin/io/bazel/kotlin/defs.bzl +++ b/src/test/kotlin/io/bazel/kotlin/defs.bzl @@ -24,14 +24,28 @@ def _get_class_name(kwargs): return kwargs["test_classes"] def kt_rules_test(name, **kwargs): - kwargs.setdefault("size", "small") - kwargs["deps"] = kwargs.setdefault("deps", []) + ["//src/test/kotlin/io/bazel/kotlin/builder:test_lib"] - kwargs.setdefault("test_class", _get_class_name(kwargs)) - for f in kwargs.get("srcs"): + args = dict(kwargs.items()) + args.setdefault("size", "small") + args.setdefault("data", []) + args.setdefault("jvm_flags", []) + args["deps"] = args.setdefault("deps", []) + ["//src/test/kotlin/io/bazel/kotlin/builder:test_lib"] + for dep in [ + "//src/main/kotlin/io/bazel/kotlin/compiler", + "@com_github_jetbrains_kotlin//:annotations", + "@com_github_jetbrains_kotlin//:kotlin-stdlib", + "@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk7", + "@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk8", + ] + args["data"]: + if dep not in args["data"]: + args["data"] += [dep] + args["jvm_flags"] += ["-D%s=$(rootpath %s)" %(dep.replace("/",".").replace(":","."), dep)] + + args.setdefault("test_class", _get_class_name(kwargs)) + for f in args.get("srcs"): if f.endswith(".kt"): - kt_jvm_test(name = name, **kwargs) + kt_jvm_test(name = name, **args) return - java_test(name = name, **kwargs) + java_test(name = name, **args) def kt_rules_e2e_test(name, **kwargs): kwargs.setdefault("size", "small") From e8fd9ced9641baffae48cda22e57cda47e4d849f Mon Sep 17 00:00:00 2001 From: Corbin McNeely-Smith <58151731+restingbull@users.noreply.github.com> Date: Fri, 3 Apr 2020 11:27:57 -0400 Subject: [PATCH 13/16] Apply autoformatting to all files. (#302) Ran google java format, ktlint, and buildifier. Added .buildconfig to help standardize formatting. --- .bazelci/presubmit.yml | 20 +- .editorconfig | 4 + docs/index.html | 420 +++--- docs/kotlin/kotlin.html | 1170 +++++++++-------- docs/kotlin/toolchains.html | 386 +++--- examples/dagger/src/coffee/CoffeeApp.kt | 30 +- examples/dagger/src/coffee/CoffeeMaker.kt | 22 +- .../dagger/src/coffee/DripCoffeeModule.kt | 11 +- examples/dagger/src/coffee/ElectricHeater.kt | 16 +- examples/dagger/src/coffee/Heater.kt | 6 +- examples/dagger/src/coffee/Pump.kt | 2 +- examples/dagger/src/coffee/PumpModule.kt | 4 +- examples/dagger/src/coffee/Thermosiphon.kt | 8 +- examples/node/express/App.kt | 4 +- examples/node/express/Routes.kt | 4 +- examples/node/express/auth/Auth.kt | 3 +- kotlin/dependencies.bzl | 9 +- kotlin/internal/js/importer.py | 13 +- kotlin/internal/jvm/android.bzl | 3 +- kotlin/internal/jvm/compile.bzl | 5 +- kotlin/internal/repositories/BUILD | 2 +- kotlin/internal/repositories/repositories.bzl | 3 +- scripts/noop.sh | 1 - src/main/kotlin/BUILD | 4 +- src/main/kotlin/io/bazel/kotlin/builder/BUILD | 6 +- .../builder/KotlinBuilderComponent.java | 52 +- .../kotlin/builder/KotlinBuilderMain.java | 16 +- .../io/bazel/kotlin/builder/tasks/BUILD.bazel | 6 +- .../bazel/kotlin/builder/tasks/BazelWorker.kt | 224 ++-- .../kotlin/builder/tasks/KotlinBuilder.kt | 187 ++- .../builder/tasks/js/Kotlin2JsTaskExecutor.kt | 102 +- .../builder/tasks/jvm/JDepsGenerator.kt | 91 +- .../kotlin/builder/tasks/jvm/JavaCompiler.kt | 63 +- .../kotlin/builder/tasks/jvm/JdepsParser.kt | 199 +-- .../tasks/jvm/KotlinJvmTaskExecutor.kt | 4 +- .../builder/tasks/jvm/compilation_task.kt | 163 ++- .../kotlin/builder/toolchain/BUILD.bazel | 2 +- .../toolchain/CompilationTaskContext.kt | 260 ++-- .../KotlinCompilerPluginArgsEncoder.kt | 143 +- .../builder/toolchain/KotlinToolException.kt | 14 +- .../builder/toolchain/KotlinToolchain.kt | 62 +- .../io/bazel/kotlin/builder/utils/ArgMap.kt | 42 +- .../io/bazel/kotlin/builder/utils/BUILD.bazel | 2 +- .../bazel/kotlin/builder/utils/BazelUtils.kt | 123 +- .../io/bazel/kotlin/builder/utils/IOUtils.kt | 93 +- .../bazel/kotlin/builder/utils/MiscUtils.kt | 6 +- .../bazel/kotlin/builder/utils/TaskUtils.kt | 12 +- .../kotlin/builder/utils/jars/JarCreator.kt | 376 +++--- .../kotlin/builder/utils/jars/JarExtractor.kt | 52 +- .../kotlin/builder/utils/jars/JarHelper.kt | 401 +++--- .../builder/utils/jars/SourceJarCreator.kt | 294 ++--- .../builder/utils/jars/SourceJarExtractor.kt | 49 +- .../io/bazel/kotlin/compiler/BUILD.bazel | 2 +- .../kotlin/compiler/BazelK2JVMCompiler.kt | 13 +- src/main/protobuf/worker_protocol.proto | 36 +- src/test/Bazel_all_local_tests.xml | 5 +- src/test/data/jvm/basic/helloworld/Main.kt | 15 +- .../propagation/CompileTimeDependent.java | 8 +- .../data/jvm/basic/test_friends/Service.kt | 2 +- .../jvm/basic/testresources/src/AClass.kt | 8 +- .../data/jvm/kapt/java/TestAutoValue.java | 6 +- .../data/jvm/kapt/java/TestJavaService.java | 3 +- .../jvm/kapt/kotlin/TestKtAPNoGenReference.kt | 14 +- .../data/jvm/kapt/kotlin/TestKtService.kt | 6 +- src/test/data/jvm/kapt/kotlin/TestKtValue.kt | 16 +- .../bazel/kotlin/KotlinAssertionTestCase.kt | 168 +-- .../kotlin/io/bazel/kotlin/KotlinJvm13Test.kt | 14 +- .../kotlin/KotlinJvmBasicAssertionTest.kt | 115 +- .../kotlin/KotlinJvmDaggerExampleTest.kt | 16 +- .../kotlin/KotlinJvmFriendsVisibilityTest.kt | 16 +- .../kotlin/KotlinJvmKaptAssertionTest.kt | 133 +- .../KotlinNormalizationAssertionTest.kt | 63 +- src/test/kotlin/io/bazel/kotlin/builder/BUILD | 4 +- .../kotlin/io/bazel/kotlin/builder/Deps.java | 191 +-- .../bazel/kotlin/builder/DirectoryType.java | 44 +- .../builder/KotlinAbstractTestBuilder.java | 370 +++--- .../kotlin/builder/KotlinJsTestBuilder.java | 87 +- .../kotlin/builder/KotlinJvmTestBuilder.java | 244 ++-- .../io/bazel/kotlin/builder/tasks/BUILD.bazel | 17 +- .../builder/tasks/js/KotlinBuilderJsTest.java | 29 +- .../builder/tasks/jvm/JdepsParserTest.java | 228 ++-- .../tasks/jvm/KotlinBuilderJvmBasicTest.java | 235 ++-- .../tasks/jvm/KotlinBuilderJvmKaptTest.java | 229 ++-- .../tasks/jvm/KotlinJvmTaskExecutorTest.kt | 83 +- .../utils/jars/SourceJarCreatorTest.java | 46 +- src/test/kotlin/io/bazel/kotlin/defs.bzl | 2 +- 86 files changed, 3937 insertions(+), 3725 deletions(-) create mode 100644 .editorconfig diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 983580612..8bcc40ca1 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -14,19 +14,19 @@ tasks: - "//:rules_kotlin_release" rbe_ubuntu1604: test_targets: - - "--" - - "//src/test/kotlin/io/bazel/kotlin/builder:builder_tests" - # KotlinJvmDaggerExampleTest and KotlinJvmKaptAssertionTest are not remote - # execution compatible, do not run them for now. - - "//src/test/kotlin/io/bazel/kotlin:KotlinJvmFriendsVisibilityTest" - - "//src/test/kotlin/io/bazel/kotlin:KotlinJvmBasicAssertionTest" + - "--" + - "//src/test/kotlin/io/bazel/kotlin/builder:builder_tests" + # KotlinJvmDaggerExampleTest and KotlinJvmKaptAssertionTest are not remote + # execution compatible, do not run them for now. + - "//src/test/kotlin/io/bazel/kotlin:KotlinJvmFriendsVisibilityTest" + - "//src/test/kotlin/io/bazel/kotlin:KotlinJvmBasicAssertionTest" test_flags: - # Override the default worker strategy for remote builds (worker strategy - # cannot be used with remote builds) - - "--strategy=KotlinCompile=remote" + # Override the default worker strategy for remote builds (worker strategy + # cannot be used with remote builds) + - "--strategy=KotlinCompile=remote" macos: test_targets: - - "//:all_tests" + - "//:all_tests" example-android: name: "Example - Android" platform: ubuntu1804 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..d8296a313 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +[*.{kt, kts}] +indent_size = 2 +insert_final_newline = true +max_line_length = 100 diff --git a/docs/index.html b/docs/index.html index 5719cbd30..f6ba5bb5c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,234 +1,236 @@ - - - + - - + + Overview - - - + + + - - - -

- + + + diff --git a/docs/kotlin/kotlin.html b/docs/kotlin/kotlin.html index 976f158b9..93bd7e740 100644 --- a/docs/kotlin/kotlin.html +++ b/docs/kotlin/kotlin.html @@ -1,102 +1,101 @@ - - - + - - + + Kotlin Rules - - - + + + - - - - - + + + diff --git a/docs/kotlin/toolchains.html b/docs/kotlin/toolchains.html index 8617634cf..e708c2d18 100644 --- a/docs/kotlin/toolchains.html +++ b/docs/kotlin/toolchains.html @@ -1,214 +1,222 @@ - - - + - - + + toolchains Rules - - - + + + - - - - - + + + diff --git a/examples/dagger/src/coffee/CoffeeApp.kt b/examples/dagger/src/coffee/CoffeeApp.kt index 19fc2239f..68bd6732e 100644 --- a/examples/dagger/src/coffee/CoffeeApp.kt +++ b/examples/dagger/src/coffee/CoffeeApp.kt @@ -17,25 +17,25 @@ package coffee import dagger.Component import kotlinx.coroutines.runBlocking -import javax.inject.Singleton import tea.TeaPot +import javax.inject.Singleton class CoffeeApp { - @Singleton - @Component(modules = [(DripCoffeeModule::class)]) - interface CoffeeShop { - fun maker(): CoffeeMaker - } + @Singleton + @Component(modules = [(DripCoffeeModule::class)]) + interface CoffeeShop { + fun maker(): CoffeeMaker + } - companion object { - @JvmStatic - fun main(args: Array) { - if (TeaPot.isEmpty()) { - val coffeeShop = DaggerCoffeeApp_CoffeeShop.builder().build() - runBlocking { - coffeeShop.maker().brew() - } - } + companion object { + @JvmStatic + fun main(args: Array) { + if (TeaPot.isEmpty()) { + val coffeeShop = DaggerCoffeeApp_CoffeeShop.builder().build() + runBlocking { + coffeeShop.maker().brew() } + } } + } } diff --git a/examples/dagger/src/coffee/CoffeeMaker.kt b/examples/dagger/src/coffee/CoffeeMaker.kt index 7ccd2ee41..270eb1efb 100644 --- a/examples/dagger/src/coffee/CoffeeMaker.kt +++ b/examples/dagger/src/coffee/CoffeeMaker.kt @@ -21,18 +21,18 @@ import kotlinx.coroutines.withContext import javax.inject.Inject class CoffeeMaker @Inject internal constructor( - // Create a possibly costly heater only when we use it. - private val heater: Lazy, - private val pump: Pump + // Create a possibly costly heater only when we use it. + private val heater: Lazy, + private val pump: Pump ) { - suspend fun brew() { - // this function is async to verify intellij support for coroutines. - withContext(Dispatchers.Default) { - heater.get().on() - pump.pump() - println(" [_]P coffee! [_]P ") - heater.get().off() - } + suspend fun brew() { + // this function is async to verify intellij support for coroutines. + withContext(Dispatchers.Default) { + heater.get().on() + pump.pump() + println(" [_]P coffee! [_]P ") + heater.get().off() } + } } diff --git a/examples/dagger/src/coffee/DripCoffeeModule.kt b/examples/dagger/src/coffee/DripCoffeeModule.kt index a4717ebdc..42bddbc33 100644 --- a/examples/dagger/src/coffee/DripCoffeeModule.kt +++ b/examples/dagger/src/coffee/DripCoffeeModule.kt @@ -17,14 +17,13 @@ package coffee import dagger.Module import dagger.Provides - import javax.inject.Singleton @Module(includes = arrayOf(PumpModule::class)) internal class DripCoffeeModule { - @Provides - @Singleton - fun provideHeater(): Heater { - return ElectricHeater() - } + @Provides + @Singleton + fun provideHeater(): Heater { + return ElectricHeater() + } } diff --git a/examples/dagger/src/coffee/ElectricHeater.kt b/examples/dagger/src/coffee/ElectricHeater.kt index eebdb1dc1..32cd9eea7 100644 --- a/examples/dagger/src/coffee/ElectricHeater.kt +++ b/examples/dagger/src/coffee/ElectricHeater.kt @@ -16,14 +16,14 @@ package coffee internal class ElectricHeater : Heater { - override var isHot: Boolean = false + override var isHot: Boolean = false - override fun on() { - println("~ ~ ~ heating ~ ~ ~") - this.isHot = true - } + override fun on() { + println("~ ~ ~ heating ~ ~ ~") + this.isHot = true + } - override fun off() { - this.isHot = false - } + override fun off() { + this.isHot = false + } } diff --git a/examples/dagger/src/coffee/Heater.kt b/examples/dagger/src/coffee/Heater.kt index cebb61ff5..d4eb52bac 100644 --- a/examples/dagger/src/coffee/Heater.kt +++ b/examples/dagger/src/coffee/Heater.kt @@ -16,7 +16,7 @@ package coffee internal interface Heater { - val isHot: Boolean - fun on() - fun off() + val isHot: Boolean + fun on() + fun off() } diff --git a/examples/dagger/src/coffee/Pump.kt b/examples/dagger/src/coffee/Pump.kt index 6796ee000..e695cc22b 100644 --- a/examples/dagger/src/coffee/Pump.kt +++ b/examples/dagger/src/coffee/Pump.kt @@ -16,5 +16,5 @@ package coffee internal interface Pump { - fun pump() + fun pump() } diff --git a/examples/dagger/src/coffee/PumpModule.kt b/examples/dagger/src/coffee/PumpModule.kt index 8a499e7c5..304c3e217 100644 --- a/examples/dagger/src/coffee/PumpModule.kt +++ b/examples/dagger/src/coffee/PumpModule.kt @@ -20,6 +20,6 @@ import dagger.Module @Module internal abstract class PumpModule { - @Binds - internal abstract fun providePump(pump: Thermosiphon): Pump + @Binds + internal abstract fun providePump(pump: Thermosiphon): Pump } diff --git a/examples/dagger/src/coffee/Thermosiphon.kt b/examples/dagger/src/coffee/Thermosiphon.kt index b70633520..cea1253e4 100644 --- a/examples/dagger/src/coffee/Thermosiphon.kt +++ b/examples/dagger/src/coffee/Thermosiphon.kt @@ -20,9 +20,9 @@ import javax.inject.Inject internal class Thermosiphon @Inject constructor(private val heater: Heater) : Pump { - override fun pump() { - if (heater.isHot) { - println("=> => pumping => =>") - } + override fun pump() { + if (heater.isHot) { + println("=> => pumping => =>") } + } } diff --git a/examples/node/express/App.kt b/examples/node/express/App.kt index 36947ffcd..a7cfa6e30 100644 --- a/examples/node/express/App.kt +++ b/examples/node/express/App.kt @@ -15,7 +15,7 @@ fun main(args: Array) { // register the routes. val hitCountChannel = routes(app) scope.launch { - hitCountChannel.consumeEach { + hitCountChannel.consumeEach { println("Hits so far: $it") } } @@ -23,4 +23,4 @@ fun main(args: Array) { app.listen(3000, { println("Listening on port 3000") }) -} \ No newline at end of file +} diff --git a/examples/node/express/Routes.kt b/examples/node/express/Routes.kt index 44d15d21a..dc00de50f 100644 --- a/examples/node/express/Routes.kt +++ b/examples/node/express/Routes.kt @@ -15,7 +15,7 @@ fun routes(app: dynamic): Channel { val hitsSoFar = hitCounter.updateAndGet { it + 1 } channel.send(hitsSoFar) } - if(!isAuthenticated("bob")) { + if (!isAuthenticated("bob")) { res.send(401, "you sir, are not authorized !") } else { res.type("text/plain") @@ -24,4 +24,4 @@ fun routes(app: dynamic): Channel { } return channel -} \ No newline at end of file +} diff --git a/examples/node/express/auth/Auth.kt b/examples/node/express/auth/Auth.kt index f5a2d4c93..8665a22f3 100644 --- a/examples/node/express/auth/Auth.kt +++ b/examples/node/express/auth/Auth.kt @@ -1,6 +1,5 @@ package express.auth - fun isAuthenticated(user: String): Boolean { return user != "bob" -} \ No newline at end of file +} diff --git a/kotlin/dependencies.bzl b/kotlin/dependencies.bzl index c1aa2984d..85e217d24 100644 --- a/kotlin/dependencies.bzl +++ b/kotlin/dependencies.bzl @@ -12,8 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +load( + "//kotlin/internal/repositories:download.bzl", + _kt_download_local_dev_dependencies = "kt_download_local_dev_dependencies", +) -load("//kotlin/internal/repositories:download.bzl", - _kt_download_local_dev_dependencies="kt_download_local_dev_dependencies") - -kt_download_local_dev_dependencies=_kt_download_local_dev_dependencies \ No newline at end of file +kt_download_local_dev_dependencies = _kt_download_local_dev_dependencies diff --git a/kotlin/internal/js/importer.py b/kotlin/internal/js/importer.py index 87bfb571e..c6d023c5e 100644 --- a/kotlin/internal/js/importer.py +++ b/kotlin/internal/js/importer.py @@ -14,9 +14,9 @@ import argparse import os import re -import zipfile -import tempfile import shutil +import tempfile +import zipfile def _is_jar(jar): @@ -42,7 +42,7 @@ def _extract_root_entry(jar, filename_pattern, output_path, touch=False): if filename_pattern.match(filename): target = filename break - + if not target: if touch: f = open(output_path, 'a') @@ -50,7 +50,7 @@ def _extract_root_entry(jar, filename_pattern, output_path, touch=False): return else: raise FileNotFoundError("No file matching {0} was found in jar".format(filename_pattern)) - + # Extract the target file to a temporary location. temp_dir = tempfile.gettempdir() temp_file = os.path.join(temp_dir, os.path.basename(target)) @@ -70,10 +70,11 @@ def _main(p): parser = argparse.ArgumentParser() parser.add_argument("--jar", type=_is_jar, required=True) -parser.add_argument("--import_pattern", required=True, type=re.compile, help="regular expression to match when searching the jar for the KotlinJS file") +parser.add_argument("--import_pattern", required=True, type=re.compile, + help="regular expression to match when searching the jar for the KotlinJS file") parser.add_argument("--import_out", required=True, help="path where the extracted KotlinJS import should be stored") parser.add_argument( - "--aux_pattern", nargs="*", type=re.compile, + "--aux_pattern", nargs="*", type=re.compile, help="""regular expressions to match when searching the jar for additional files""") parser.add_argument( "--aux_out", nargs="*", diff --git a/kotlin/internal/jvm/android.bzl b/kotlin/internal/jvm/android.bzl index ab329a713..87c2d6af3 100644 --- a/kotlin/internal/jvm/android.bzl +++ b/kotlin/internal/jvm/android.bzl @@ -22,8 +22,9 @@ def _kt_android_artifact(name, srcs = [], deps = [], plugins = [], **kwargs): """ base_name = name + "_base" kt_name = name + "_kt" + # TODO(bazelbuild/rules_kotlin/issues/273): This should be retrieved from a provider. - base_deps = deps + [ "@io_bazel_rules_kotlin//third_party:android_sdk" ] + base_deps = deps + ["@io_bazel_rules_kotlin//third_party:android_sdk"] native.android_library( name = base_name, diff --git a/kotlin/internal/jvm/compile.bzl b/kotlin/internal/jvm/compile.bzl index ded6c9317..76c14f040 100644 --- a/kotlin/internal/jvm/compile.bzl +++ b/kotlin/internal/jvm/compile.bzl @@ -233,7 +233,7 @@ def kt_jvm_compile_action(ctx, rule_kind, output_jar): "output": output_jar, "kotlin_output_jdeps": ctx.outputs.jdeps, "kotlin_output_srcjar": ctx.outputs.srcjar, - } + }, ) return struct( @@ -263,7 +263,6 @@ def kt_jvm_compile_action(ctx, rule_kind, output_jar): ), ) - def _run_kt_builder_action(ctx, rule_kind, toolchains, dirs, srcs, friend, compile_deps, plugins, outputs): """Creates a KotlinBuilder action invocation.""" args = _utils.init_args(ctx, rule_kind, friend.module_name) @@ -320,8 +319,6 @@ def _run_kt_builder_action(ctx, rule_kind, toolchains, dirs, srcs, friend, compi }, ) - - def kt_jvm_produce_jar_actions(ctx, rule_kind): """Setup The actions to compile a jar and if any resources or resource_jars were provided to merge these in with the compilation output. diff --git a/kotlin/internal/repositories/BUILD b/kotlin/internal/repositories/BUILD index cd4191ac1..a70aa0c15 100644 --- a/kotlin/internal/repositories/BUILD +++ b/kotlin/internal/repositories/BUILD @@ -18,7 +18,7 @@ release_archive( srcs = [ "BUILD", "BUILD.com_github_jetbrains_kotlin", - "download.bzl" + "download.bzl", ], src_map = { "release_repositories.bzl": "repositories.bzl", diff --git a/kotlin/internal/repositories/repositories.bzl b/kotlin/internal/repositories/repositories.bzl index 1030709bc..f4d5cfd84 100644 --- a/kotlin/internal/repositories/repositories.bzl +++ b/kotlin/internal/repositories/repositories.bzl @@ -13,11 +13,12 @@ # limitations under the License. """This file contains the Kotlin compiler repository definitions. It should not be loaded directly by client workspaces. """ + load("//kotlin/internal/repositories:setup.bzl", "kt_configure") load( "//kotlin/internal/repositories:release_repositories.bzl", - _release_kotlin_repositories = "kotlin_repositories", "KOTLIN_CURRENT_COMPILER_RELEASE", + _release_kotlin_repositories = "kotlin_repositories", ) def kotlin_repositories(compiler_release = KOTLIN_CURRENT_COMPILER_RELEASE): diff --git a/scripts/noop.sh b/scripts/noop.sh index 89a7f2066..239dfa952 100755 --- a/scripts/noop.sh +++ b/scripts/noop.sh @@ -1,3 +1,2 @@ #!/usr/bin/env bash # do nothing. - diff --git a/src/main/kotlin/BUILD b/src/main/kotlin/BUILD index 7fd6f1c2f..f71eb9a4d 100644 --- a/src/main/kotlin/BUILD +++ b/src/main/kotlin/BUILD @@ -33,7 +33,7 @@ jar_jar( java_binary( name = "builder", data = [ - "//src/main/kotlin/io/bazel/kotlin/compiler:compiler", + "//src/main/kotlin/io/bazel/kotlin/compiler", "@com_github_jetbrains_kotlin//:lib/kotlin-compiler.jar", ], jvm_flags = [ @@ -50,7 +50,7 @@ java_binary( release_archive( name = "pkg", srcs = [ - "//src/main/kotlin/io/bazel/kotlin/compiler:compiler", + "//src/main/kotlin/io/bazel/kotlin/compiler", ], package_dir = "src/main/kotlin", # explicitly set the package directory, as there are no parent release_archives. src_map = { diff --git a/src/main/kotlin/io/bazel/kotlin/builder/BUILD b/src/main/kotlin/io/bazel/kotlin/builder/BUILD index 527161266..9f77d6b18 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/BUILD +++ b/src/main/kotlin/io/bazel/kotlin/builder/BUILD @@ -22,6 +22,9 @@ java_library( "@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk8", ], deps = [ + "//src/main/kotlin/io/bazel/kotlin/builder/tasks", + "//src/main/kotlin/io/bazel/kotlin/builder/toolchain", + "//src/main/kotlin/io/bazel/kotlin/builder/utils", "//src/main/protobuf:deps_java_proto", "//src/main/protobuf:kotlin_model_java_proto", "//src/main/protobuf:worker_protocol_java_proto", @@ -29,8 +32,5 @@ java_library( "@com_github_jetbrains_kotlin//:annotations", "@com_github_jetbrains_kotlin//:kotlin-stdlib", "@kotlin_rules_maven//:javax_inject_javax_inject", - "//src/main/kotlin/io/bazel/kotlin/builder/utils:utils", - "//src/main/kotlin/io/bazel/kotlin/builder/toolchain:toolchain", - "//src/main/kotlin/io/bazel/kotlin/builder/tasks:tasks", ], ) diff --git a/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java b/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java index a3f0daac3..521a0e012 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java +++ b/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java @@ -22,8 +22,8 @@ import io.bazel.kotlin.builder.tasks.KotlinBuilder; import io.bazel.kotlin.builder.tasks.js.Kotlin2JsTaskExecutor; import io.bazel.kotlin.builder.tasks.jvm.KotlinJvmTaskExecutor; -import io.bazel.kotlin.builder.toolchain.KotlinToolchain; import io.bazel.kotlin.builder.toolchain.KotlinCompilerPluginArgsEncoder; +import io.bazel.kotlin.builder.toolchain.KotlinToolchain; import javax.inject.Singleton; import java.io.PrintStream; @@ -31,38 +31,38 @@ @Singleton @dagger.Component(modules = {KotlinBuilderComponent.Module.class}) public interface KotlinBuilderComponent { - KotlinToolchain toolchain(); - - KotlinJvmTaskExecutor jvmTaskExecutor(); + KotlinToolchain toolchain(); - Kotlin2JsTaskExecutor jsTaskExecutor(); + KotlinJvmTaskExecutor jvmTaskExecutor(); - BazelWorker worker(); + Kotlin2JsTaskExecutor jsTaskExecutor(); - @Component.Builder - interface Builder { - @BindsInstance - KotlinBuilderComponent.Builder toolchain(KotlinToolchain toolchain); + BazelWorker worker(); - KotlinBuilderComponent build(); - } + @Component.Builder + interface Builder { + @BindsInstance + KotlinBuilderComponent.Builder toolchain(KotlinToolchain toolchain); - @dagger.Module - class Module { - @Provides - public KotlinCompilerPluginArgsEncoder providePluginArgEncoder(KotlinToolchain toolchain) { - return new KotlinCompilerPluginArgsEncoder( - toolchain.getKapt3Plugin().getJarPath(), toolchain.getKapt3Plugin().getId()); + KotlinBuilderComponent build(); } - @Provides - public PrintStream provideDebugPrintStream() { - return System.err; - } + @dagger.Module + class Module { + @Provides + public KotlinCompilerPluginArgsEncoder providePluginArgEncoder(KotlinToolchain toolchain) { + return new KotlinCompilerPluginArgsEncoder( + toolchain.getKapt3Plugin().getJarPath(), toolchain.getKapt3Plugin().getId()); + } + + @Provides + public PrintStream provideDebugPrintStream() { + return System.err; + } - @Provides - public BazelWorker provideWorker(KotlinBuilder builder) { - return new BazelWorker(builder, System.err, "KotlinCompile"); + @Provides + public BazelWorker provideWorker(KotlinBuilder builder) { + return new BazelWorker(builder, System.err, "KotlinCompile"); + } } - } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderMain.java b/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderMain.java index c98ad2db3..58134d436 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderMain.java +++ b/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderMain.java @@ -17,16 +17,14 @@ import io.bazel.kotlin.builder.toolchain.KotlinToolchain; -import javax.inject.Provider; -import java.io.PrintStream; import java.util.Arrays; public class KotlinBuilderMain { - public static void main(String[] args) { - KotlinBuilderComponent component = - DaggerKotlinBuilderComponent.builder() - .toolchain(KotlinToolchain.createToolchain()) - .build(); - System.exit(component.worker().apply(Arrays.asList(args))); - } + public static void main(String[] args) { + KotlinBuilderComponent component = + DaggerKotlinBuilderComponent.builder() + .toolchain(KotlinToolchain.createToolchain()) + .build(); + System.exit(component.worker().apply(Arrays.asList(args))); + } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel b/src/main/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel index d8c7d501a..b07e40672 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel @@ -21,6 +21,8 @@ kt_bootstrap_library( ]), visibility = ["//src:__subpackages__"], deps = [ + "//src/main/kotlin/io/bazel/kotlin/builder/toolchain", + "//src/main/kotlin/io/bazel/kotlin/builder/utils", "//src/main/protobuf:deps_java_proto", "//src/main/protobuf:kotlin_model_java_proto", "//src/main/protobuf:worker_protocol_java_proto", @@ -28,7 +30,5 @@ kt_bootstrap_library( "@kotlin_rules_maven//:com_google_protobuf_protobuf_java", "@kotlin_rules_maven//:com_google_protobuf_protobuf_java_util", "@kotlin_rules_maven//:javax_inject_javax_inject", - "//src/main/kotlin/io/bazel/kotlin/builder/utils:utils", - "//src/main/kotlin/io/bazel/kotlin/builder/toolchain:toolchain", ], -) \ No newline at end of file +) diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/BazelWorker.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/BazelWorker.kt index 2f865a132..cd575ed0e 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/BazelWorker.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/BazelWorker.kt @@ -17,7 +17,11 @@ package io.bazel.kotlin.builder.tasks import com.google.devtools.build.lib.worker.WorkerProtocol import io.bazel.kotlin.builder.utils.rootCause -import java.io.* +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.IOException +import java.io.InterruptedIOException +import java.io.PrintStream import java.nio.charset.StandardCharsets.UTF_8 import java.nio.file.Files import java.nio.file.Paths @@ -28,16 +32,16 @@ import java.nio.file.Paths * This is the same thing as a main function, except not static. */ interface CommandLineProgram { - /** - * Runs blocking program start to finish. - * - * This function might be called multiple times throughout the life of this object. Output - * must be sent to [System.out] and [System.err]. - * - * @param args command line arguments - * @return program exit code, i.e. 0 for success, non-zero for failure - */ - fun apply(args: List): Int + /** + * Runs blocking program start to finish. + * + * This function might be called multiple times throughout the life of this object. Output + * must be sent to [System.out] and [System.err]. + * + * @param args command line arguments + * @return program exit code, i.e. 0 for success, non-zero for failure + */ + fun apply(args: List): Int } /** @@ -50,115 +54,117 @@ interface CommandLineProgram { * @param delegate program type */ class BazelWorker( - private val delegate: CommandLineProgram, - private val output: PrintStream, - private val mnemonic: String + private val delegate: CommandLineProgram, + private val output: PrintStream, + private val mnemonic: String ) : CommandLineProgram { - companion object { - private const val INTERUPTED_STATUS = 0 - private const val ERROR_STATUS = 1 - } - - override fun apply(args: List): Int { - return if (args.contains("--persistent_worker")) - runAsPersistentWorker(args) - else delegate.apply(loadArguments(args, false)) - } + companion object { + private const val INTERUPTED_STATUS = 0 + private const val ERROR_STATUS = 1 + } - @Suppress("UNUSED_PARAMETER") - private fun runAsPersistentWorker(ignored: List): Int { - val realStdIn = System.`in` - val realStdOut = System.out - val realStdErr = System.err - try { - ByteArrayInputStream(ByteArray(0)).use { emptyIn -> - ByteArrayOutputStream().use { buffer -> - PrintStream(buffer).use { ps -> - System.setIn(emptyIn) - System.setOut(ps) - System.setErr(ps) - while (true) { - val request = WorkerProtocol.WorkRequest.parseDelimitedFrom(realStdIn) ?: return 0 - val exitCode = try { - delegate.apply(loadArguments(request.argumentsList, true)) - } catch (e: RuntimeException) { - val innerExitCode = if (wasInterrupted(e)) INTERUPTED_STATUS - else ERROR_STATUS.also { - System.err.println( - "ERROR: Worker threw uncaught exception with args: ${request.argumentsList.joinToString(" ")}" - ) - e.printStackTrace(System.err) - } - WorkerProtocol.WorkResponse.newBuilder() - .setOutput(buffer.toString()) - .setExitCode(innerExitCode) - .build() - .writeDelimitedTo(realStdOut) - realStdOut.flush() - return innerExitCode - } + override fun apply(args: List): Int { + return if (args.contains("--persistent_worker")) + runAsPersistentWorker(args) + else delegate.apply(loadArguments(args, false)) + } - WorkerProtocol.WorkResponse.newBuilder() - .setOutput(buffer.toString()) - .setExitCode(exitCode) - .build() - .writeDelimitedTo(realStdOut) - realStdOut.flush() - buffer.reset() - System.gc() // be a good little worker process and consume less memory when idle - } - } + @Suppress("UNUSED_PARAMETER") + private fun runAsPersistentWorker(ignored: List): Int { + val realStdIn = System.`in` + val realStdOut = System.out + val realStdErr = System.err + try { + ByteArrayInputStream(ByteArray(0)).use { emptyIn -> + ByteArrayOutputStream().use { buffer -> + PrintStream(buffer).use { ps -> + System.setIn(emptyIn) + System.setOut(ps) + System.setErr(ps) + while (true) { + val request = WorkerProtocol.WorkRequest.parseDelimitedFrom(realStdIn) ?: return 0 + val exitCode = try { + delegate.apply(loadArguments(request.argumentsList, true)) + } catch (e: RuntimeException) { + val innerExitCode = if (wasInterrupted(e)) INTERUPTED_STATUS + else ERROR_STATUS.also { + System.err.println( + "ERROR: Worker threw uncaught exception with args: ${request.argumentsList.joinToString( + " " + )}" + ) + e.printStackTrace(System.err) } + WorkerProtocol.WorkResponse.newBuilder() + .setOutput(buffer.toString()) + .setExitCode(innerExitCode) + .build() + .writeDelimitedTo(realStdOut) + realStdOut.flush() + return innerExitCode + } + + WorkerProtocol.WorkResponse.newBuilder() + .setOutput(buffer.toString()) + .setExitCode(exitCode) + .build() + .writeDelimitedTo(realStdOut) + realStdOut.flush() + buffer.reset() + System.gc() // be a good little worker process and consume less memory when idle } - } catch (e: IOException) { - if (wasInterrupted(e)) { - return INTERUPTED_STATUS - } - throw e - } catch (e: RuntimeException) { - if (wasInterrupted(e)) { - return INTERUPTED_STATUS - } - throw e - } finally { - System.setIn(realStdIn) - System.setOut(realStdOut) - System.setErr(realStdErr) + } } - throw RuntimeException("drop through") + } + } catch (e: IOException) { + if (wasInterrupted(e)) { + return INTERUPTED_STATUS + } + throw e + } catch (e: RuntimeException) { + if (wasInterrupted(e)) { + return INTERUPTED_STATUS + } + throw e + } finally { + System.setIn(realStdIn) + System.setOut(realStdOut) + System.setErr(realStdErr) } + throw RuntimeException("drop through") + } - private fun loadArguments(args: List, isWorker: Boolean): List { - if (args.isNotEmpty()) { - val lastArg = args[args.size - 1] + private fun loadArguments(args: List, isWorker: Boolean): List { + if (args.isNotEmpty()) { + val lastArg = args[args.size - 1] - if (lastArg.startsWith("@")) { - val pathElement = lastArg.substring(1) - val flagFile = Paths.get(pathElement) - if (isWorker && lastArg.startsWith("@@") || Files.exists(flagFile)) { - if (!isWorker && !mnemonic.isEmpty()) { - output.printf( - "HINT: %s will compile faster if you run: " + "echo \"build --strategy=%s=worker\" >>~/.bazelrc\n", - mnemonic, mnemonic - ) - } - try { - return Files.readAllLines(flagFile, UTF_8) - } catch (e: IOException) { - throw RuntimeException(e) - } - } - } + if (lastArg.startsWith("@")) { + val pathElement = lastArg.substring(1) + val flagFile = Paths.get(pathElement) + if (isWorker && lastArg.startsWith("@@") || Files.exists(flagFile)) { + if (!isWorker && !mnemonic.isEmpty()) { + output.printf( + "HINT: %s will compile faster if you run: " + "echo \"build --strategy=%s=worker\" >>~/.bazelrc\n", + mnemonic, mnemonic + ) + } + try { + return Files.readAllLines(flagFile, UTF_8) + } catch (e: IOException) { + throw RuntimeException(e) + } } - return args + } } + return args + } - private fun wasInterrupted(e: Throwable): Boolean { - val cause = e.rootCause - if (cause is InterruptedException || cause is InterruptedIOException) { - output.println("Terminating worker due to interrupt signal") - return true - } - return false + private fun wasInterrupted(e: Throwable): Boolean { + val cause = e.rootCause + if (cause is InterruptedException || cause is InterruptedIOException) { + output.println("Terminating worker due to interrupt signal") + return true } + return false + } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt index 6263ab0dd..b1ddd94e9 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt @@ -59,7 +59,8 @@ class KotlinBuilder @Inject internal constructor( Platform.JVM -> executeJvmTask(context, argMap) Platform.JS -> executeJsTask(context, argMap) Platform.UNRECOGNIZED -> throw IllegalStateException( - "unrecognized platform: ${context.info}") + "unrecognized platform: ${context.info}" + ) } success = true } catch (ex: CompilationStatusException) { @@ -76,10 +77,11 @@ class KotlinBuilder @Inject internal constructor( private fun buildContext(args: List): Pair { check(args.isNotEmpty()) { "expected at least a single arg got: ${args.joinToString(" ")}" } val (flagFileName, primaryOutputPath, _) = - checkNotNull( - FLAGFILE_RE.matchEntire(args[0])) { "invalid flagfile ${args[0]}" }.destructured + checkNotNull( + FLAGFILE_RE.matchEntire(args[0]) + ) { "invalid flagfile ${args[0]}" }.destructured val argMap = - Files.readAllLines(Paths.get(flagFileName), StandardCharsets.UTF_8).let(ArgMaps::from) + Files.readAllLines(Paths.get(flagFileName), StandardCharsets.UTF_8).let(ArgMaps::from) val info = buildTaskInfo(argMap).also { it.primaryOutputPath = primaryOutputPath }.build() @@ -125,70 +127,70 @@ class KotlinBuilder @Inject internal constructor( TEST_ONLY("--testonly"); } - private enum class KotlinBuilderFlags(override val flag: String) : Flag { - MODULE_NAME("--kotlin_module_name"), - PASSTHROUGH_FLAGS("--kotlin_passthrough_flags"), - API_VERSION("--kotlin_api_version"), - LANGUAGE_VERSION("--kotlin_language_version"), - JVM_TARGET("--kotlin_jvm_target"), - OUTPUT_SRCJAR("--kotlin_output_srcjar"), - GENERATED_CLASSDIR("--kotlin_generated_classdir"), - FRIEND_PATHS("--kotlin_friend_paths"), - OUTPUT_JDEPS("--kotlin_output_jdeps"), - OUTPUT_JS_JAR("--kotlin_output_js_jar"), - JS_PASSTHROUGH_FLAGS("--kotlin_js_passthrough_flags"), - JS_LIBRARIES("--kotlin_js_libraries"), - DEBUG("--kotlin_debug_tags"), - TASK_ID("--kotlin_task_id"); - } + private enum class KotlinBuilderFlags(override val flag: String) : Flag { + MODULE_NAME("--kotlin_module_name"), + PASSTHROUGH_FLAGS("--kotlin_passthrough_flags"), + API_VERSION("--kotlin_api_version"), + LANGUAGE_VERSION("--kotlin_language_version"), + JVM_TARGET("--kotlin_jvm_target"), + OUTPUT_SRCJAR("--kotlin_output_srcjar"), + GENERATED_CLASSDIR("--kotlin_generated_classdir"), + FRIEND_PATHS("--kotlin_friend_paths"), + OUTPUT_JDEPS("--kotlin_output_jdeps"), + OUTPUT_JS_JAR("--kotlin_output_js_jar"), + JS_PASSTHROUGH_FLAGS("--kotlin_js_passthrough_flags"), + JS_LIBRARIES("--kotlin_js_libraries"), + DEBUG("--kotlin_debug_tags"), + TASK_ID("--kotlin_task_id"); + } private fun buildTaskInfo(argMap: ArgMap): CompilationTaskInfo.Builder = - with(CompilationTaskInfo.newBuilder()) { - addAllDebug(argMap.mandatory(KotlinBuilderFlags.DEBUG)) - - label = argMap.mandatorySingle(JavaBuilderFlags.TARGET_LABEL) - argMap.mandatorySingle(JavaBuilderFlags.RULE_KIND).split("_").also { - check(it.size == 3 && it[0] == "kt") { "invalid rule kind $it" } - platform = checkNotNull(Platform.valueOf(it[1].toUpperCase())) { - "unrecognized platform ${it[1]}" - } - ruleKind = checkNotNull(RuleKind.valueOf(it[2].toUpperCase())) { - "unrecognized rule kind ${it[2]}" - } + with(CompilationTaskInfo.newBuilder()) { + addAllDebug(argMap.mandatory(KotlinBuilderFlags.DEBUG)) + + label = argMap.mandatorySingle(JavaBuilderFlags.TARGET_LABEL) + argMap.mandatorySingle(JavaBuilderFlags.RULE_KIND).split("_").also { + check(it.size == 3 && it[0] == "kt") { "invalid rule kind $it" } + platform = checkNotNull(Platform.valueOf(it[1].toUpperCase())) { + "unrecognized platform ${it[1]}" } - moduleName = argMap.mandatorySingle(KotlinBuilderFlags.MODULE_NAME).also { - check(it.isNotBlank()) { "--kotlin_module_name should not be blank" } + ruleKind = checkNotNull(RuleKind.valueOf(it[2].toUpperCase())) { + "unrecognized rule kind ${it[2]}" } - passthroughFlags = argMap.optionalSingle(KotlinBuilderFlags.PASSTHROUGH_FLAGS) - argMap.optional(KotlinBuilderFlags.FRIEND_PATHS)?.let(::addAllFriendPaths) - toolchainInfoBuilder.commonBuilder.apiVersion = - argMap.mandatorySingle(KotlinBuilderFlags.API_VERSION) - toolchainInfoBuilder.commonBuilder.languageVersion = - argMap.mandatorySingle(KotlinBuilderFlags.LANGUAGE_VERSION) - this } + moduleName = argMap.mandatorySingle(KotlinBuilderFlags.MODULE_NAME).also { + check(it.isNotBlank()) { "--kotlin_module_name should not be blank" } + } + passthroughFlags = argMap.optionalSingle(KotlinBuilderFlags.PASSTHROUGH_FLAGS) + argMap.optional(KotlinBuilderFlags.FRIEND_PATHS)?.let(::addAllFriendPaths) + toolchainInfoBuilder.commonBuilder.apiVersion = + argMap.mandatorySingle(KotlinBuilderFlags.API_VERSION) + toolchainInfoBuilder.commonBuilder.languageVersion = + argMap.mandatorySingle(KotlinBuilderFlags.LANGUAGE_VERSION) + this + } private fun executeJsTask(context: CompilationTaskContext, argMap: ArgMap) = - buildJsTask(context.info, argMap).let { jsTask -> - context.whenTracing { printProto("js task input", jsTask) } - jsTaskExecutor.execute(context, jsTask) - } + buildJsTask(context.info, argMap).let { jsTask -> + context.whenTracing { printProto("js task input", jsTask) } + jsTaskExecutor.execute(context, jsTask) + } private fun buildJsTask(info: CompilationTaskInfo, argMap: ArgMap): JsCompilationTask = - with(JsCompilationTask.newBuilder()) { - this.info = info - with(inputsBuilder) { - addAllLibraries(argMap.mandatory(KotlinBuilderFlags.JS_LIBRARIES)) - addAllKotlinSources(argMap.mandatory(JavaBuilderFlags.SOURCES)) - } - with(outputsBuilder) { - js = argMap.mandatorySingle(JavaBuilderFlags.OUTPUT) - jar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_JS_JAR) - srcjar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_SRCJAR) - } - addAllPassThroughFlags(argMap.mandatory(KotlinBuilderFlags.JS_PASSTHROUGH_FLAGS)) - build() + with(JsCompilationTask.newBuilder()) { + this.info = info + with(inputsBuilder) { + addAllLibraries(argMap.mandatory(KotlinBuilderFlags.JS_LIBRARIES)) + addAllKotlinSources(argMap.mandatory(JavaBuilderFlags.SOURCES)) } + with(outputsBuilder) { + js = argMap.mandatorySingle(JavaBuilderFlags.OUTPUT) + jar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_JS_JAR) + srcjar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_SRCJAR) + } + addAllPassThroughFlags(argMap.mandatory(KotlinBuilderFlags.JS_PASSTHROUGH_FLAGS)) + build() + } private fun executeJvmTask(context: CompilationTaskContext, argMap: ArgMap) { val task = buildJvmTask(context.info, argMap) @@ -199,47 +201,44 @@ class KotlinBuilder @Inject internal constructor( } private fun buildJvmTask(info: CompilationTaskInfo, argMap: ArgMap): JvmCompilationTask = - JvmCompilationTask.newBuilder().let { root -> - root.info = info + JvmCompilationTask.newBuilder().let { root -> + root.info = info - with(root.outputsBuilder) { - jar = argMap.mandatorySingle(JavaBuilderFlags.OUTPUT) - srcjar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_SRCJAR) + with(root.outputsBuilder) { + jar = argMap.mandatorySingle(JavaBuilderFlags.OUTPUT) + srcjar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_SRCJAR) - argMap.optionalSingle(KotlinBuilderFlags.OUTPUT_JDEPS)?.apply { jdeps = this } - } + argMap.optionalSingle(KotlinBuilderFlags.OUTPUT_JDEPS)?.apply { jdeps = this } + } - with(root.directoriesBuilder) - { - classes = argMap.mandatorySingle(JavaBuilderFlags.CLASSDIR) - generatedClasses = argMap.mandatorySingle(KotlinBuilderFlags.GENERATED_CLASSDIR) - temp = argMap.mandatorySingle(JavaBuilderFlags.TEMPDIR) - generatedSources = argMap.mandatorySingle(JavaBuilderFlags.SOURCEGEN_DIR) - } + with(root.directoriesBuilder) { + classes = argMap.mandatorySingle(JavaBuilderFlags.CLASSDIR) + generatedClasses = argMap.mandatorySingle(KotlinBuilderFlags.GENERATED_CLASSDIR) + temp = argMap.mandatorySingle(JavaBuilderFlags.TEMPDIR) + generatedSources = argMap.mandatorySingle(JavaBuilderFlags.SOURCEGEN_DIR) + } - with(root.inputsBuilder) - { - addAllClasspath(argMap.mandatory(JavaBuilderFlags.CLASSPATH)) - putAllIndirectDependencies(argMap.labelDepMap(JavaBuilderFlags.DIRECT_DEPENDENCY)) - putAllIndirectDependencies(argMap.labelDepMap(JavaBuilderFlags.INDIRECT_DEPENDENCY)) - - addAllProcessors(argMap.optional(JavaBuilderFlags.PROCESSORS) ?: emptyList()) - addAllProcessorpaths(argMap.optional(JavaBuilderFlags.PROCESSOR_PATH) ?: emptyList()) - - argMap.optional(JavaBuilderFlags.SOURCES)?.iterator()?.partitionJvmSources( - { addKotlinSources(it) }, - { addJavaSources(it) } - ) - argMap.optional(JavaBuilderFlags.SOURCE_JARS)?.also { - addAllSourceJars(it) - } - } + with(root.inputsBuilder) { + addAllClasspath(argMap.mandatory(JavaBuilderFlags.CLASSPATH)) + putAllIndirectDependencies(argMap.labelDepMap(JavaBuilderFlags.DIRECT_DEPENDENCY)) + putAllIndirectDependencies(argMap.labelDepMap(JavaBuilderFlags.INDIRECT_DEPENDENCY)) - with(root.infoBuilder) - { - toolchainInfoBuilder.jvmBuilder.jvmTarget = - argMap.mandatorySingle(KotlinBuilderFlags.JVM_TARGET) + addAllProcessors(argMap.optional(JavaBuilderFlags.PROCESSORS) ?: emptyList()) + addAllProcessorpaths(argMap.optional(JavaBuilderFlags.PROCESSOR_PATH) ?: emptyList()) + + argMap.optional(JavaBuilderFlags.SOURCES)?.iterator()?.partitionJvmSources( + { addKotlinSources(it) }, + { addJavaSources(it) } + ) + argMap.optional(JavaBuilderFlags.SOURCE_JARS)?.also { + addAllSourceJars(it) } - root.build() } + + with(root.infoBuilder) { + toolchainInfoBuilder.jvmBuilder.jvmTarget = + argMap.mandatorySingle(KotlinBuilderFlags.JVM_TARGET) + } + root.build() + } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt index fa5dc45e8..d2e59178b 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt @@ -1,8 +1,8 @@ package io.bazel.kotlin.builder.tasks.js import io.bazel.kotlin.builder.toolchain.CompilationException -import io.bazel.kotlin.builder.toolchain.KotlinToolchain import io.bazel.kotlin.builder.toolchain.CompilationTaskContext +import io.bazel.kotlin.builder.toolchain.KotlinToolchain import io.bazel.kotlin.builder.utils.addAll import io.bazel.kotlin.builder.utils.jars.JarCreator import io.bazel.kotlin.builder.utils.jars.SourceJarCreator @@ -17,64 +17,64 @@ import javax.inject.Singleton @Singleton class Kotlin2JsTaskExecutor @Inject constructor( - private val invoker: KotlinToolchain.K2JSCompilerInvoker + private val invoker: KotlinToolchain.K2JSCompilerInvoker ) { - fun execute(context: CompilationTaskContext, task: JsCompilationTask) { - task.compile(context) + fun execute(context: CompilationTaskContext, task: JsCompilationTask) { + task.compile(context) - val jsPath = Paths.get(task.outputs.js) - val jsMetaFile = jsPath.resolveTwinVerified(".meta.js") - val jsDirectory = jsPath.parent.resolve(jsPath.toFile().nameWithoutExtension) - task.createJar(jsDirectory, listOf(jsPath, jsPath.resolveTwinVerified(".js.map"), jsMetaFile)) - // this mutates the jsPath file , so do it after creating the jar. - appendMetaToPrimary(jsPath, jsMetaFile) - task.createSourceJar() - } + val jsPath = Paths.get(task.outputs.js) + val jsMetaFile = jsPath.resolveTwinVerified(".meta.js") + val jsDirectory = jsPath.parent.resolve(jsPath.toFile().nameWithoutExtension) + task.createJar(jsDirectory, listOf(jsPath, jsPath.resolveTwinVerified(".js.map"), jsMetaFile)) + // this mutates the jsPath file , so do it after creating the jar. + appendMetaToPrimary(jsPath, jsMetaFile) + task.createSourceJar() + } - private fun JsCompilationTask.compile(context: CompilationTaskContext) { - val args = mutableListOf().also { - it.addAll(passThroughFlagsList) - it.addAll("-libraries", inputs.librariesList.joinToString(":")) - it.addAll("-output", outputs.js) - it.addAll(inputs.kotlinSourcesList) - } - context.whenTracing { printLines("js compile args", args) } - context.executeCompilerTask(args, invoker::compile) + private fun JsCompilationTask.compile(context: CompilationTaskContext) { + val args = mutableListOf().also { + it.addAll(passThroughFlagsList) + it.addAll("-libraries", inputs.librariesList.joinToString(":")) + it.addAll("-output", outputs.js) + it.addAll(inputs.kotlinSourcesList) } + context.whenTracing { printLines("js compile args", args) } + context.executeCompilerTask(args, invoker::compile) + } - private fun JsCompilationTask.createSourceJar() { - try { - SourceJarCreator(Paths.get(outputs.srcjar), false).also { creator -> - creator.addSources(inputs.kotlinSourcesList.map { Paths.get(it) }.stream()) - }.execute() - } catch (ex: Throwable) { - throw CompilationException("could not create source jar", ex) - } + private fun JsCompilationTask.createSourceJar() { + try { + SourceJarCreator(Paths.get(outputs.srcjar), false).also { creator -> + creator.addSources(inputs.kotlinSourcesList.map { Paths.get(it) }.stream()) + }.execute() + } catch (ex: Throwable) { + throw CompilationException("could not create source jar", ex) } + } - /** - * Append the meta file to the JS file. This is an accepted pattern, and it allows us to not have to export the - * meta.js file with the js. - */ - private fun appendMetaToPrimary(jsPath: Path, jsMetaFile: Path) { - try { - FileOutputStream(jsPath.toFile(), true).use { Files.copy(jsMetaFile, it) } - } catch (ex: Throwable) { - throw CompilationException("could not normalize js file", ex) - } + /** + * Append the meta file to the JS file. This is an accepted pattern, and it allows us to not have to export the + * meta.js file with the js. + */ + private fun appendMetaToPrimary(jsPath: Path, jsMetaFile: Path) { + try { + FileOutputStream(jsPath.toFile(), true).use { Files.copy(jsMetaFile, it) } + } catch (ex: Throwable) { + throw CompilationException("could not normalize js file", ex) } + } - private fun JsCompilationTask.createJar(jsDirectoryPath: Path, rootEntries: List) { - try { - val outputJarPath = Paths.get(outputs.jar) + private fun JsCompilationTask.createJar(jsDirectoryPath: Path, rootEntries: List) { + try { + val outputJarPath = Paths.get(outputs.jar) - JarCreator(outputJarPath).also { creator -> - creator.addDirectory(jsDirectoryPath) - creator.addRootEntries(rootEntries.map { it.toString() }) - creator.execute() - } - } catch (ex: Throwable) { - throw CompilationException("error creating js jar", ex) - } + JarCreator(outputJarPath).also { creator -> + creator.addDirectory(jsDirectoryPath) + creator.addRootEntries(rootEntries.map { it.toString() }) + creator.execute() + } + } catch (ex: Throwable) { + throw CompilationException("error creating js jar", ex) } -} \ No newline at end of file + } +} diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JDepsGenerator.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JDepsGenerator.kt index d544d39ae..e4bc72a55 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JDepsGenerator.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JDepsGenerator.kt @@ -33,53 +33,54 @@ import javax.inject.Singleton @Singleton internal class JDepsGenerator @Inject constructor( - toolchain: KotlinToolchain, - private val invoker: KotlinToolchain.JDepsInvoker + toolchain: KotlinToolchain, + private val invoker: KotlinToolchain.JDepsInvoker ) { - private val isKotlinImplicit = JdepsParser.pathSuffixMatchingPredicate( - toolchain.kotlinHome.resolveVerified("lib").toPath(), *toolchain.kotlinStandardLibraries.toTypedArray() - ) + private val isKotlinImplicit = JdepsParser.pathSuffixMatchingPredicate( + toolchain.kotlinHome.resolveVerified("lib").toPath(), + *toolchain.kotlinStandardLibraries.toTypedArray() + ) - fun generateJDeps(command: JvmCompilationTask) { - val jdepsContent = - if (command.inputs.classpathList.isEmpty()) { - Deps.Dependencies.newBuilder().let { - it.ruleLabel = command.info.label - it.build() - } - } else { - ByteArrayOutputStream().use { out -> - PrintWriter(out).use { writer -> - val joinedClasspath = command.inputs.joinedClasspath - val version = System.getProperty("java.version").majorJavaVersion() - val multiRelease = - if (version < 9) arrayOf() else arrayOf("--multi-release", "base") - val jarPath = command.outputs.jar - val args = multiRelease + arrayOf("-v", "-cp", joinedClasspath, jarPath) - val res = invoker.run(args, writer) - out.toByteArray().inputStream().bufferedReader().readLines().let { - if (res != 0) { - throw CompilationStatusException("could not run jdeps tool", res, it) - } else try { - JdepsParser.parse( - command.info.label, - jarPath, - command.inputs.classpathList, - it, - isKotlinImplicit - ) - } catch (e: Exception) { - throw CompilationException("error reading or parsing jdeps file", e.rootCause) - } - } - } - } + fun generateJDeps(command: JvmCompilationTask) { + val jdepsContent = + if (command.inputs.classpathList.isEmpty()) { + Deps.Dependencies.newBuilder().let { + it.ruleLabel = command.info.label + it.build() + } + } else { + ByteArrayOutputStream().use { out -> + PrintWriter(out).use { writer -> + val joinedClasspath = command.inputs.joinedClasspath + val version = System.getProperty("java.version").majorJavaVersion() + val multiRelease = + if (version < 9) arrayOf() else arrayOf("--multi-release", "base") + val jarPath = command.outputs.jar + val args = multiRelease + arrayOf("-v", "-cp", joinedClasspath, jarPath) + val res = invoker.run(args, writer) + out.toByteArray().inputStream().bufferedReader().readLines().let { + if (res != 0) { + throw CompilationStatusException("could not run jdeps tool", res, it) + } else try { + JdepsParser.parse( + command.info.label, + jarPath, + command.inputs.classpathList, + it, + isKotlinImplicit + ) + } catch (e: Exception) { + throw CompilationException("error reading or parsing jdeps file", e.rootCause) + } } - Paths.get(command.outputs.jdeps).also { - Files.deleteIfExists(it) - FileOutputStream(Files.createFile(it).toFile()).use(jdepsContent::writeTo) + } } + } + Paths.get(command.outputs.jdeps).also { + Files.deleteIfExists(it) + FileOutputStream(Files.createFile(it).toFile()).use(jdepsContent::writeTo) } + } } /** @@ -91,7 +92,7 @@ internal class JDepsGenerator @Inject constructor( * minor version as the major one. Otherwise, it uses the first term as the major version. */ private fun String.majorJavaVersion(): Int { - val (major, minor) = this.trim().split('.') - val parsedMajor = Integer.parseInt(major) - return if (parsedMajor == 1) Integer.parseInt(minor) else parsedMajor + val (major, minor) = this.trim().split('.') + val parsedMajor = Integer.parseInt(major) + return if (parsedMajor == 1) Integer.parseInt(minor) else parsedMajor } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt index d006026fa..4ad938e30 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt @@ -15,8 +15,8 @@ */ package io.bazel.kotlin.builder.tasks.jvm -import io.bazel.kotlin.builder.toolchain.KotlinToolchain import io.bazel.kotlin.builder.toolchain.CompilationTaskContext +import io.bazel.kotlin.builder.toolchain.KotlinToolchain import io.bazel.kotlin.builder.utils.addAll import io.bazel.kotlin.builder.utils.joinedClasspath import io.bazel.kotlin.model.JvmCompilationTask @@ -27,35 +27,36 @@ import javax.inject.Singleton @Singleton internal class JavaCompiler @Inject constructor( - private val javacInvoker: KotlinToolchain.JavacInvoker + private val javacInvoker: KotlinToolchain.JavacInvoker ) { - companion object { - /** - * Separator for a directory in the classpath. - */ - private val DIR_SEP = "${File.separatorChar}${File.pathSeparator}" - } - fun compile(context: CompilationTaskContext, command: JvmCompilationTask) { - val i = command.inputs - val d = command.directories - if (i.javaSourcesList.isNotEmpty()) { - val args = mutableListOf( - "-cp", "${d.classes}$DIR_SEP${d.temp}$DIR_SEP${i.joinedClasspath}", - "-d", d.classes - ).also { - it.addAll( - // Kotlin takes care of annotation processing. - "-proc:none", - // Disable option linting, it will complain about the source. - "-Xlint:-options", - "-source", command.info.toolchainInfo.jvm.jvmTarget, - "-target", command.info.toolchainInfo.jvm.jvmTarget - ) - it.addAll(i.javaSourcesList) - } - context.executeCompilerTask(args, { a, pw -> - javacInvoker.compile(a, PrintWriter(pw)) - }) - } + companion object { + /** + * Separator for a directory in the classpath. + */ + private val DIR_SEP = "${File.separatorChar}${File.pathSeparator}" + } + + fun compile(context: CompilationTaskContext, command: JvmCompilationTask) { + val i = command.inputs + val d = command.directories + if (i.javaSourcesList.isNotEmpty()) { + val args = mutableListOf( + "-cp", "${d.classes}$DIR_SEP${d.temp}$DIR_SEP${i.joinedClasspath}", + "-d", d.classes + ).also { + it.addAll( + // Kotlin takes care of annotation processing. + "-proc:none", + // Disable option linting, it will complain about the source. + "-Xlint:-options", + "-source", command.info.toolchainInfo.jvm.jvmTarget, + "-target", command.info.toolchainInfo.jvm.jvmTarget + ) + it.addAll(i.javaSourcesList) + } + context.executeCompilerTask(args, { a, pw -> + javacInvoker.compile(a, PrintWriter(pw)) + }) } -} \ No newline at end of file + } +} diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParser.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParser.kt index fa45b12d9..c1934cdea 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParser.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParser.kt @@ -18,119 +18,128 @@ package io.bazel.kotlin.builder.tasks.jvm import com.google.devtools.build.lib.view.proto.Deps import java.nio.file.Path import java.nio.file.Paths -import java.util.* +import java.util.HashMap +import java.util.HashSet import java.util.function.Predicate -internal class JdepsParser private constructor(private val filename: String, private val isImplicit: Predicate) { - private val packageSuffix: String = " ($filename)" +internal class JdepsParser private constructor( + private val filename: String, + private val isImplicit: Predicate +) { + private val packageSuffix: String = " ($filename)" - private val depMap = HashMap() - private val packages = HashSet() + private val depMap = HashMap() + private val packages = HashSet() - private var mode = Mode.COLLECT_DEPS + private var mode = Mode.COLLECT_DEPS - private fun consumeJarLine(classJarPath: String, kind: Deps.Dependency.Kind) { - val path = Paths.get(classJarPath) + private fun consumeJarLine(classJarPath: String, kind: Deps.Dependency.Kind) { + val path = Paths.get(classJarPath) - // ignore absolute files, -- jdk jar paths etc. - // only process jar files - if (!(path.isAbsolute || !classJarPath.endsWith(".jar"))) { - val entry = depMap.computeIfAbsent(classJarPath) { - val depBuilder = Deps.Dependency.newBuilder() - depBuilder.path = classJarPath - depBuilder.kind = kind + // ignore absolute files, -- jdk jar paths etc. + // only process jar files + if (!(path.isAbsolute || !classJarPath.endsWith(".jar"))) { + val entry = depMap.computeIfAbsent(classJarPath) { + val depBuilder = Deps.Dependency.newBuilder() + depBuilder.path = classJarPath + depBuilder.kind = kind - if (isImplicit.test(classJarPath)) { - depBuilder.kind = Deps.Dependency.Kind.IMPLICIT - } - depBuilder - } - - // don't flip an implicit dep. - if (entry.kind != Deps.Dependency.Kind.IMPLICIT) { - entry.kind = kind - } + if (isImplicit.test(classJarPath)) { + depBuilder.kind = Deps.Dependency.Kind.IMPLICIT } - } + depBuilder + } - private enum class Mode { - COLLECT_DEPS, - DETERMINE_JDK, - COLLECT_PACKAGES_JDK8, - COLLECT_PACKAGES_JDK9 + // don't flip an implicit dep. + if (entry.kind != Deps.Dependency.Kind.IMPLICIT) { + entry.kind = kind + } } + } - // maybe simplify this by tokenizing on whitespace and arrows. - private fun processLine(line: String) { - val trimmedLine = line.trim { it <= ' ' } - when (mode) { - Mode.COLLECT_DEPS -> if (!line.startsWith(" ")) { - val parts = line.split(" -> ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() - if (parts.size == 2) { - if (parts[0] != filename) { - throw RuntimeException("should only get dependencies for dep: $filename") - } - consumeJarLine(parts[1], Deps.Dependency.Kind.EXPLICIT) - } - } else { - mode = Mode.DETERMINE_JDK - processLine(line) - } - Mode.DETERMINE_JDK -> { - mode = Mode.COLLECT_PACKAGES_JDK8 - if (!line.endsWith(packageSuffix)) { - mode = Mode.COLLECT_PACKAGES_JDK9 - } - processLine(line) - } - Mode.COLLECT_PACKAGES_JDK8 -> when { - trimmedLine.endsWith(packageSuffix) -> packages.add(trimmedLine.substring(0, trimmedLine.length - packageSuffix.length)) - trimmedLine.startsWith("-> ") -> { - // ignore package detail lines, in the jdk8 format these start with arrows. - } - else -> throw RuntimeException("unexpected line while collecting packages: $line") - } - Mode.COLLECT_PACKAGES_JDK9 -> { - val pkg = trimmedLine.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() - packages.add(pkg[0]) - } + private enum class Mode { + COLLECT_DEPS, + DETERMINE_JDK, + COLLECT_PACKAGES_JDK8, + COLLECT_PACKAGES_JDK9 + } + + // maybe simplify this by tokenizing on whitespace and arrows. + private fun processLine(line: String) { + val trimmedLine = line.trim { it <= ' ' } + when (mode) { + Mode.COLLECT_DEPS -> if (!line.startsWith(" ")) { + val parts = line.split(" -> ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + if (parts.size == 2) { + if (parts[0] != filename) { + throw RuntimeException("should only get dependencies for dep: $filename") + } + consumeJarLine(parts[1], Deps.Dependency.Kind.EXPLICIT) + } + } else { + mode = Mode.DETERMINE_JDK + processLine(line) + } + Mode.DETERMINE_JDK -> { + mode = Mode.COLLECT_PACKAGES_JDK8 + if (!line.endsWith(packageSuffix)) { + mode = Mode.COLLECT_PACKAGES_JDK9 } + processLine(line) + } + Mode.COLLECT_PACKAGES_JDK8 -> when { + trimmedLine.endsWith(packageSuffix) -> packages.add( + trimmedLine.substring( + 0, + trimmedLine.length - packageSuffix.length + ) + ) + trimmedLine.startsWith("-> ") -> { + // ignore package detail lines, in the jdk8 format these start with arrows. + } + else -> throw RuntimeException("unexpected line while collecting packages: $line") + } + Mode.COLLECT_PACKAGES_JDK9 -> { + val pkg = trimmedLine.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + packages.add(pkg[0]) + } } + } - companion object { - fun pathSuffixMatchingPredicate(directory: Path, vararg jars: String): Predicate { - val suffixes = jars.map { directory.resolve(it).toString() } - return Predicate { jar -> - for (implicitJarsEnding in suffixes) { - if (jar.endsWith(implicitJarsEnding)) { - return@Predicate true - } - } - false - } + companion object { + fun pathSuffixMatchingPredicate(directory: Path, vararg jars: String): Predicate { + val suffixes = jars.map { directory.resolve(it).toString() } + return Predicate { jar -> + for (implicitJarsEnding in suffixes) { + if (jar.endsWith(implicitJarsEnding)) { + return@Predicate true + } } + false + } + } - fun parse( - label: String, - jarFile: String, - classPath: MutableList, - lines: List, - isImplicit: Predicate - ): Deps.Dependencies { - val filename = Paths.get(jarFile).fileName.toString() - val jdepsParser = JdepsParser(filename, isImplicit) - classPath.forEach { x -> jdepsParser.consumeJarLine(x, Deps.Dependency.Kind.UNUSED) } - lines.forEach { jdepsParser.processLine(it) } + fun parse( + label: String, + jarFile: String, + classPath: MutableList, + lines: List, + isImplicit: Predicate + ): Deps.Dependencies { + val filename = Paths.get(jarFile).fileName.toString() + val jdepsParser = JdepsParser(filename, isImplicit) + classPath.forEach { x -> jdepsParser.consumeJarLine(x, Deps.Dependency.Kind.UNUSED) } + lines.forEach { jdepsParser.processLine(it) } - val rootBuilder = Deps.Dependencies.newBuilder() - rootBuilder.success = false - rootBuilder.ruleLabel = label + val rootBuilder = Deps.Dependencies.newBuilder() + rootBuilder.success = false + rootBuilder.ruleLabel = label - rootBuilder.addAllContainedPackage(jdepsParser.packages) - jdepsParser.depMap.values.forEach { b -> rootBuilder.addDependency(b.build()) } + rootBuilder.addAllContainedPackage(jdepsParser.packages) + jdepsParser.depMap.values.forEach { b -> rootBuilder.addDependency(b.build()) } - rootBuilder.success = true - return rootBuilder.build() - } + rootBuilder.success = true + return rootBuilder.build() } + } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt index 06f654423..830ab0eca 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt @@ -38,8 +38,8 @@ class KotlinJvmTaskExecutor @Inject internal constructor( ) { fun execute(context: CompilationTaskContext, task: JvmCompilationTask) { val preprocessedTask = task - .preProcessingSteps(context) - .runAnnotationProcessors(context, pluginArgsEncoder, compiler) + .preProcessingSteps(context) + .runAnnotationProcessors(context, pluginArgsEncoder, compiler) context.execute("compile classes") { preprocessedTask.apply { diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt index 72cb65e3a..72a95ae06 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt @@ -37,27 +37,27 @@ import java.nio.file.Paths * Return a list with the common arguments. */ internal fun JvmCompilationTask.commonArgs(): CompilationArgs = baseArgs() - .absolutePaths(info.friendPathsList) { - "-Xfriend-paths=${it.joinToString(X_FRIENDS_PATH_SEPARATOR)}" - } - .flag("-d", directories.classes) - .givenNotEmpty(info.passthroughFlags) { it.split(" ") } + .absolutePaths(info.friendPathsList) { + "-Xfriend-paths=${it.joinToString(X_FRIENDS_PATH_SEPARATOR)}" + } + .flag("-d", directories.classes) + .givenNotEmpty(info.passthroughFlags) { it.split(" ") } internal fun JvmCompilationTask.baseArgs(): CompilationArgs = CompilationArgs() - .flag("-cp").absolutePaths(inputs.classpathList) { - it.map(Path::toString).joinToString(File.pathSeparator) - } - .flag("-api-version", info.toolchainInfo.common.apiVersion) - .flag("-language-version", info.toolchainInfo.common.languageVersion) - .flag("-jvm-target", info.toolchainInfo.jvm.jvmTarget) - .flag("-module-name", info.moduleName) + .flag("-cp").absolutePaths(inputs.classpathList) { + it.map(Path::toString).joinToString(File.pathSeparator) + } + .flag("-api-version", info.toolchainInfo.common.apiVersion) + .flag("-language-version", info.toolchainInfo.common.languageVersion) + .flag("-jvm-target", info.toolchainInfo.jvm.jvmTarget) + .flag("-module-name", info.moduleName) internal fun JvmCompilationTask.preProcessingSteps(context: CompilationTaskContext): JvmCompilationTask { ensureDirectories( - directories.temp, - directories.generatedSources, - directories.generatedClasses, - directories.classes + directories.temp, + directories.generatedSources, + directories.generatedClasses, + directories.classes ) return context.execute("expand sources") { expandWithSourceJarSources() } } @@ -66,20 +66,20 @@ internal fun JvmCompilationTask.produceSourceJar() { Paths.get(outputs.srcjar).also { sourceJarPath -> Files.createFile(sourceJarPath) SourceJarCreator( - sourceJarPath + sourceJarPath ).also { creator -> // This check asserts that source jars were unpacked if present. check( - inputs.sourceJarsList.isEmpty() || - Files.exists(Paths.get(directories.temp).resolve("_srcjars")) + inputs.sourceJarsList.isEmpty() || + Files.exists(Paths.get(directories.temp).resolve("_srcjars")) ) listOf( - // Any (input) source jars should already have been expanded so do not add them here. - inputs.javaSourcesList.stream(), - inputs.kotlinSourcesList.stream() + // Any (input) source jars should already have been expanded so do not add them here. + inputs.javaSourcesList.stream(), + inputs.kotlinSourcesList.stream() ).stream() - .flatMap { it.map { p -> Paths.get(p) } } - .also { creator.addSources(it) } + .flatMap { it.map { p -> Paths.get(p) } } + .also { creator.addSources(it) } creator.execute() } } @@ -93,24 +93,23 @@ internal fun JvmCompilationTask.runAnnotationProcessors( if (inputs.processorsList.isEmpty()) { return this } else { - return context.execute("kapt (${inputs.processorsList.joinToString(", ")})") - { + return context.execute("kapt (${inputs.processorsList.joinToString(", ")})") { commonArgs() - .values(pluginArgsEncoder.encode(context, this)) - .values(inputs.kotlinSourcesList) - .values(inputs.javaSourcesList).list().let { args -> - context.executeCompilerTask( - args, - compiler::compile, - printOnSuccess = context.whenTracing { false } ?: true) - }.let { outputLines -> - // if tracing is enabled the output should be formatted in a special way, if we aren't - // tracing then any compiler output would make it's way to the console as is. - context.whenTracing { - printLines("kapt output", outputLines) - } - return@let expandWithGeneratedSources() + .values(pluginArgsEncoder.encode(context, this)) + .values(inputs.kotlinSourcesList) + .values(inputs.javaSourcesList).list().let { args -> + context.executeCompilerTask( + args, + compiler::compile, + printOnSuccess = context.whenTracing { false } ?: true) + }.let { outputLines -> + // if tracing is enabled the output should be formatted in a special way, if we aren't + // tracing then any compiler output would make it's way to the console as is. + context.whenTracing { + printLines("kapt output", outputLines) } + return@let expandWithGeneratedSources() + } } } } @@ -119,16 +118,16 @@ internal fun JvmCompilationTask.runAnnotationProcessors( * Produce the primary output jar. */ internal fun JvmCompilationTask.createOutputJar() = - JarCreator( - path = Paths.get(outputs.jar), - normalize = true, - verbose = false - ).also { - it.addDirectory(Paths.get(directories.classes)) - it.addDirectory(Paths.get(directories.generatedClasses)) - it.setJarOwner(info.label, info.bazelRuleKind) - it.execute() - } + JarCreator( + path = Paths.get(outputs.jar), + normalize = true, + verbose = false + ).also { + it.addDirectory(Paths.get(directories.classes)) + it.addDirectory(Paths.get(directories.generatedClasses)) + it.setJarOwner(info.label, info.bazelRuleKind) + it.execute() + } /** * Compiles Kotlin sources to classes. Does not compile Java sources. @@ -138,53 +137,53 @@ internal fun JvmCompilationTask.compileKotlin( compiler: KotlinToolchain.KotlincInvoker, printOnFail: Boolean = true ) = - commonArgs() - .values(inputs.javaSourcesList) - .values(inputs.kotlinSourcesList) - .list().let { args -> - return@let context.executeCompilerTask(args, compiler::compile, printOnFail = printOnFail) - } + commonArgs() + .values(inputs.javaSourcesList) + .values(inputs.kotlinSourcesList) + .list().let { args -> + return@let context.executeCompilerTask(args, compiler::compile, printOnFail = printOnFail) + } /** * If any srcjars were provided expand the jars sources and create a new [JvmCompilationTask] with the * Java and Kotlin sources merged in. */ internal fun JvmCompilationTask.expandWithSourceJarSources(): JvmCompilationTask = - if (inputs.sourceJarsList.isEmpty()) - this - else expandWithSources( - SourceJarExtractor( - destDir = Paths.get(directories.temp).resolve("_srcjars"), - fileMatcher = IS_JVM_SOURCE_FILE - ).also { - it.jarFiles.addAll(inputs.sourceJarsList.map { p -> Paths.get(p) }) - it.execute() - }.sourcesList.iterator() - ) + if (inputs.sourceJarsList.isEmpty()) + this + else expandWithSources( + SourceJarExtractor( + destDir = Paths.get(directories.temp).resolve("_srcjars"), + fileMatcher = IS_JVM_SOURCE_FILE + ).also { + it.jarFiles.addAll(inputs.sourceJarsList.map { p -> Paths.get(p) }) + it.execute() + }.sourcesList.iterator() + ) /** * Create a new [JvmCompilationTask] with sources found in the generatedSources directory. This should be run after * annotation processors have been run. */ internal fun JvmCompilationTask.expandWithGeneratedSources(): JvmCompilationTask = - expandWithSources( - File(directories.generatedSources).walkTopDown() - .filter { it.isFile } - .map { it.path } - .iterator() - ) + expandWithSources( + File(directories.generatedSources).walkTopDown() + .filter { it.isFile } + .map { it.path } + .iterator() + ) private fun JvmCompilationTask.expandWithSources(sources: Iterator): JvmCompilationTask = - updateBuilder { builder -> - sources.partitionJvmSources( - { builder.inputsBuilder.addKotlinSources(it) }, - { builder.inputsBuilder.addJavaSources(it) }) - } + updateBuilder { builder -> + sources.partitionJvmSources( + { builder.inputsBuilder.addKotlinSources(it) }, + { builder.inputsBuilder.addJavaSources(it) }) + } private fun JvmCompilationTask.updateBuilder( block: (JvmCompilationTask.Builder) -> Unit ): JvmCompilationTask = - toBuilder().let { - block(it) - it.build() - } + toBuilder().let { + block(it) + it.build() + } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/BUILD.bazel b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/BUILD.bazel index b9c66dc22..24c6bb483 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/BUILD.bazel +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/BUILD.bazel @@ -20,11 +20,11 @@ kt_bootstrap_library( ]), visibility = ["//src:__subpackages__"], deps = [ + "//src/main/kotlin/io/bazel/kotlin/builder/utils", "//src/main/protobuf:kotlin_model_java_proto", "@com_github_jetbrains_kotlin//:kotlin-preloader", "@kotlin_rules_maven//:com_google_protobuf_protobuf_java", "@kotlin_rules_maven//:com_google_protobuf_protobuf_java_util", "@kotlin_rules_maven//:javax_inject_javax_inject", - "//src/main/kotlin/io/bazel/kotlin/builder/utils:utils", ], ) diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt index 42c04a6b1..fc0107b99 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt @@ -25,148 +25,156 @@ import java.io.PrintStream import java.nio.file.Paths class CompilationTaskContext(val info: CompilationTaskInfo, private val out: PrintStream) { - private val start = System.currentTimeMillis() - private val executionRoot: String = Paths.get( - System.getProperty("user.dir") - ).toAbsolutePath().toString() + File.separator - private var timings: MutableList? - private var level = -1 - private val isTracing: Boolean + private val start = System.currentTimeMillis() + private val executionRoot: String = Paths.get( + System.getProperty("user.dir") + ).toAbsolutePath().toString() + File.separator + private var timings: MutableList? + private var level = -1 + private val isTracing: Boolean - init { - val debugging = info.debugList.toSet() - timings = if (debugging.contains("timings")) mutableListOf() else null - isTracing = debugging.contains("trace") - } + init { + val debugging = info.debugList.toSet() + timings = if (debugging.contains("timings")) mutableListOf() else null + isTracing = debugging.contains("trace") + } - fun reportUnhandledException(throwable: Throwable) { - throwable.printStackTrace(out) - } + fun reportUnhandledException(throwable: Throwable) { + throwable.printStackTrace(out) + } - @Suppress("unused") - fun print(msg: String) { - out.println(msg) - } + @Suppress("unused") + fun print(msg: String) { + out.println(msg) + } - /** - * Print a list of debugging lines. - * - * @param header a header string - * @param lines a list of lines to print out - * @param prefix a prefix to add to each line - * @param filterEmpty if empty lines should be discarded or not - */ - fun printLines(header: String, lines: List, prefix: String = "| ", filterEmpty: Boolean = false) { - check(header.isNotEmpty()) - out.println(if (header.endsWith(":")) header else "$header:") - lines.forEach { - if (it.isNotEmpty() || !filterEmpty) { - out.println("$prefix$it") - } - } - out.println() + /** + * Print a list of debugging lines. + * + * @param header a header string + * @param lines a list of lines to print out + * @param prefix a prefix to add to each line + * @param filterEmpty if empty lines should be discarded or not + */ + fun printLines( + header: String, + lines: List, + prefix: String = "| ", + filterEmpty: Boolean = false + ) { + check(header.isNotEmpty()) + out.println(if (header.endsWith(":")) header else "$header:") + lines.forEach { + if (it.isNotEmpty() || !filterEmpty) { + out.println("$prefix$it") + } } + out.println() + } - fun whenTracing(block: CompilationTaskContext.() -> T): T? { - return if (isTracing) { - block() - } else null - } + fun whenTracing(block: CompilationTaskContext.() -> T): T? { + return if (isTracing) { + block() + } else null + } - /** - * Print a proto message if debugging is enabled for the task. - */ - fun printProto(header: String, msg: MessageOrBuilder) { - printLines(header, TextFormat.printToString(msg).split("\n"), filterEmpty = true) - } + /** + * Print a proto message if debugging is enabled for the task. + */ + fun printProto(header: String, msg: MessageOrBuilder) { + printLines(header, TextFormat.printToString(msg).split("\n"), filterEmpty = true) + } - /** - * This method normalizes and reports the output from the Kotlin compiler. - */ - fun printCompilerOutput(lines: List) { - lines.map(::trimExecutionRootPrefix).forEach(out::println) - } + /** + * This method normalizes and reports the output from the Kotlin compiler. + */ + fun printCompilerOutput(lines: List) { + lines.map(::trimExecutionRootPrefix).forEach(out::println) + } - private fun trimExecutionRootPrefix(toPrint: String): String { - // trim off the workspace component - return if (toPrint.startsWith(executionRoot)) { - toPrint.replaceFirst(executionRoot, "") - } else toPrint - } + private fun trimExecutionRootPrefix(toPrint: String): String { + // trim off the workspace component + return if (toPrint.startsWith(executionRoot)) { + toPrint.replaceFirst(executionRoot, "") + } else toPrint + } - /** - * Execute a compilation task. - * - * @throws CompilationStatusException if the compiler returns a status of anything but zero. - * @param args the compiler command line switches - * @param printOnFail if this is true the output will be printed if the task fails else the caller is responsible - * for logging it by catching the [CompilationStatusException] exception. - * @param compile the compilation method. - */ - fun executeCompilerTask( - args: List, - compile: (Array, PrintStream) -> Int, - printOnFail: Boolean = true, - printOnSuccess: Boolean = true - ): List { - val outputStream = ByteArrayOutputStream() - val ps = PrintStream(outputStream) - val result = compile(args.toTypedArray(), ps) - val output = ByteArrayInputStream(outputStream.toByteArray()).bufferedReader().readLines() - if (result != 0) { - if (printOnFail) { - printCompilerOutput(output) - } - throw CompilationStatusException("compile phase failed", result, output) - } else if (printOnSuccess) { - printCompilerOutput(output) - } - return output + /** + * Execute a compilation task. + * + * @throws CompilationStatusException if the compiler returns a status of anything but zero. + * @param args the compiler command line switches + * @param printOnFail if this is true the output will be printed if the task fails else the caller is responsible + * for logging it by catching the [CompilationStatusException] exception. + * @param compile the compilation method. + */ + fun executeCompilerTask( + args: List, + compile: (Array, PrintStream) -> Int, + printOnFail: Boolean = true, + printOnSuccess: Boolean = true + ): List { + val outputStream = ByteArrayOutputStream() + val ps = PrintStream(outputStream) + val result = compile(args.toTypedArray(), ps) + val output = ByteArrayInputStream(outputStream.toByteArray()).bufferedReader().readLines() + if (result != 0) { + if (printOnFail) { + printCompilerOutput(output) + } + throw CompilationStatusException("compile phase failed", result, output) + } else if (printOnSuccess) { + printCompilerOutput(output) } + return output + } - /** - * Runs a task and records the timings. - */ - fun execute(name: String, task: () -> T): T = execute({ name }, task) + /** + * Runs a task and records the timings. + */ + fun execute(name: String, task: () -> T): T = execute({ name }, task) - /** - * Runs a task and records the timings. - */ - @Suppress("MemberVisibilityCanBePrivate") - fun execute(name: () -> String, task: () -> T): T { - return if (timings == null) { - task() - } else pushTimedTask(name(), task) - } + /** + * Runs a task and records the timings. + */ + @Suppress("MemberVisibilityCanBePrivate") + fun execute(name: () -> String, task: () -> T): T { + return if (timings == null) { + task() + } else pushTimedTask(name(), task) + } - private inline fun pushTimedTask(name: String, task: () -> T): T { - level += 1 - val previousTimings = timings - timings = mutableListOf() - return try { - System.currentTimeMillis().let { start -> - task().also { - val stop = System.currentTimeMillis() - previousTimings!! += "${" ".repeat(level)} * $name: ${stop - start} ms" - previousTimings.addAll(timings!!) - } - } - } finally { - level -= 1 - timings = previousTimings + private inline fun pushTimedTask(name: String, task: () -> T): T { + level += 1 + val previousTimings = timings + timings = mutableListOf() + return try { + System.currentTimeMillis().let { start -> + task().also { + val stop = System.currentTimeMillis() + previousTimings!! += "${" ".repeat(level)} * $name: ${stop - start} ms" + previousTimings.addAll(timings!!) } + } + } finally { + level -= 1 + timings = previousTimings } + } - /** - * This method should be called at the end of builder invocation. - * - * @param successful true if the task finished successfully. - */ - fun finalize(successful: Boolean) { - if (successful) { - timings?.also { - printLines("Task timings for ${info.label} (total: ${System.currentTimeMillis() - start} ms)", it) - } - } + /** + * This method should be called at the end of builder invocation. + * + * @param successful true if the task finished successfully. + */ + fun finalize(successful: Boolean) { + if (successful) { + timings?.also { + printLines( + "Task timings for ${info.label} (total: ${System.currentTimeMillis() - start} ms)", + it + ) + } } + } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinCompilerPluginArgsEncoder.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinCompilerPluginArgsEncoder.kt index f141159bc..770f07ac0 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinCompilerPluginArgsEncoder.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinCompilerPluginArgsEncoder.kt @@ -15,7 +15,6 @@ */ package io.bazel.kotlin.builder.toolchain - import io.bazel.kotlin.model.JvmCompilationTask import java.io.ByteArrayOutputStream import java.io.ObjectOutputStream @@ -23,89 +22,89 @@ import java.util.Base64 // TODO(hs) move the kapt specific stuff to the JVM package. class KotlinCompilerPluginArgsEncoder( - private val jarPath: String, - private val pluginId: String + private val jarPath: String, + private val pluginId: String ) { - companion object { - private fun encodeMap(options: Map): String { - val os = ByteArrayOutputStream() - val oos = ObjectOutputStream(os) - - oos.writeInt(options.size) - for ((key, value) in options.entries) { - oos.writeUTF(key) - oos.writeUTF(value) - } + companion object { + private fun encodeMap(options: Map): String { + val os = ByteArrayOutputStream() + val oos = ObjectOutputStream(os) - oos.flush() - return Base64.getEncoder().encodeToString(os.toByteArray()) - } + oos.writeInt(options.size) + for ((key, value) in options.entries) { + oos.writeUTF(key) + oos.writeUTF(value) + } - private fun encodeMultiMap(options: Map>): String { - val os = ByteArrayOutputStream() - val oos = ObjectOutputStream(os) + oos.flush() + return Base64.getEncoder().encodeToString(os.toByteArray()) + } - oos.writeInt(options.size) - for ((key, values) in options.entries) { - oos.writeUTF(key) + private fun encodeMultiMap(options: Map>): String { + val os = ByteArrayOutputStream() + val oos = ObjectOutputStream(os) - oos.writeInt(values.size) - for (value in values) { - oos.writeUTF(value) - } - } + oos.writeInt(options.size) + for ((key, values) in options.entries) { + oos.writeUTF(key) - oos.flush() - return Base64.getEncoder().encodeToString(os.toByteArray()) + oos.writeInt(values.size) + for (value in values) { + oos.writeUTF(value) } - } + } - /** - * Plugin using the undocumented encoding format for kapt3 - */ - inner class PluginArgs internal constructor() { - private val tally = mutableMapOf>() + oos.flush() + return Base64.getEncoder().encodeToString(os.toByteArray()) + } + } - operator fun set(key: String, value: String) { - check(tally[key] == null) { "value allready set" } - tally[key] = mutableListOf(value) - } + /** + * Plugin using the undocumented encoding format for kapt3 + */ + inner class PluginArgs internal constructor() { + private val tally = mutableMapOf>() - fun bindMulti(key: String, value: String) { - tally[key].also { if (it != null) it.add(value) else this[key] = value } - } + operator fun set(key: String, value: String) { + check(tally[key] == null) { "value allready set" } + tally[key] = mutableListOf(value) + } - // "configuration" is an undocumented kapt3 argument. preparing the arguments this way is the only way to get more than one annotation processor class - // passed to kotlinc. - fun encode(): List = listOf( - "-Xplugin=$jarPath", - "-P", "plugin:$pluginId:configuration=${encodeMultiMap(tally)}" - ) + fun bindMulti(key: String, value: String) { + tally[key].also { if (it != null) it.add(value) else this[key] = value } } - fun encode(context: CompilationTaskContext, task: JvmCompilationTask): List { - val javacArgs = mutableMapOf( - "-target" to task.info.toolchainInfo.jvm.jvmTarget - ) - val d = task.directories - return if (task.inputs.processorsList.isNotEmpty()) { - PluginArgs().let { arg -> - arg["sources"] = d.generatedSources.toString() - arg["classes"] = d.generatedClasses.toString() - arg["stubs"] = d.temp.toString() - arg["incrementalData"] = d.temp.toString() - arg["javacArguments"] = javacArgs.let(Companion::encodeMap) - arg["aptMode"] = "stubsAndApt" - arg["correctErrorTypes"] = "true" - context.whenTracing { - arg["verbose"] = "true" - } - arg["processors"] = task.inputs.processorsList.joinToString(",") - task.inputs.processorpathsList.forEach { arg.bindMulti("apclasspath", it) } - arg.encode() - } - } else { - emptyList() + // "configuration" is an undocumented kapt3 argument. preparing the arguments this way is the only way to get more than one annotation processor class + // passed to kotlinc. + fun encode(): List = listOf( + "-Xplugin=$jarPath", + "-P", "plugin:$pluginId:configuration=${encodeMultiMap(tally)}" + ) + } + + fun encode(context: CompilationTaskContext, task: JvmCompilationTask): List { + val javacArgs = mutableMapOf( + "-target" to task.info.toolchainInfo.jvm.jvmTarget + ) + val d = task.directories + return if (task.inputs.processorsList.isNotEmpty()) { + PluginArgs().let { arg -> + arg["sources"] = d.generatedSources.toString() + arg["classes"] = d.generatedClasses.toString() + arg["stubs"] = d.temp.toString() + arg["incrementalData"] = d.temp.toString() + arg["javacArguments"] = javacArgs.let(Companion::encodeMap) + arg["aptMode"] = "stubsAndApt" + arg["correctErrorTypes"] = "true" + context.whenTracing { + arg["verbose"] = "true" } + arg["processors"] = task.inputs.processorsList.joinToString(",") + task.inputs.processorpathsList.forEach { arg.bindMulti("apclasspath", it) } + arg.encode() + } + } else { + emptyList() } -} \ No newline at end of file + } +} diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolException.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolException.kt index 20ecd30f5..f1b7082e4 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolException.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolException.kt @@ -16,15 +16,15 @@ package io.bazel.kotlin.builder.toolchain sealed class KotlinToolException( - msg: String, - ex: Throwable? = null + msg: String, + ex: Throwable? = null ) : RuntimeException(msg, ex) class CompilationException(msg: String, cause: Throwable? = null) : - KotlinToolException(msg, cause) + KotlinToolException(msg, cause) class CompilationStatusException( - msg: String, - val status: Int, - val lines: List = emptyList() -) : KotlinToolException("$msg:${lines.joinToString("\n", "\n")}") \ No newline at end of file + msg: String, + val status: Int, + val lines: List = emptyList() +) : KotlinToolException("$msg:${lines.joinToString("\n", "\n")}") diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt index d76f48e0b..43ab00033 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt @@ -32,13 +32,13 @@ class KotlinToolchain private constructor( val kotlinHome: Path, val classLoader: ClassLoader, val kotlinStandardLibraries: List = listOf( - "kotlin-stdlib.jar", - "kotlin-stdlib-jdk7.jar", - "kotlin-stdlib-jdk8.jar" + "kotlin-stdlib.jar", + "kotlin-stdlib-jdk7.jar", + "kotlin-stdlib-jdk8.jar" ), val kapt3Plugin: KotlinToolchain.CompilerPlugin = KotlinToolchain.CompilerPlugin( - kotlinHome.resolveVerified("lib", "kotlin-annotation-processing.jar").absolutePath, - "org.jetbrains.kotlin.kapt3" + kotlinHome.resolveVerified("lib", "kotlin-annotation-processing.jar").absolutePath, + "org.jetbrains.kotlin.kapt3" ) ) { @@ -48,17 +48,17 @@ class KotlinToolchain private constructor( private val isJdk9OrNewer = !System.getProperty("java.version").startsWith("1.") private fun createClassLoader(javaHome: Path, baseJars: List): ClassLoader = - ClassPreloadingUtils.preloadClasses( - mutableListOf().also { - it += baseJars - if (!isJdk9OrNewer) { - it += javaHome.resolveVerified("lib", "tools.jar") - } - }, - Preloader.DEFAULT_CLASS_NUMBER_ESTIMATE, - ClassLoader.getSystemClassLoader(), - null - ) + ClassPreloadingUtils.preloadClasses( + mutableListOf().also { + it += baseJars + if (!isJdk9OrNewer) { + it += javaHome.resolveVerified("lib", "tools.jar") + } + }, + Preloader.DEFAULT_CLASS_NUMBER_ESTIMATE, + ClassLoader.getSystemClassLoader(), + null + ) @JvmStatic fun createToolchain(): KotlinToolchain { @@ -66,19 +66,21 @@ class KotlinToolchain private constructor( path.takeIf { !it.endsWith(Paths.get("jre")) } ?: path.parent } val kotlinCompilerJar = BazelRunFiles.resolveVerified( - "external", "com_github_jetbrains_kotlin", "lib", "kotlin-compiler.jar") + "external", "com_github_jetbrains_kotlin", "lib", "kotlin-compiler.jar" + ) return KotlinToolchain( - kotlinCompilerJar.toPath().parent.parent, - createClassLoader( - javaHome, - listOf( - kotlinCompilerJar, - BazelRunFiles.resolveVerified( - "io_bazel_rules_kotlin", - "src", "main", "kotlin", "io", "bazel", "kotlin", "compiler", - "compiler.jar") - ) + kotlinCompilerJar.toPath().parent.parent, + createClassLoader( + javaHome, + listOf( + kotlinCompilerJar, + BazelRunFiles.resolveVerified( + "io_bazel_rules_kotlin", + "src", "main", "kotlin", "io", "bazel", "kotlin", "compiler", + "compiler.jar" + ) ) + ) ) } } @@ -112,11 +114,11 @@ class KotlinToolchain private constructor( init { val compilerClass = toolchain.classLoader.loadClass(clazz) val exitCodeClass = - toolchain.classLoader.loadClass("org.jetbrains.kotlin.cli.common.ExitCode") + toolchain.classLoader.loadClass("org.jetbrains.kotlin.cli.common.ExitCode") compiler = compilerClass.getConstructor().newInstance() execMethod = - compilerClass.getMethod("exec", PrintStream::class.java, Array::class.java) + compilerClass.getMethod("exec", PrintStream::class.java, Array::class.java) getCodeMethod = exitCodeClass.getMethod("getCode") } @@ -140,5 +142,3 @@ class KotlinToolchain private constructor( toolchain: KotlinToolchain ) : KotlinCliToolInvoker(toolchain, "org.jetbrains.kotlin.cli.js.K2JSCompiler") } - - diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/ArgMap.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/ArgMap.kt index 3f13d79f7..823dbf928 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/ArgMap.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/ArgMap.kt @@ -23,24 +23,24 @@ class ArgMap(private val map: Map>) { * Get the mandatory single value from a key */ private fun mandatorySingle(key: String): String = - optionalSingle(key) ?: throw IllegalArgumentException("$key is not optional") + optionalSingle(key) ?: throw IllegalArgumentException("$key is not optional") private fun labelDepMap(key: String) = - optional(key) - ?.asSequence() - ?.windowed(2, 2) - ?.map { it[0] to it[1] } - ?.toMap() - ?: emptyMap() + optional(key) + ?.asSequence() + ?.windowed(2, 2) + ?.map { it[0] to it[1] } + ?.toMap() + ?: emptyMap() private fun optionalSingle(key: String): String? = - optional(key)?.let { - when (it.size) { - 0 -> throw IllegalArgumentException("$key did not have a value") - 1 -> it[0] - else -> throw IllegalArgumentException("$key should have a single value") - } + optional(key)?.let { + when (it.size) { + 0 -> throw IllegalArgumentException("$key did not have a value") + 1 -> it[0] + else -> throw IllegalArgumentException("$key should have a single value") } + } private fun optionalSingleIf(key: String, condition: () -> Boolean): String? { return if (condition()) { @@ -59,22 +59,22 @@ class ArgMap(private val map: Map>) { } private fun mandatory(key: String): List = optional(key) - ?: throw IllegalArgumentException( - "$key is not optional") + ?: throw IllegalArgumentException( + "$key is not optional" + ) private fun optional(key: String): List? = map[key] fun mandatorySingle(key: Flag) = mandatorySingle(key.flag) fun optionalSingle(key: Flag) = optionalSingle(key.flag) fun optionalSingleIf(key: Flag, condition: () -> Boolean) = - optionalSingleIf(key.flag, condition) + optionalSingleIf(key.flag, condition) fun hasAll(vararg keys: Flag) = hasAll(keys.map(Flag::flag).toTypedArray()) fun hasAny(vararg keys: Flag) = hasAny(keys.map(Flag::flag).toTypedArray()) fun mandatory(key: Flag) = mandatory(key.flag) fun optional(key: Flag) = optional(key.flag) fun labelDepMap(key: Flag) = labelDepMap(key.flag) - } interface Flag { @@ -84,9 +84,9 @@ interface Flag { object ArgMaps { @JvmStatic fun from(args: List): ArgMap = - mutableMapOf>() - .also { argsToMap(args, it) } - .let(::ArgMap) + mutableMapOf>() + .also { argsToMap(args, it) } + .let(::ArgMap) @JvmStatic fun from(file: File): ArgMap = from(file.reader().readLines()) @@ -97,7 +97,7 @@ object ArgMaps { isFlag: (String) -> Boolean = { it.startsWith("--") } ) { var currentKey: String = - args.first().also { require(isFlag(it)) { "first arg must be a flag" } } + args.first().also { require(isFlag(it)) { "first arg must be a flag" } } val currentValue = mutableListOf() val mergeCurrent = { argMap.computeIfAbsent(currentKey) { mutableListOf() }.addAll(currentValue) diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/BUILD.bazel b/src/main/kotlin/io/bazel/kotlin/builder/utils/BUILD.bazel index f82e208c3..82985f138 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/BUILD.bazel +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/BUILD.bazel @@ -16,11 +16,11 @@ load("//src/main/kotlin:bootstrap.bzl", "kt_bootstrap_library") kt_bootstrap_library( name = "utils", - visibility = ["//src:__subpackages__",], srcs = glob([ "*.kt", "**/*.kt", ]), + visibility = ["//src:__subpackages__"], deps = [ "//src/main/protobuf:deps_java_proto", "//src/main/protobuf:kotlin_model_java_proto", diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/BazelUtils.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/BazelUtils.kt index 311327ec3..e69791c50 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/BazelUtils.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/BazelUtils.kt @@ -19,75 +19,76 @@ import java.io.File import java.io.FileInputStream import java.nio.charset.Charset import java.nio.file.Paths -import java.util.* +import java.util.Collections /** Utility class for getting runfiles on windows and *nix. */ object BazelRunFiles { - private val isWindows = System.getProperty("os.name").toLowerCase().indexOf("win") >= 0 - /** - * Populated on windows. The RUNFILES_MANIFEST_FILE is set on platforms other then windows but it can be empty,] - */ - private val manifestFile: String? = - if (isWindows) { - checkNotNull(System.getenv("RUNFILES_MANIFEST_FILE")) { "RUNFILES_MANIFEST_FILE not set in environment" } - } else null + private val isWindows = System.getProperty("os.name").toLowerCase().indexOf("win") >= 0 - private val javaRunFiles = Paths.get(System.getenv("JAVA_RUNFILES")) + /** + * Populated on windows. The RUNFILES_MANIFEST_FILE is set on platforms other then windows but it can be empty,] + */ + private val manifestFile: String? = + if (isWindows) { + checkNotNull(System.getenv("RUNFILES_MANIFEST_FILE")) { "RUNFILES_MANIFEST_FILE not set in environment" } + } else null - private val runfiles by lazy { - with(mutableMapOf()) { - FileInputStream(manifestFile) - .bufferedReader(Charset.forName("UTF-8")) - .lines() - .forEach { it -> - val line = it.trim { it <= ' ' } - if (!line.isEmpty()) { - // TODO(bazel-team): This is buggy when the path contains spaces, we should fix the manifest format. - line.split(" ").also { - check(it.size == 2) { "RunFiles manifest entry $line contains more than one space" } - put(it[0], it[1]) - } - } - } - Collections.unmodifiableMap(this) - } - } + private val javaRunFiles = Paths.get(System.getenv("JAVA_RUNFILES")) - /** - * Resolve a run file on windows or *nix. - */ - @JvmStatic - fun resolveVerified(vararg path: String): File { - check(path.isNotEmpty()) - val fromManifest = manifestFile?.let { mf -> - path.joinToString("/").let { rfPath -> - // trim off the external/ prefix if it is present. - val trimmedPath = - if (rfPath.startsWith("external/")) { - rfPath.replaceFirst("external/", "") - } else { - rfPath - } - File( - checkNotNull(runfiles[trimmedPath]) { - "runfile manifest $mf did not contain path mapping for $rfPath" - } - ) - }.also { - check(it.exists()) { "file $it resolved from runfiles did not exist" } + private val runfiles by lazy { + with(mutableMapOf()) { + FileInputStream(manifestFile) + .bufferedReader(Charset.forName("UTF-8")) + .lines() + .forEach { it -> + val line = it.trim { it <= ' ' } + if (!line.isEmpty()) { + // TODO(bazel-team): This is buggy when the path contains spaces, we should fix the manifest format. + line.split(" ").also { + check(it.size == 2) { "RunFiles manifest entry $line contains more than one space" } + put(it[0], it[1]) } + } } - if(fromManifest != null) { - return fromManifest - } + Collections.unmodifiableMap(this) + } + } - /// if it could not be resolved from the manifest then first try to resolve it directly. - val resolvedDirect = File(path.joinToString(File.separator)).takeIf { it.exists() } - if(resolvedDirect != null) { - return resolvedDirect - } + /** + * Resolve a run file on windows or *nix. + */ + @JvmStatic + fun resolveVerified(vararg path: String): File { + check(path.isNotEmpty()) + val fromManifest = manifestFile?.let { mf -> + path.joinToString("/").let { rfPath -> + // trim off the external/ prefix if it is present. + val trimmedPath = + if (rfPath.startsWith("external/")) { + rfPath.replaceFirst("external/", "") + } else { + rfPath + } + File( + checkNotNull(runfiles[trimmedPath]) { + "runfile manifest $mf did not contain path mapping for $rfPath" + } + ) + }.also { + check(it.exists()) { "file $it resolved from runfiles did not exist" } + } + } + if (fromManifest != null) { + return fromManifest + } - // Try the java runfiles as the last resort. - return javaRunFiles.resolveVerified(path.joinToString(File.separator)) + // / if it could not be resolved from the manifest then first try to resolve it directly. + val resolvedDirect = File(path.joinToString(File.separator)).takeIf { it.exists() } + if (resolvedDirect != null) { + return resolvedDirect } -} \ No newline at end of file + + // Try the java runfiles as the last resort. + return javaRunFiles.resolveVerified(path.joinToString(File.separator)) + } +} diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/IOUtils.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/IOUtils.kt index f3b9de652..faef6b3db 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/IOUtils.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/IOUtils.kt @@ -23,76 +23,77 @@ import java.io.PrintStream import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths -import java.util.* +import java.util.Arrays import java.util.concurrent.TimeUnit import java.util.concurrent.TimeoutException private fun executeAwait(timeoutSeconds: Int, process: Process): Int { - try { - if (!process.waitFor(timeoutSeconds.toLong(), TimeUnit.SECONDS)) { - throw TimeoutException() - } - return process.exitValue() - } finally { - if (process.isAlive) { - process.destroy() - } + try { + if (!process.waitFor(timeoutSeconds.toLong(), TimeUnit.SECONDS)) { + throw TimeoutException() } + return process.exitValue() + } finally { + if (process.isAlive) { + process.destroy() + } + } } fun executeAndAwait(timeoutSeconds: Int, directory: File? = null, args: List): Int { - val process = ProcessBuilder(*args.toTypedArray()).let { pb -> - pb.redirectError(ProcessBuilder.Redirect.PIPE) - pb.redirectOutput(ProcessBuilder.Redirect.PIPE) - directory?.also { pb.directory(it) } - pb.start() - } + val process = ProcessBuilder(*args.toTypedArray()).let { pb -> + pb.redirectError(ProcessBuilder.Redirect.PIPE) + pb.redirectOutput(ProcessBuilder.Redirect.PIPE) + directory?.also { pb.directory(it) } + pb.start() + } - var isr: BufferedReader? = null - var esr: BufferedReader? = null + var isr: BufferedReader? = null + var esr: BufferedReader? = null - try { - isr = process.inputStream.bufferedReader() - esr = process.errorStream.bufferedReader() - return executeAwait(timeoutSeconds, process) - } finally { - isr?.drainTo(System.out) - esr?.drainTo(System.err) - } + try { + isr = process.inputStream.bufferedReader() + esr = process.errorStream.bufferedReader() + return executeAwait(timeoutSeconds, process) + } finally { + isr?.drainTo(System.out) + esr?.drainTo(System.err) + } } private fun BufferedReader.drainTo(pw: PrintStream) { - lines().forEach(pw::println); close() + lines().forEach(pw::println); close() } fun Path.resolveTwinVerified(extension: String): Path = - parent.resolve( - "${toFile().nameWithoutExtension}${if (extension.startsWith(".")) "" else "."}$extension" - ).verified().toPath() - + parent.resolve( + "${toFile().nameWithoutExtension}${if (extension.startsWith(".")) "" else "."}$extension" + ).verified().toPath() fun Path.resolveVerified(vararg parts: String): File = - resolve(Paths.get(parts[0], *Arrays.copyOfRange(parts, 1, parts.size))).verified() + resolve(Paths.get(parts[0], *Arrays.copyOfRange(parts, 1, parts.size))).verified() fun Path.resolveVerifiedToAbsoluteString(vararg parts: String): String = - resolveVerified(*parts).absolutePath.toString() + resolveVerified(*parts).absolutePath.toString() -fun Path.verified(): File = this.toFile().also { check(it.exists()) { "file did not exist: $this" } } +fun Path.verified(): File = + this.toFile().also { check(it.exists()) { "file did not exist: $this" } } -fun Path.verifiedPath(): Path = this.toFile().also { check(it.exists()) { "file did not exist: $this" } }.toPath() +fun Path.verifiedPath(): Path = + this.toFile().also { check(it.exists()) { "file did not exist: $this" } }.toPath() fun ensureDirectories(vararg directories: String) { - for (directory in directories) { - Files.createDirectories(Paths.get(directory)) - } + for (directory in directories) { + Files.createDirectories(Paths.get(directory)) + } } val Throwable.rootCause: Throwable - get() { - var result = this - do { - val cause = result.cause - if (cause != null) result = cause - } while (cause != null && result != cause) - return result - } + get() { + var result = this + do { + val cause = result.cause + if (cause != null) result = cause + } while (cause != null && result != cause) + return result + } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/MiscUtils.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/MiscUtils.kt index 356a02c33..6d8d17b0a 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/MiscUtils.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/MiscUtils.kt @@ -24,9 +24,11 @@ fun > C.addAll(vararg entries: T): C = this.also { a /** * Utility function to add multiple entries to a list with a leader. */ -fun > C.addAll(leader: T, entries: List): C = this.also { add(leader); addAll(entries) } +fun > C.addAll(leader: T, entries: List): C = + this.also { add(leader); addAll(entries) } private fun extensionMatcher(vararg ext: String): Predicate = - Pattern.compile("^(.+?)${ext.joinToString("|\\.", prefix = "(\\.",postfix = ")$")}").asPredicate() + Pattern.compile("^(.+?)${ext.joinToString("|\\.", prefix = "(\\.", postfix = ")$")}") + .asPredicate() val IS_JVM_SOURCE_FILE = extensionMatcher("kt", "java") diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/TaskUtils.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/TaskUtils.kt index 2f91ca6a3..1aeaf9f5c 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/TaskUtils.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/TaskUtils.kt @@ -24,11 +24,11 @@ val JvmCompilationTask.Inputs.joinedClasspath: String get() = this.classpathList val CompilationTaskInfo.bazelRuleKind: String get() = "kt_${platform.name.toLowerCase()}_${ruleKind.name.toLowerCase()}" fun Iterator.partitionJvmSources(kt: (String) -> Unit, java: (String) -> Unit) { - forEach { - when { - it.endsWith(".kt") -> kt(it) - it.endsWith(".java") -> java(it) - else -> throw IllegalStateException("invalid source file type $it") - } + forEach { + when { + it.endsWith(".kt") -> kt(it) + it.endsWith(".java") -> java(it) + else -> throw IllegalStateException("invalid source file type $it") } + } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarCreator.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarCreator.kt index 7127ad107..ca00ac912 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarCreator.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarCreator.kt @@ -15,11 +15,18 @@ */ package io.bazel.kotlin.builder.utils.jars -import java.io.* -import java.nio.file.* -import java.nio.file.Paths.* +import java.io.BufferedOutputStream +import java.io.ByteArrayOutputStream +import java.io.FileInputStream +import java.io.IOException +import java.io.UncheckedIOException +import java.nio.file.FileVisitResult +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths.get +import java.nio.file.SimpleFileVisitor import java.nio.file.attribute.BasicFileAttributes -import java.util.* +import java.util.TreeMap import java.util.jar.Attributes import java.util.jar.JarOutputStream import java.util.jar.Manifest @@ -30,196 +37,195 @@ import java.util.jar.Manifest * the DOS epoch. All Jar entries are sorted alphabetically. */ class JarCreator( - path: Path, - normalize: Boolean = true, - verbose: Boolean = false + path: Path, + normalize: Boolean = true, + verbose: Boolean = false ) : JarHelper(path, normalize, verbose) { - // Map from Jar entry names to files. Use TreeMap so we can establish a canonical order for the - // entries regardless in what order they get added. - private val jarEntries = TreeMap() - private var manifestFile: String? = null - private var mainClass: String? = null - private var targetLabel: String? = null - private var injectingRuleKind: String? = null - - /** - * Adds an entry to the Jar file, normalizing the name. - * - * @param entryName the name of the entry in the Jar file - * @param path the path of the input for the entry - * @return true iff a new entry was added - */ - private fun addEntry(entryName: String, path: Path): Boolean { - var normalizedEntryName = entryName - if (normalizedEntryName.startsWith("/")) { - normalizedEntryName = normalizedEntryName.substring(1) - } else if (normalizedEntryName.length >= 3 - && Character.isLetter(normalizedEntryName[0]) - && normalizedEntryName[1] == ':' - && (normalizedEntryName[2] == '\\' || normalizedEntryName[2] == '/') - ) { - // Windows absolute path, e.g. "D:\foo" or "e:/blah". - // Windows paths are case-insensitive, and support both backslashes and forward slashes. - normalizedEntryName = normalizedEntryName.substring(3) - } else if (normalizedEntryName.startsWith("./")) { - normalizedEntryName = normalizedEntryName.substring(2) - } - return jarEntries.put(normalizedEntryName, path) == null + // Map from Jar entry names to files. Use TreeMap so we can establish a canonical order for the + // entries regardless in what order they get added. + private val jarEntries = TreeMap() + private var manifestFile: String? = null + private var mainClass: String? = null + private var targetLabel: String? = null + private var injectingRuleKind: String? = null + + /** + * Adds an entry to the Jar file, normalizing the name. + * + * @param entryName the name of the entry in the Jar file + * @param path the path of the input for the entry + * @return true iff a new entry was added + */ + private fun addEntry(entryName: String, path: Path): Boolean { + var normalizedEntryName = entryName + if (normalizedEntryName.startsWith("/")) { + normalizedEntryName = normalizedEntryName.substring(1) + } else if (normalizedEntryName.length >= 3 && + Character.isLetter(normalizedEntryName[0]) && + normalizedEntryName[1] == ':' && + (normalizedEntryName[2] == '\\' || normalizedEntryName[2] == '/') + ) { + // Windows absolute path, e.g. "D:\foo" or "e:/blah". + // Windows paths are case-insensitive, and support both backslashes and forward slashes. + normalizedEntryName = normalizedEntryName.substring(3) + } else if (normalizedEntryName.startsWith("./")) { + normalizedEntryName = normalizedEntryName.substring(2) } - - /** - * Adds an entry to the Jar file, normalizing the name. - * - * @param entryName the name of the entry in the Jar file - * @param fileName the name of the input file for the entry - * @return true iff a new entry was added - */ - fun addEntry(entryName: String, fileName: String): Boolean { - return addEntry(entryName, get(fileName)) + return jarEntries.put(normalizedEntryName, path) == null + } + + /** + * Adds an entry to the Jar file, normalizing the name. + * + * @param entryName the name of the entry in the Jar file + * @param fileName the name of the input file for the entry + * @return true iff a new entry was added + */ + fun addEntry(entryName: String, fileName: String): Boolean { + return addEntry(entryName, get(fileName)) + } + + /** + * Adds the contents of a directory to the Jar file. All files below this directory will be added + * to the Jar file using the name relative to the directory as the name for the Jar entry. + * + * @param directory the directory to add to the jar + */ + fun addDirectory(directory: Path) { + if (!Files.exists(directory)) { + throw IllegalArgumentException("directory does not exist: $directory") } - - /** - * Adds the contents of a directory to the Jar file. All files below this directory will be added - * to the Jar file using the name relative to the directory as the name for the Jar entry. - * - * @param directory the directory to add to the jar - */ - fun addDirectory(directory: Path) { - if (!Files.exists(directory)) { - throw IllegalArgumentException("directory does not exist: $directory") - } - try { - Files.walkFileTree( - directory, - object : SimpleFileVisitor() { - - @Throws(IOException::class) - override fun preVisitDirectory(path: Path, attrs: BasicFileAttributes): FileVisitResult { - if (path != directory) { - // For consistency with legacy behaviour, include entries for directories except for - // the root. - addEntry(path, /* isDirectory= */ true) - } - return FileVisitResult.CONTINUE - } - - @Throws(IOException::class) - override fun visitFile(path: Path, attrs: BasicFileAttributes): FileVisitResult { - addEntry(path, /* isDirectory= */ false) - return FileVisitResult.CONTINUE - } - - fun addEntry(path: Path, isDirectory: Boolean) { - val sb = StringBuilder() - var first = true - for (entry in directory.relativize(path)) { - if (!first) { - // use `/` as the directory separator for jar paths, even on Windows - sb.append('/') - } - sb.append(entry.fileName) - first = false - } - if (isDirectory) { - sb.append('/') - } - jarEntries[sb.toString()] = path - } - }) - } catch (e: IOException) { - throw UncheckedIOException(e) - } - + try { + Files.walkFileTree( + directory, + object : SimpleFileVisitor() { + + @Throws(IOException::class) + override fun preVisitDirectory(path: Path, attrs: BasicFileAttributes): FileVisitResult { + if (path != directory) { + // For consistency with legacy behaviour, include entries for directories except for + // the root. + addEntry(path, /* isDirectory= */ true) + } + return FileVisitResult.CONTINUE + } + + @Throws(IOException::class) + override fun visitFile(path: Path, attrs: BasicFileAttributes): FileVisitResult { + addEntry(path, /* isDirectory= */ false) + return FileVisitResult.CONTINUE + } + + fun addEntry(path: Path, isDirectory: Boolean) { + val sb = StringBuilder() + var first = true + for (entry in directory.relativize(path)) { + if (!first) { + // use `/` as the directory separator for jar paths, even on Windows + sb.append('/') + } + sb.append(entry.fileName) + first = false + } + if (isDirectory) { + sb.append('/') + } + jarEntries[sb.toString()] = path + } + }) + } catch (e: IOException) { + throw UncheckedIOException(e) } - - /** - * Adds a collection of entries to the jar, each with a given source path, and with the resulting - * file in the root of the jar. - * - *
-     * some/long/path.foo => (path.foo, some/long/path.foo)
-    
* - */ - fun addRootEntries(entries: Collection) { - for (entry in entries) { - val path = get(entry) - jarEntries[path.fileName.toString()] = path - } + } + + /** + * Adds a collection of entries to the jar, each with a given source path, and with the resulting + * file in the root of the jar. + * + *
+   * some/long/path.foo => (path.foo, some/long/path.foo)
+  
* + */ + fun addRootEntries(entries: Collection) { + for (entry in entries) { + val path = get(entry) + jarEntries[path.fileName.toString()] = path } - - /** - * Sets the main.class entry for the manifest. A value of `null` (the default) will - * omit the entry. - * - * @param mainClass the fully qualified name of the main class - */ - fun setMainClass(mainClass: String) { - this.mainClass = mainClass + } + + /** + * Sets the main.class entry for the manifest. A value of `null` (the default) will + * omit the entry. + * + * @param mainClass the fully qualified name of the main class + */ + fun setMainClass(mainClass: String) { + this.mainClass = mainClass + } + + fun setJarOwner(targetLabel: String, injectingRuleKind: String) { + this.targetLabel = targetLabel + this.injectingRuleKind = injectingRuleKind + } + + /** + * Sets filename for the manifest content. If this is set the manifest will be read from this file + * otherwise the manifest content will get generated on the fly. + * + * @param manifestFile the filename of the manifest file. + */ + fun setManifestFile(manifestFile: String) { + this.manifestFile = manifestFile + } + + @Throws(IOException::class) + private fun manifestContent(): ByteArray { + if (manifestFile != null) { + FileInputStream(manifestFile!!).use { `in` -> return manifestContentImpl(Manifest(`in`)) } + } else { + return manifestContentImpl(Manifest()) } - - fun setJarOwner(targetLabel: String, injectingRuleKind: String) { - this.targetLabel = targetLabel - this.injectingRuleKind = injectingRuleKind + } + + @Throws(IOException::class) + private fun manifestContentImpl(manifest: Manifest): ByteArray { + val attributes = manifest.mainAttributes + attributes[Attributes.Name.MANIFEST_VERSION] = "1.0" + val createdBy = Attributes.Name("Created-By") + if (attributes.getValue(createdBy) == null) { + attributes[createdBy] = "io.bazel.rules.kotlin" } - - /** - * Sets filename for the manifest content. If this is set the manifest will be read from this file - * otherwise the manifest content will get generated on the fly. - * - * @param manifestFile the filename of the manifest file. - */ - fun setManifestFile(manifestFile: String) { - this.manifestFile = manifestFile + if (mainClass != null) { + attributes[Attributes.Name.MAIN_CLASS] = mainClass } - - @Throws(IOException::class) - private fun manifestContent(): ByteArray { - if (manifestFile != null) { - FileInputStream(manifestFile!!).use { `in` -> return manifestContentImpl(Manifest(`in`)) } - } else { - return manifestContentImpl(Manifest()) - } + if (targetLabel != null) { + attributes[TARGET_LABEL] = targetLabel } - - @Throws(IOException::class) - private fun manifestContentImpl(manifest: Manifest): ByteArray { - val attributes = manifest.mainAttributes - attributes[Attributes.Name.MANIFEST_VERSION] = "1.0" - val createdBy = Attributes.Name("Created-By") - if (attributes.getValue(createdBy) == null) { - attributes[createdBy] = "io.bazel.rules.kotlin" - } - if (mainClass != null) { - attributes[Attributes.Name.MAIN_CLASS] = mainClass - } - if (targetLabel != null) { - attributes[TARGET_LABEL] = targetLabel - } - if (injectingRuleKind != null) { - attributes[INJECTING_RULE_KIND] = injectingRuleKind - } - val out = ByteArrayOutputStream() - manifest.write(out) - return out.toByteArray() + if (injectingRuleKind != null) { + attributes[INJECTING_RULE_KIND] = injectingRuleKind } - - /** - * Executes the creation of the Jar file. - * - * @throws IOException if the Jar cannot be written or any of the entries cannot be read. - */ - @Throws(IOException::class) - fun execute() { - Files.newOutputStream(jarPath).use { os -> - BufferedOutputStream(os).use { bos -> - JarOutputStream(bos).use { out -> - // Create the manifest entry in the Jar file - writeManifestEntry(out, manifestContent()) - for ((key, value) in jarEntries) { - out.copyEntry(key, value) - } - } - } + val out = ByteArrayOutputStream() + manifest.write(out) + return out.toByteArray() + } + + /** + * Executes the creation of the Jar file. + * + * @throws IOException if the Jar cannot be written or any of the entries cannot be read. + */ + @Throws(IOException::class) + fun execute() { + Files.newOutputStream(jarPath).use { os -> + BufferedOutputStream(os).use { bos -> + JarOutputStream(bos).use { out -> + // Create the manifest entry in the Jar file + writeManifestEntry(out, manifestContent()) + for ((key, value) in jarEntries) { + out.copyEntry(key, value) + } } + } } -} \ No newline at end of file + } +} diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarExtractor.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarExtractor.kt index 13574ba1c..d955031c1 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarExtractor.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarExtractor.kt @@ -19,39 +19,37 @@ import java.nio.file.Files import java.nio.file.Path import java.util.jar.JarFile - open class JarExtractor protected constructor( - protected var destDir: Path + protected var destDir: Path ) { - /** - * @param isDirectory is the target a directory. - * @param target path the operation will apply to. - * @return weather the operation should be applied or not. - */ - internal open fun preWrite(isDirectory: Boolean, target: Path): Boolean = true + /** + * @param isDirectory is the target a directory. + * @param target path the operation will apply to. + * @return weather the operation should be applied or not. + */ + internal open fun preWrite(isDirectory: Boolean, target: Path): Boolean = true - protected fun extract(jarFile: Path) { - JarFile(jarFile.toFile()).use { jar -> - jar.entries().also { entries -> - while (entries.hasMoreElements()) { - (entries.nextElement() as java.util.jar.JarEntry).also { entry -> - destDir.resolve(entry.name).also { target -> - if (preWrite(entry.isDirectory, target)) { - when { - entry.isDirectory -> - Files.createDirectories(target) - else -> jar.getInputStream(entry).use { - Files.createDirectories(target.parent) - Files.copy(it, target) - } - } - } - } - } + protected fun extract(jarFile: Path) { + JarFile(jarFile.toFile()).use { jar -> + jar.entries().also { entries -> + while (entries.hasMoreElements()) { + (entries.nextElement() as java.util.jar.JarEntry).also { entry -> + destDir.resolve(entry.name).also { target -> + if (preWrite(entry.isDirectory, target)) { + when { + entry.isDirectory -> + Files.createDirectories(target) + else -> jar.getInputStream(entry).use { + Files.createDirectories(target.parent) + Files.copy(it, target) + } } + } } + } } + } } + } } - diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarHelper.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarHelper.kt index 2fa0a1373..8af6836fa 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarHelper.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarHelper.kt @@ -14,7 +14,8 @@ // Copied from bazel core and there is some code in other branches which will use the some of the unused elements. Fix // this later on. -@file:Suppress("unused","MemberVisibilityCanBePrivate") +@file:Suppress("unused", "MemberVisibilityCanBePrivate") + package io.bazel.kotlin.builder.utils.jars import java.io.FileNotFoundException @@ -23,7 +24,7 @@ import java.nio.file.Files import java.nio.file.Path import java.time.LocalDateTime import java.time.ZoneId -import java.util.* +import java.util.HashSet import java.util.jar.Attributes import java.util.jar.JarEntry import java.util.jar.JarFile @@ -37,218 +38,226 @@ import java.util.zip.CRC32 * Adjusting the timestamp for .class files is necessary since otherwise javac will recompile java * files if both the java file and its .class file are present. */ -open class JarHelper internal constructor ( - // The path to the Jar we want to create - protected val jarPath: Path, - // The properties to describe how to create the Jar - protected val normalize: Boolean = true, - protected val verbose: Boolean = false, - compression: Boolean = true +open class JarHelper internal constructor( + // The path to the Jar we want to create + protected val jarPath: Path, + // The properties to describe how to create the Jar + protected val normalize: Boolean = true, + protected val verbose: Boolean = false, + compression: Boolean = true ) { - private var storageMethod: Int = JarEntry.DEFLATED - // The state needed to create the Jar - private val names: MutableSet = HashSet() + private var storageMethod: Int = JarEntry.DEFLATED - init { - setCompression(compression) - } + // The state needed to create the Jar + private val names: MutableSet = HashSet() - /** - * Enables or disables compression for the Jar file entries. - * - * @param compression if true enables compressions for the Jar file entries. - */ - private fun setCompression(compression: Boolean) { - storageMethod = if (compression) JarEntry.DEFLATED else JarEntry.STORED - } + init { + setCompression(compression) + } - /** - * Returns the normalized timestamp for a jar entry based on its name. This is necessary since - * javac will, when loading a class X, prefer a source file to a class file, if both files have - * the same timestamp. Therefore, we need to adjust the timestamp for class files to slightly - * after the normalized time. - * - * @param name The name of the file for which we should return the normalized timestamp. - * @return the time for a new Jar file entry in milliseconds since the epoch. - */ - private fun normalizedTimestamp(name: String): Long { - return if (name.endsWith(".class")) { - DEFAULT_TIMESTAMP + MINIMUM_TIMESTAMP_INCREMENT - } else { - DEFAULT_TIMESTAMP - } - } + /** + * Enables or disables compression for the Jar file entries. + * + * @param compression if true enables compressions for the Jar file entries. + */ + private fun setCompression(compression: Boolean) { + storageMethod = if (compression) JarEntry.DEFLATED else JarEntry.STORED + } - /** - * Returns the time for a new Jar file entry in milliseconds since the epoch. Uses JarCreator.DEFAULT_TIMESTAMP] - * for normalized entries, [System.currentTimeMillis] otherwise. - * - * @param filename The name of the file for which we are entering the time - * @return the time for a new Jar file entry in milliseconds since the epoch. - */ - private fun newEntryTimeMillis(filename: String): Long { - return if (normalize) normalizedTimestamp(filename) else System.currentTimeMillis() + /** + * Returns the normalized timestamp for a jar entry based on its name. This is necessary since + * javac will, when loading a class X, prefer a source file to a class file, if both files have + * the same timestamp. Therefore, we need to adjust the timestamp for class files to slightly + * after the normalized time. + * + * @param name The name of the file for which we should return the normalized timestamp. + * @return the time for a new Jar file entry in milliseconds since the epoch. + */ + private fun normalizedTimestamp(name: String): Long { + return if (name.endsWith(".class")) { + DEFAULT_TIMESTAMP + MINIMUM_TIMESTAMP_INCREMENT + } else { + DEFAULT_TIMESTAMP } + } - /** - * Writes an entry with specific contents to the jar. Directory entries must include the trailing - * '/'. - */ - @Throws(IOException::class) - private fun writeEntry(out: JarOutputStream, name: String, content: ByteArray) { - if (names.add(name)) { - // Create a new entry - val entry = JarEntry(name) - entry.time = newEntryTimeMillis(name) - val size = content.size - entry.size = size.toLong() - if (size == 0) { - entry.method = JarEntry.STORED - entry.crc = 0 - out.putNextEntry(entry) - } else { - entry.method = storageMethod - if (storageMethod == JarEntry.STORED) { - val crc = CRC32() - crc.update(content) - entry.crc = crc.value - } - out.putNextEntry(entry) - out.write(content) - } - out.closeEntry() - } - } + /** + * Returns the time for a new Jar file entry in milliseconds since the epoch. Uses JarCreator.DEFAULT_TIMESTAMP] + * for normalized entries, [System.currentTimeMillis] otherwise. + * + * @param filename The name of the file for which we are entering the time + * @return the time for a new Jar file entry in milliseconds since the epoch. + */ + private fun newEntryTimeMillis(filename: String): Long { + return if (normalize) normalizedTimestamp(filename) else System.currentTimeMillis() + } - /** - * Writes a standard Java manifest entry into the JarOutputStream. This includes the directory - * entry for the "META-INF" directory - * - * @param content the Manifest content to write to the manifest entry. - * @throws IOException - */ - @Throws(IOException::class) - protected fun writeManifestEntry(out: JarOutputStream, content: ByteArray) { - val oldStorageMethod = storageMethod - // Do not compress small manifest files, the compressed one is frequently - // larger than the original. The threshold of 256 bytes is somewhat arbitrary. - if (content.size < 256) { - storageMethod = JarEntry.STORED - } - try { - writeEntry(out, MANIFEST_DIR, byteArrayOf()) - writeEntry(out, MANIFEST_NAME, content) - } finally { - storageMethod = oldStorageMethod + /** + * Writes an entry with specific contents to the jar. Directory entries must include the trailing + * '/'. + */ + @Throws(IOException::class) + private fun writeEntry(out: JarOutputStream, name: String, content: ByteArray) { + if (names.add(name)) { + // Create a new entry + val entry = JarEntry(name) + entry.time = newEntryTimeMillis(name) + val size = content.size + entry.size = size.toLong() + if (size == 0) { + entry.method = JarEntry.STORED + entry.crc = 0 + out.putNextEntry(entry) + } else { + entry.method = storageMethod + if (storageMethod == JarEntry.STORED) { + val crc = CRC32() + crc.update(content) + entry.crc = crc.value } + out.putNextEntry(entry) + out.write(content) + } + out.closeEntry() } + } - /** - * Copies file or directory entries from the file system into the jar. Directory entries will be - * detected and their names automatically '/' suffixed. - */ - @Throws(IOException::class) - protected fun JarOutputStream.copyEntry(name: String, path: Path) { - var normalizedName = name - if (!names.contains(normalizedName)) { - if (!Files.exists(path)) { - throw FileNotFoundException("${path.toAbsolutePath()} (No such file or directory)") - } - val isDirectory = Files.isDirectory(path) - if (isDirectory && !normalizedName.endsWith("/")) { - normalizedName = "$normalizedName/" // always normalize directory names before checking set - } - if (names.add(normalizedName)) { - if (verbose) { - System.err.println("adding $path") - } - // Create a new entry - val size = if (isDirectory) 0 else Files.size(path) - val outEntry = JarEntry(normalizedName) - val newtime = if (normalize) normalizedTimestamp(normalizedName) else Files.getLastModifiedTime(path).toMillis() - outEntry.time = newtime - outEntry.size = size - if (size == 0L) { - outEntry.method = JarEntry.STORED - outEntry.crc = 0 - putNextEntry(outEntry) - } else { - outEntry.method = storageMethod - if (storageMethod == JarEntry.STORED) { - // ZipFile requires us to calculate the CRC-32 for any STORED entry. - // It would be nicer to do this via DigestInputStream, but - // the architecture of ZipOutputStream requires us to know the CRC-32 - // before we write the data to the stream. - val bytes = Files.readAllBytes(path) - val crc = CRC32() - crc.update(bytes) - outEntry.crc = crc.value - putNextEntry(outEntry) - write(bytes) - } else { - putNextEntry(outEntry) - Files.copy(path, this) - } - } - closeEntry() - } - } + /** + * Writes a standard Java manifest entry into the JarOutputStream. This includes the directory + * entry for the "META-INF" directory + * + * @param content the Manifest content to write to the manifest entry. + * @throws IOException + */ + @Throws(IOException::class) + protected fun writeManifestEntry(out: JarOutputStream, content: ByteArray) { + val oldStorageMethod = storageMethod + // Do not compress small manifest files, the compressed one is frequently + // larger than the original. The threshold of 256 bytes is somewhat arbitrary. + if (content.size < 256) { + storageMethod = JarEntry.STORED + } + try { + writeEntry(out, MANIFEST_DIR, byteArrayOf()) + writeEntry(out, MANIFEST_NAME, content) + } finally { + storageMethod = oldStorageMethod } + } - /** - * Copies a a single entry into the jar. This variant differs from the other [copyEntry] in two ways. Firstly the - * jar contents are already loaded in memory and Secondly the [name] and [path] entries don't necessarily have a - * correspondence. - * - * @param path the path used to retrieve the timestamp in case normalize is disabled. - * @param data if this is empty array then the entry is a directory. - */ - protected fun JarOutputStream.copyEntry(name: String, path: Path? = null, data: ByteArray = EMPTY_BYTEARRAY) { - val outEntry = JarEntry(name) - outEntry.time = when { - normalize -> normalizedTimestamp(name) - else -> Files.getLastModifiedTime(checkNotNull(path)).toMillis() + /** + * Copies file or directory entries from the file system into the jar. Directory entries will be + * detected and their names automatically '/' suffixed. + */ + @Throws(IOException::class) + protected fun JarOutputStream.copyEntry(name: String, path: Path) { + var normalizedName = name + if (!names.contains(normalizedName)) { + if (!Files.exists(path)) { + throw FileNotFoundException("${path.toAbsolutePath()} (No such file or directory)") + } + val isDirectory = Files.isDirectory(path) + if (isDirectory && !normalizedName.endsWith("/")) { + normalizedName = "$normalizedName/" // always normalize directory names before checking set + } + if (names.add(normalizedName)) { + if (verbose) { + System.err.println("adding $path") } - outEntry.size = data.size.toLong() - - if (data.isEmpty()) { - outEntry.method = JarEntry.STORED - outEntry.crc = 0 - putNextEntry(outEntry) + // Create a new entry + val size = if (isDirectory) 0 else Files.size(path) + val outEntry = JarEntry(normalizedName) + val newtime = + if (normalize) normalizedTimestamp(normalizedName) else Files.getLastModifiedTime(path) + .toMillis() + outEntry.time = newtime + outEntry.size = size + if (size == 0L) { + outEntry.method = JarEntry.STORED + outEntry.crc = 0 + putNextEntry(outEntry) } else { - outEntry.method = storageMethod - if (storageMethod == JarEntry.STORED) { - val crc = CRC32() - crc.update(data) - outEntry.crc = crc.value - putNextEntry(outEntry) - write(data) - } else { - putNextEntry(outEntry) - write(data) - } + outEntry.method = storageMethod + if (storageMethod == JarEntry.STORED) { + // ZipFile requires us to calculate the CRC-32 for any STORED entry. + // It would be nicer to do this via DigestInputStream, but + // the architecture of ZipOutputStream requires us to know the CRC-32 + // before we write the data to the stream. + val bytes = Files.readAllBytes(path) + val crc = CRC32() + crc.update(bytes) + outEntry.crc = crc.value + putNextEntry(outEntry) + write(bytes) + } else { + putNextEntry(outEntry) + Files.copy(path, this) + } } closeEntry() + } + } + } + + /** + * Copies a a single entry into the jar. This variant differs from the other [copyEntry] in two ways. Firstly the + * jar contents are already loaded in memory and Secondly the [name] and [path] entries don't necessarily have a + * correspondence. + * + * @param path the path used to retrieve the timestamp in case normalize is disabled. + * @param data if this is empty array then the entry is a directory. + */ + protected fun JarOutputStream.copyEntry( + name: String, + path: Path? = null, + data: ByteArray = EMPTY_BYTEARRAY + ) { + val outEntry = JarEntry(name) + outEntry.time = when { + normalize -> normalizedTimestamp(name) + else -> Files.getLastModifiedTime(checkNotNull(path)).toMillis() } + outEntry.size = data.size.toLong() - companion object { - const val MANIFEST_DIR = "META-INF/" - const val MANIFEST_NAME = JarFile.MANIFEST_NAME - const val SERVICES_DIR = "META-INF/services/" - internal val EMPTY_BYTEARRAY = ByteArray(0) - /** Normalize timestamps. */ - val DEFAULT_TIMESTAMP = LocalDateTime.of(1980, 1, 1, 0, 0, 0) - .atZone(ZoneId.systemDefault()) - .toInstant() - .toEpochMilli() - - // These attributes are used by JavaBuilder, Turbine, and ijar. - // They must all be kept in sync. - val TARGET_LABEL = Attributes.Name("Target-Label") - val INJECTING_RULE_KIND = Attributes.Name("Injecting-Rule-Kind") - - // ZIP timestamps have a resolution of 2 seconds. - // see http://www.info-zip.org/FAQ.html#limits - const val MINIMUM_TIMESTAMP_INCREMENT = 2000L + if (data.isEmpty()) { + outEntry.method = JarEntry.STORED + outEntry.crc = 0 + putNextEntry(outEntry) + } else { + outEntry.method = storageMethod + if (storageMethod == JarEntry.STORED) { + val crc = CRC32() + crc.update(data) + outEntry.crc = crc.value + putNextEntry(outEntry) + write(data) + } else { + putNextEntry(outEntry) + write(data) + } } + closeEntry() + } + + companion object { + const val MANIFEST_DIR = "META-INF/" + const val MANIFEST_NAME = JarFile.MANIFEST_NAME + const val SERVICES_DIR = "META-INF/services/" + internal val EMPTY_BYTEARRAY = ByteArray(0) + + /** Normalize timestamps. */ + val DEFAULT_TIMESTAMP = LocalDateTime.of(1980, 1, 1, 0, 0, 0) + .atZone(ZoneId.systemDefault()) + .toInstant() + .toEpochMilli() + + // These attributes are used by JavaBuilder, Turbine, and ijar. + // They must all be kept in sync. + val TARGET_LABEL = Attributes.Name("Target-Label") + val INJECTING_RULE_KIND = Attributes.Name("Injecting-Rule-Kind") + + // ZIP timestamps have a resolution of 2 seconds. + // see http://www.info-zip.org/FAQ.html#limits + const val MINIMUM_TIMESTAMP_INCREMENT = 2000L + } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarCreator.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarCreator.kt index 2b8f95e19..4c127787f 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarCreator.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarCreator.kt @@ -18,7 +18,7 @@ package io.bazel.kotlin.builder.utils.jars import java.nio.charset.Charset import java.nio.file.Files import java.nio.file.Path -import java.util.* +import java.util.TreeMap import java.util.jar.JarFile import java.util.jar.JarOutputStream import java.util.regex.Pattern @@ -28,177 +28,177 @@ import java.util.stream.Stream * Source jar packager for JavaLike files. The placement is discovered from the package entry. */ class SourceJarCreator( - path: Path, - verbose: Boolean = false + path: Path, + verbose: Boolean = false ) : JarHelper(path, normalize = true, verbose = verbose) { - companion object { - private const val BL = """\p{Blank}*""" - private const val COM_BL = """$BL(?:/\*[^\n]*\*/$BL)*""" - private val PKG_PATTERN: Pattern = - Pattern.compile("""^${COM_BL}package$COM_BL([a-zA-Z1-9.]+)$COM_BL(?:;?.*)$""") - - @JvmStatic - fun extractPackage(line: String): String? = PKG_PATTERN.matcher(line).takeIf { it.matches() }?.group(1) - - private fun isJavaSourceLike(name: String): Boolean { - return name.endsWith(".kt") || name.endsWith(".java") - } + companion object { + private const val BL = """\p{Blank}*""" + private const val COM_BL = """$BL(?:/\*[^\n]*\*/$BL)*""" + private val PKG_PATTERN: Pattern = + Pattern.compile("""^${COM_BL}package$COM_BL([a-zA-Z1-9.]+)$COM_BL(?:;?.*)$""") + + @JvmStatic + fun extractPackage(line: String): String? = + PKG_PATTERN.matcher(line).takeIf { it.matches() }?.group(1) + + private fun isJavaSourceLike(name: String): Boolean { + return name.endsWith(".kt") || name.endsWith(".java") } + } - - sealed class Entry { - class File(val path: Path, val content: ByteArray) : Entry() { - override fun toString(): String = "File $path" - } - - object Directory : Entry() { - override fun toString(): String = "Directory" - } + sealed class Entry { + class File(val path: Path, val content: ByteArray) : Entry() { + override fun toString(): String = "File $path" } - private class JarFilenameHelper { - /** - * A map from the directories in the underlying filesystem to jar directory names. - */ - private val directoryToPackageMap = mutableMapOf() - /** - * Entries for which packages paths could not be located during processing. - */ - private val deferredEntries = mutableMapOf() - - /** - * Locate the directory name for the file as it should appear in the jar. - * - * If the directory could not be located add it to the deferred list and return null. - * - * Files like `package-info.java` could end up getting deferred if they have an annotation embedded on the same - * line or files that have entries such as `/* weird comment */package lala` - */ - fun getFilenameOrDefer(sourceFile: Path, body: ByteArray): String? = - directoryToPackageMap[sourceFile.parent] ?: locatePackagePathOrDefer(sourceFile, body)?.let { - "$it/${sourceFile.fileName}" - } - - /** - * Visit any deferred entries. - * - * @param block the visitor, the second param is the package name and may still be null. - */ - fun visitDeferredEntries(block: (Path, String?, ByteArray) -> Unit) { - deferredEntries.forEach { sourceFile, bytes -> - block(sourceFile, directoryToPackageMap[sourceFile.parent], bytes) - } - } - - private fun locatePackagePathOrDefer(sourceFile: Path, body: ByteArray): String? = - body.inputStream().bufferedReader().useLines { - it.mapNotNull(::extractPackage).firstOrNull()?.replace('.', '/') - }.also { - if (it == null) { - deferredEntries[sourceFile] = body - } - } + object Directory : Entry() { + override fun toString(): String = "Directory" } + } - private val filenameHelper = JarFilenameHelper() - private val entries = TreeMap() + private class JarFilenameHelper { + /** + * A map from the directories in the underlying filesystem to jar directory names. + */ + private val directoryToPackageMap = mutableMapOf() + /** + * Entries for which packages paths could not be located during processing. + */ + private val deferredEntries = mutableMapOf() /** - * Consume a stream of sources, this should contain valid source files and srcjar. + * Locate the directory name for the file as it should appear in the jar. + * + * If the directory could not be located add it to the deferred list and return null. + * + * Files like `package-info.java` could end up getting deferred if they have an annotation embedded on the same + * line or files that have entries such as `/* weird comment */package lala` */ - fun addSources(sources: Stream) { - sources.forEach { path -> - val fileName = path.fileName.toString() - when { - isJavaSourceLike(fileName) -> addJavaLikeSourceFile(path) - fileName.endsWith(".srcjar") -> addSourceJar(path) - } - } - } + fun getFilenameOrDefer(sourceFile: Path, body: ByteArray): String? = + directoryToPackageMap[sourceFile.parent] ?: locatePackagePathOrDefer(sourceFile, body)?.let { + "$it/${sourceFile.fileName}" + } /** - * Add a single source jar + * Visit any deferred entries. + * + * @param block the visitor, the second param is the package name and may still be null. */ - private fun addSourceJar(path: Path) { - if (verbose) { - System.err.println("adding source jar: $path") + fun visitDeferredEntries(block: (Path, String?, ByteArray) -> Unit) { + deferredEntries.forEach { sourceFile, bytes -> + block(sourceFile, directoryToPackageMap[sourceFile.parent], bytes) + } + } + + private fun locatePackagePathOrDefer(sourceFile: Path, body: ByteArray): String? = + body.inputStream().bufferedReader().useLines { + it.mapNotNull(::extractPackage).firstOrNull()?.replace('.', '/') + }.also { + if (it == null) { + deferredEntries[sourceFile] = body } - JarFile(path.toFile()).use { jar -> - for (entry in jar.entries()) { - if (!entry.isDirectory) { - if (isJavaSourceLike(entry.name)) { - jar.getInputStream(entry).readBytes().also { - addEntry(entry.name, path, it) - } - } - } + } + } + + private val filenameHelper = JarFilenameHelper() + private val entries = TreeMap() + + /** + * Consume a stream of sources, this should contain valid source files and srcjar. + */ + fun addSources(sources: Stream) { + sources.forEach { path -> + val fileName = path.fileName.toString() + when { + isJavaSourceLike(fileName) -> addJavaLikeSourceFile(path) + fileName.endsWith(".srcjar") -> addSourceJar(path) + } + } + } + + /** + * Add a single source jar + */ + private fun addSourceJar(path: Path) { + if (verbose) { + System.err.println("adding source jar: $path") + } + JarFile(path.toFile()).use { jar -> + for (entry in jar.entries()) { + if (!entry.isDirectory) { + if (isJavaSourceLike(entry.name)) { + jar.getInputStream(entry).readBytes().also { + addEntry(entry.name, path, it) } + } } + } } - - /** - * Add a single source file. This method uses the [JarFilenameHelper] so it should be used when jar filename - * correction is desired. It should only be used for Java-Like source files. - */ - private fun addJavaLikeSourceFile(sourceFile: Path) { - val bytes = Files.readAllBytes(sourceFile) - filenameHelper.getFilenameOrDefer(sourceFile, bytes)?.also { - addEntry(it, sourceFile, bytes) - } + } + + /** + * Add a single source file. This method uses the [JarFilenameHelper] so it should be used when jar filename + * correction is desired. It should only be used for Java-Like source files. + */ + private fun addJavaLikeSourceFile(sourceFile: Path) { + val bytes = Files.readAllBytes(sourceFile) + filenameHelper.getFilenameOrDefer(sourceFile, bytes)?.also { + addEntry(it, sourceFile, bytes) } + } - fun execute() { + fun execute() { + if (verbose) { + System.err.println("creating source jar file: $jarPath") + } + filenameHelper.visitDeferredEntries { path, jarFilename, bytes -> + if (jarFilename == null) { if (verbose) { - System.err.println("creating source jar file: $jarPath") + val body = bytes.toString(Charset.defaultCharset()) + System.err.println("""could not determine jar entry name for $path. Body:\n$body}""") + } else { + // if not verbose silently add files at the root. + addEntry(path.fileName.toString(), path, bytes) } - filenameHelper.visitDeferredEntries { path, jarFilename, bytes -> - if (jarFilename == null) { - if (verbose) { - val body = bytes.toString(Charset.defaultCharset()) - System.err.println("""could not determine jar entry name for $path. Body:\n$body}""") - } else { - // if not verbose silently add files at the root. - addEntry(path.fileName.toString(), path, bytes) - } - } else { - System.err.println("adding deferred source file $path -> $jarFilename") - addEntry(jarFilename, path, bytes) - } - } - Files.newOutputStream(jarPath).use { - JarOutputStream(it).use { out -> - for ((key, value) in entries) { - try { - when (value) { - is Entry.File -> out.copyEntry(key, value.path, value.content) - is Entry.Directory -> out.copyEntry(key) - } - } catch (throwable: Throwable) { - throw RuntimeException("could not copy JarEntry $key $value", throwable) - } - } + } else { + System.err.println("adding deferred source file $path -> $jarFilename") + addEntry(jarFilename, path, bytes) + } + } + Files.newOutputStream(jarPath).use { + JarOutputStream(it).use { out -> + for ((key, value) in entries) { + try { + when (value) { + is Entry.File -> out.copyEntry(key, value.path, value.content) + is Entry.Directory -> out.copyEntry(key) } + } catch (throwable: Throwable) { + throw RuntimeException("could not copy JarEntry $key $value", throwable) + } } + } } - - private fun addEntry(name: String, path: Path, bytes: ByteArray) { - name.split("/").also { - if (it.size >= 2) { - for (i in ((it.size - 1) downTo 1)) { - val dirName = it.subList(0, i).joinToString("/", postfix = "/") - if (entries.putIfAbsent(dirName, Entry.Directory) != null) { - break - } else if (verbose) { - System.err.println("adding directory: $dirName") - } - } - } + } + + private fun addEntry(name: String, path: Path, bytes: ByteArray) { + name.split("/").also { + if (it.size >= 2) { + for (i in ((it.size - 1) downTo 1)) { + val dirName = it.subList(0, i).joinToString("/", postfix = "/") + if (entries.putIfAbsent(dirName, Entry.Directory) != null) { + break + } else if (verbose) { + System.err.println("adding directory: $dirName") + } } + } + } - val result = entries.putIfAbsent(name, Entry.File(path, bytes)) - require(result as? Entry.Directory != null || result == null) { - "source entry jarName: $name from: $path collides with entry from: ${(result as Entry.File).path}" - } + val result = entries.putIfAbsent(name, Entry.File(path, bytes)) + require(result as? Entry.Directory != null || result == null) { + "source entry jarName: $name from: $path collides with entry from: ${(result as Entry.File).path}" } -} \ No newline at end of file + } +} diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarExtractor.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarExtractor.kt index 29eeccf6e..3a61e5e08 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarExtractor.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarExtractor.kt @@ -18,31 +18,32 @@ package io.bazel.kotlin.builder.utils.jars import java.nio.file.Path import java.util.function.Predicate -class SourceJarExtractor(destDir: Path, val fileMatcher: Predicate = Predicate { true }) : JarExtractor(destDir) { - val jarFiles = mutableListOf() - val sourcesList = mutableListOf() +class SourceJarExtractor(destDir: Path, val fileMatcher: Predicate = Predicate { true }) : + JarExtractor(destDir) { + val jarFiles = mutableListOf() + val sourcesList = mutableListOf() - override fun preWrite(isDirectory: Boolean, target: Path): Boolean { - if (!isDirectory && fileMatcher.test(target.toString())) { - sourcesList.add(target.toString()) - } - return true + override fun preWrite(isDirectory: Boolean, target: Path): Boolean { + if (!isDirectory && fileMatcher.test(target.toString())) { + sourcesList.add(target.toString()) } + return true + } - fun execute() { - destDir.also { - try { - it.toFile().mkdirs() - } catch (ex: Exception) { - throw RuntimeException("could not create unpack directory at $it", ex) - } - } - jarFiles.forEach { - try { - extract(it) - } catch (ex: Throwable) { - throw RuntimeException("error extracting source jar $it", ex) - } - } + fun execute() { + destDir.also { + try { + it.toFile().mkdirs() + } catch (ex: Exception) { + throw RuntimeException("could not create unpack directory at $it", ex) + } } -} \ No newline at end of file + jarFiles.forEach { + try { + extract(it) + } catch (ex: Throwable) { + throw RuntimeException("error extracting source jar $it", ex) + } + } + } +} diff --git a/src/main/kotlin/io/bazel/kotlin/compiler/BUILD.bazel b/src/main/kotlin/io/bazel/kotlin/compiler/BUILD.bazel index d997f18ef..4465aeda0 100644 --- a/src/main/kotlin/io/bazel/kotlin/compiler/BUILD.bazel +++ b/src/main/kotlin/io/bazel/kotlin/compiler/BUILD.bazel @@ -18,10 +18,10 @@ load("//src/main/kotlin:bootstrap.bzl", "kt_bootstrap_library") kt_bootstrap_library( name = "compiler", srcs = glob(["*.kt"]), - visibility = ["//src:__subpackages__"], neverlink_deps = [ "@com_github_jetbrains_kotlin//:kotlin-compiler", "@com_github_jetbrains_kotlin//:kotlin-annotation-processing", "@com_github_jetbrains_kotlin//:kotlin-script-runtime", ], + visibility = ["//src:__subpackages__"], ) diff --git a/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt b/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt index 69fb6310f..2393f3245 100644 --- a/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt +++ b/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt @@ -23,9 +23,10 @@ import org.jetbrains.kotlin.config.Services @Suppress("unused") class BazelK2JVMCompiler(private val delegate: K2JVMCompiler = K2JVMCompiler()) { - fun exec(errStream: java.io.PrintStream, vararg args: kotlin.String): ExitCode { - val arguments = delegate.createArguments().also { delegate.parseArguments(args, it) } - val collector = PrintingMessageCollector(errStream, MessageRenderer.PLAIN_RELATIVE_PATHS, arguments.verbose) - return delegate.exec(collector, Services.EMPTY, arguments) - } -} \ No newline at end of file + fun exec(errStream: java.io.PrintStream, vararg args: kotlin.String): ExitCode { + val arguments = delegate.createArguments().also { delegate.parseArguments(args, it) } + val collector = + PrintingMessageCollector(errStream, MessageRenderer.PLAIN_RELATIVE_PATHS, arguments.verbose) + return delegate.exec(collector, Services.EMPTY, arguments) + } +} diff --git a/src/main/protobuf/worker_protocol.proto b/src/main/protobuf/worker_protocol.proto index dd20384f3..1733d822a 100644 --- a/src/main/protobuf/worker_protocol.proto +++ b/src/main/protobuf/worker_protocol.proto @@ -20,32 +20,32 @@ option java_package = "com.google.devtools.build.lib.worker"; // An input file. message Input { - // The path in the file system where to read this input artifact from. This is - // either a path relative to the execution root (the worker process is - // launched with the working directory set to the execution root), or an - // absolute path. - string path = 1; - - // A hash-value of the contents. The format of the contents is unspecified and - // the digest should be treated as an opaque token. - bytes digest = 2; + // The path in the file system where to read this input artifact from. This is + // either a path relative to the execution root (the worker process is + // launched with the working directory set to the execution root), or an + // absolute path. + string path = 1; + + // A hash-value of the contents. The format of the contents is unspecified and + // the digest should be treated as an opaque token. + bytes digest = 2; } // This represents a single work unit that Blaze sends to the worker. message WorkRequest { - repeated string arguments = 1; + repeated string arguments = 1; - // The inputs that the worker is allowed to read during execution of this - // request. - repeated Input inputs = 2; + // The inputs that the worker is allowed to read during execution of this + // request. + repeated Input inputs = 2; } // The worker sends this message to Blaze when it finished its work on the WorkRequest message. message WorkResponse { - int32 exit_code = 1; + int32 exit_code = 1; - // This is printed to the user after the WorkResponse has been received and is supposed to contain - // compiler warnings / errors etc. - thus we'll use a string type here, which gives us UTF-8 - // encoding. - string output = 2; + // This is printed to the user after the WorkResponse has been received and is supposed to contain + // compiler warnings / errors etc. - thus we'll use a string type here, which gives us UTF-8 + // encoding. + string output = 2; } diff --git a/src/test/Bazel_all_local_tests.xml b/src/test/Bazel_all_local_tests.xml index c2aeb5e5a..a09a3700b 100644 --- a/src/test/Bazel_all_local_tests.xml +++ b/src/test/Bazel_all_local_tests.xml @@ -1,5 +1,6 @@ - + //:all_local_tests - \ No newline at end of file + diff --git a/src/test/data/jvm/basic/helloworld/Main.kt b/src/test/data/jvm/basic/helloworld/Main.kt index 6a6b65d3a..5d6b94427 100644 --- a/src/test/data/jvm/basic/helloworld/Main.kt +++ b/src/test/data/jvm/basic/helloworld/Main.kt @@ -14,15 +14,16 @@ * limitations under the License. */ @file:JvmName("Main") + package helloworld import java.nio.file.Paths -fun main(args :Array) { - if(!Paths.get("tests", "smoke", "data" ,"datafile.txt").toFile().exists()) { - System.err.println("could not read datafile") - System.exit(1) - } - println("bang bang") - System.out.println("boom") +fun main(args: Array) { + if (!Paths.get("tests", "smoke", "data", "datafile.txt").toFile().exists()) { + System.err.println("could not read datafile") + System.exit(1) + } + println("bang bang") + System.out.println("boom") } diff --git a/src/test/data/jvm/basic/propagation/CompileTimeDependent.java b/src/test/data/jvm/basic/propagation/CompileTimeDependent.java index 6d4770652..6894be8e3 100644 --- a/src/test/data/jvm/basic/propagation/CompileTimeDependent.java +++ b/src/test/data/jvm/basic/propagation/CompileTimeDependent.java @@ -18,12 +18,12 @@ import org.junit.Test; public class CompileTimeDependent { + public static void main(String[] args) { + new Stub(); + } + @Test public void justSoIcanUseTheTestAnnotation() { } - - public static void main(String[] args) { - new Stub(); - } } diff --git a/src/test/data/jvm/basic/test_friends/Service.kt b/src/test/data/jvm/basic/test_friends/Service.kt index 276c2f0ec..0509a8b36 100644 --- a/src/test/data/jvm/basic/test_friends/Service.kt +++ b/src/test/data/jvm/basic/test_friends/Service.kt @@ -8,4 +8,4 @@ class Service internal constructor( internal fun iSayHolla(friend: String) { println("holla $friend") } -} \ No newline at end of file +} diff --git a/src/test/data/jvm/basic/testresources/src/AClass.kt b/src/test/data/jvm/basic/testresources/src/AClass.kt index 21a2f12c1..48d00685d 100644 --- a/src/test/data/jvm/basic/testresources/src/AClass.kt +++ b/src/test/data/jvm/basic/testresources/src/AClass.kt @@ -15,10 +15,6 @@ */ package testresources -class AClass() { +class AClass() -} - -class BClass() { - -} +class BClass() diff --git a/src/test/data/jvm/kapt/java/TestAutoValue.java b/src/test/data/jvm/kapt/java/TestAutoValue.java index 549241101..ce5ad5664 100644 --- a/src/test/data/jvm/kapt/java/TestAutoValue.java +++ b/src/test/data/jvm/kapt/java/TestAutoValue.java @@ -20,16 +20,16 @@ @AutoValue public abstract class TestAutoValue { - abstract String name(); - - static Builder builder() { return new AutoValue_TestAutoValue.Builder(); } + abstract String name(); + @AutoValue.Builder abstract static class Builder { abstract Builder setName(String name); + abstract TestAutoValue build(); } diff --git a/src/test/data/jvm/kapt/java/TestJavaService.java b/src/test/data/jvm/kapt/java/TestJavaService.java index 04378fba7..249cbe144 100644 --- a/src/test/data/jvm/kapt/java/TestJavaService.java +++ b/src/test/data/jvm/kapt/java/TestJavaService.java @@ -20,5 +20,6 @@ public interface TestJavaService { @AutoService(TestJavaService.class) - class Impl implements TestJavaService {} + class Impl implements TestJavaService { + } } diff --git a/src/test/data/jvm/kapt/kotlin/TestKtAPNoGenReference.kt b/src/test/data/jvm/kapt/kotlin/TestKtAPNoGenReference.kt index 43706a02f..7aa4351fb 100644 --- a/src/test/data/jvm/kapt/kotlin/TestKtAPNoGenReference.kt +++ b/src/test/data/jvm/kapt/kotlin/TestKtAPNoGenReference.kt @@ -19,11 +19,11 @@ import com.google.auto.value.AutoValue @AutoValue abstract class TestKtValueNoReferences { - abstract fun name(): String + abstract fun name(): String - @AutoValue.Builder - abstract class Builder { - abstract fun setName(name: String): Builder - abstract fun build(): TestKtValueNoReferences - } -} \ No newline at end of file + @AutoValue.Builder + abstract class Builder { + abstract fun setName(name: String): Builder + abstract fun build(): TestKtValueNoReferences + } +} diff --git a/src/test/data/jvm/kapt/kotlin/TestKtService.kt b/src/test/data/jvm/kapt/kotlin/TestKtService.kt index 03434bffc..1116d822d 100644 --- a/src/test/data/jvm/kapt/kotlin/TestKtService.kt +++ b/src/test/data/jvm/kapt/kotlin/TestKtService.kt @@ -18,6 +18,6 @@ package tests.smoke.kapt.kotlin import com.google.auto.service.AutoService interface TestKtService { - @AutoService(TestKtService::class) - class Impl(): TestKtService -} \ No newline at end of file + @AutoService(TestKtService::class) + class Impl() : TestKtService +} diff --git a/src/test/data/jvm/kapt/kotlin/TestKtValue.kt b/src/test/data/jvm/kapt/kotlin/TestKtValue.kt index 851835862..4567e9c43 100644 --- a/src/test/data/jvm/kapt/kotlin/TestKtValue.kt +++ b/src/test/data/jvm/kapt/kotlin/TestKtValue.kt @@ -19,12 +19,12 @@ import com.google.auto.value.AutoValue @AutoValue abstract class TestKtValue { - abstract fun name(): String - fun builder(): Builder = AutoValue_TestKtValue.Builder() + abstract fun name(): String + fun builder(): Builder = AutoValue_TestKtValue.Builder() - @AutoValue.Builder - abstract class Builder { - abstract fun setName(name: String): Builder - abstract fun build(): TestKtValue - } -} \ No newline at end of file + @AutoValue.Builder + abstract class Builder { + abstract fun setName(name: String): Builder + abstract fun build(): TestKtValue + } +} diff --git a/src/test/kotlin/io/bazel/kotlin/KotlinAssertionTestCase.kt b/src/test/kotlin/io/bazel/kotlin/KotlinAssertionTestCase.kt index ecaff2c50..bbf4940a8 100644 --- a/src/test/kotlin/io/bazel/kotlin/KotlinAssertionTestCase.kt +++ b/src/test/kotlin/io/bazel/kotlin/KotlinAssertionTestCase.kt @@ -32,104 +32,110 @@ import kotlin.test.assertTrue import kotlin.test.fail class TestCaseFailedException(name: String? = null, description: String? = null, cause: Throwable) : - AssertionError(""""${name?.let { "jar: $it " } ?: ""} "$description" failed, error: ${cause.message}""", cause) + AssertionError(""""${name?.let { "jar: $it " } ?: ""} "$description" failed, error: ${cause.message}""", + cause) abstract class KotlinAssertionTestCase(root: String) : BasicAssertionTestCase() { - private lateinit var currentFile: File + private lateinit var currentFile: File - private val testRunfileRoot: Path = Paths.get(root).also { - it.toFile().also { file -> - assert(file.exists()) { "runfile directory $root does not exist" } - assert(file.isDirectory) { "runfile directory $root is not a directory" } - } + private val testRunfileRoot: Path = Paths.get(root).also { + it.toFile().also { file -> + assert(file.exists()) { "runfile directory $root does not exist" } + assert(file.isDirectory) { "runfile directory $root is not a directory" } } + } - private inline fun runTestCase(name: String, description: String? = null, op: () -> Unit) = - try { - op() - } catch (t: Throwable) { - when (t) { - is AssertionError -> throw TestCaseFailedException(name, description, t) - is Exception -> throw TestCaseFailedException(name, description, t) - else -> throw t - } - } - - protected fun jarTestCase(name: String, description: String? = null, op: JarFile.() -> Unit) { - currentFile = testRunfileRoot.resolve(name).toFile() - check(currentFile.exists()) { "testFile $name did not exist in test case root $testRunfileRoot" } - runTestCase(name, description) { JarFile(currentFile).op() } + private inline fun runTestCase(name: String, description: String? = null, op: () -> Unit) = + try { + op() + } catch (t: Throwable) { + when (t) { + is AssertionError -> throw TestCaseFailedException(name, description, t) + is Exception -> throw TestCaseFailedException(name, description, t) + else -> throw t + } } - protected fun JarFile.assertContainsEntries(vararg entries: String) { - entries.forEach { - if (this.getJarEntry(it) == null) { - fail("jar ${this.name} did not contain entry $it") - } - } + protected fun jarTestCase(name: String, description: String? = null, op: JarFile.() -> Unit) { + currentFile = testRunfileRoot.resolve(name).toFile() + check(currentFile.exists()) { + "testFile $name did not exist in test case root $testRunfileRoot" } + runTestCase(name, description) { JarFile(currentFile).op() } + } - /** - * Validated the entry is compressed and has the DOS epoch for it's timestamp. - */ - protected fun JarFile.assertEntryCompressedAndNormalizedTimestampYear(entry: String) { - checkNotNull(this.getJarEntry(entry)).also { - check(!it.isDirectory) - assertTrue("$entry is not compressed") { JarEntry.DEFLATED == it.method } - val modifiedTimestamp = LocalDateTime.ofInstant( - Instant.ofEpochMilli(it.lastModifiedTime.toMillis()), ZoneId.systemDefault() - ) - assertTrue("normalized modification time stamps should have year 1980") { modifiedTimestamp.year == 1980 } - } + protected fun JarFile.assertContainsEntries(vararg entries: String) { + entries.forEach { + if (this.getJarEntry(it) == null) { + fail("jar ${this.name} did not contain entry $it") + } } + } - /** - * Assert the manifest in the jar is stamped. - */ - protected fun JarFile.assertManifestStamped() { - assertNotNull( - manifest.mainAttributes.getValue("Target-Label"), "missing manifest entry Target-Label" - ) - assertNotNull( - manifest.mainAttributes.getValue("Injecting-Rule-Kind"), "missing manifest entry Injecting-Rule-Kind" - ) + /** + * Validated the entry is compressed and has the DOS epoch for it's timestamp. + */ + protected fun JarFile.assertEntryCompressedAndNormalizedTimestampYear(entry: String) { + checkNotNull(this.getJarEntry(entry)).also { + check(!it.isDirectory) + assertTrue("$entry is not compressed") { JarEntry.DEFLATED == it.method } + val modifiedTimestamp = LocalDateTime.ofInstant( + Instant.ofEpochMilli(it.lastModifiedTime.toMillis()), ZoneId.systemDefault() + ) + assertTrue("normalized modification time stamps should have year 1980") { + modifiedTimestamp.year == 1980 + } } + } - protected fun validateFileSha256(expected: String) { - val result = Hashing.sha256().hashBytes(Files.readAllBytes(currentFile.toPath())).toString() - assertEquals(expected, result, "file $currentFile did not hash as expected") - } + /** + * Assert the manifest in the jar is stamped. + */ + protected fun JarFile.assertManifestStamped() { + assertNotNull( + manifest.mainAttributes.getValue("Target-Label"), "missing manifest entry Target-Label" + ) + assertNotNull( + manifest.mainAttributes.getValue("Injecting-Rule-Kind"), + "missing manifest entry Injecting-Rule-Kind" + ) + } - protected fun JarFile.assertDoesNotContainEntries(vararg entries: String) { - entries.forEach { - if (this.getJarEntry(it) != null) { - fail("jar ${this.name} contained entry $it") - } - } + protected fun validateFileSha256(expected: String) { + val result = Hashing.sha256().hashBytes(Files.readAllBytes(currentFile.toPath())).toString() + assertEquals(expected, result, "file $currentFile did not hash as expected") + } + + protected fun JarFile.assertDoesNotContainEntries(vararg entries: String) { + entries.forEach { + if (this.getJarEntry(it) != null) { + fail("jar ${this.name} contained entry $it") + } } + } - override fun String.resolveDirectory(): File = - if (startsWith("/")) - trimStart('/').split("/").let { File(it.take(it.size - 1).joinToString(File.separator)) } - else - testRunfileRoot.toFile() + override fun String.resolveDirectory(): File = + if (startsWith("/")) + trimStart('/').split("/").let { File(it.take(it.size - 1).joinToString(File.separator)) } + else + testRunfileRoot.toFile() } abstract class BasicAssertionTestCase { - protected fun assertExecutableRunfileSucceeds(executable: String, description: String? = null) { - ProcessBuilder().command("bash", "-c", Paths.get(executable).fileName.toString()) - .also { it.directory(executable.resolveDirectory()) } - .start().let { - it.waitFor(5, TimeUnit.SECONDS) - assert(it.exitValue() == 0) { - throw TestCaseFailedException( - description = description, - cause = RuntimeException("non-zero return code: ${it.exitValue()}") - ) - } - } - } + protected fun assertExecutableRunfileSucceeds(executable: String, description: String? = null) { + ProcessBuilder().command("bash", "-c", Paths.get(executable).fileName.toString()) + .also { it.directory(executable.resolveDirectory()) } + .start().let { + it.waitFor(5, TimeUnit.SECONDS) + assert(it.exitValue() == 0) { + throw TestCaseFailedException( + description = description, + cause = RuntimeException("non-zero return code: ${it.exitValue()}") + ) + } + } + } - protected open fun String.resolveDirectory(): File = - trimStart('/').split("/").let { File(it.take(it.size - 1).joinToString(File.separator)) } -} \ No newline at end of file + protected open fun String.resolveDirectory(): File = + trimStart('/').split("/").let { File(it.take(it.size - 1).joinToString(File.separator)) } +} diff --git a/src/test/kotlin/io/bazel/kotlin/KotlinJvm13Test.kt b/src/test/kotlin/io/bazel/kotlin/KotlinJvm13Test.kt index 1b56ddfe3..4879e49e0 100644 --- a/src/test/kotlin/io/bazel/kotlin/KotlinJvm13Test.kt +++ b/src/test/kotlin/io/bazel/kotlin/KotlinJvm13Test.kt @@ -3,10 +3,14 @@ package io.bazel.kotlin import org.junit.Test class KotlinJvm13Test { - @Test fun testFoo() { - when (val foo = "TryIng Mixed Case".toLowerCase()) { - "trying mixed case" -> { println(foo) } - else -> {} - } + @Test + fun testFoo() { + when (val foo = "TryIng Mixed Case".toLowerCase()) { + "trying mixed case" -> { + println(foo) + } + else -> { + } } + } } diff --git a/src/test/kotlin/io/bazel/kotlin/KotlinJvmBasicAssertionTest.kt b/src/test/kotlin/io/bazel/kotlin/KotlinJvmBasicAssertionTest.kt index 0c3ae8d32..5a0d1c462 100644 --- a/src/test/kotlin/io/bazel/kotlin/KotlinJvmBasicAssertionTest.kt +++ b/src/test/kotlin/io/bazel/kotlin/KotlinJvmBasicAssertionTest.kt @@ -17,51 +17,80 @@ package io.bazel.kotlin import org.junit.Test - -class KotlinJvmBasicAssertionTest: KotlinAssertionTestCase("src/test/data/jvm/basic") { - @Test - fun testResourceMerging() { - jarTestCase("test_embed_resources.jar", description = "The rules should support including resource directories") { - assertContainsEntries( - "testresources/AClass.class", - "testresources/BClass.class", - "src/test/data/jvm/basic/testresources/resources/one/alsoAFile.txt", - "src/test/data/jvm/basic/testresources/resources/one/two/aFile.txt" - ) - } - jarTestCase("test_merge_resourcesjar.jar", description = "the rules should support merging jars") { - assertContainsEntries("testresources/AClass.class", "testresources/BClass.class", "pkg/file.txt") - } - jarTestCase("test_embed_resources_strip_prefix.jar", description = "the rules should support the resource_strip_prefix attribute") { - assertContainsEntries("testresources/AClass.class", "testresources/BClass.class", "one/two/aFile.txt", "one/alsoAFile.txt") - } - jarTestCase("conventional_strip_resources.jar", description = "the rules should support conventional prefix stripping") { - assertContainsEntries("main.txt", "test.txt") - } +class KotlinJvmBasicAssertionTest : KotlinAssertionTestCase("src/test/data/jvm/basic") { + @Test + fun testResourceMerging() { + jarTestCase( + "test_embed_resources.jar", + description = "The rules should support including resource directories" + ) { + assertContainsEntries( + "testresources/AClass.class", + "testresources/BClass.class", + "src/test/data/jvm/basic/testresources/resources/one/alsoAFile.txt", + "src/test/data/jvm/basic/testresources/resources/one/two/aFile.txt" + ) } - - @Test - fun testPropogateDeps() { - assertExecutableRunfileSucceeds( - "propagation_rt_via_export_consumer", - description = "Runtime deps should be inherited transitively from `exported` deps" - ) - assertExecutableRunfileSucceeds( - "propagation_rt_via_runtime_deps_consumer", - description = "Runtime deps should be inherited transitively from `runtime_deps`" - ) + jarTestCase( + "test_merge_resourcesjar.jar", + description = "the rules should support merging jars" + ) { + assertContainsEntries( + "testresources/AClass.class", + "testresources/BClass.class", + "pkg/file.txt" + ) + } + jarTestCase( + "test_embed_resources_strip_prefix.jar", + description = "the rules should support the resource_strip_prefix attribute" + ) { + assertContainsEntries( + "testresources/AClass.class", + "testresources/BClass.class", + "one/two/aFile.txt", + "one/alsoAFile.txt" + ) + } + jarTestCase( + "conventional_strip_resources.jar", + description = "the rules should support conventional prefix stripping" + ) { + assertContainsEntries("main.txt", "test.txt") } + } - @Test - fun testModuleNaming() { - jarTestCase("test_module_name_bin.jar", description = "A binary rule should support default module naming") { - assertContainsEntries("META-INF/src_test_data_jvm_basic-test_module_name_bin.kotlin_module") - } - jarTestCase("test_module_name_lib.jar", description = "A library rule should support default module naming") { - assertContainsEntries("META-INF/src_test_data_jvm_basic-test_module_name_lib.kotlin_module") - } - jarTestCase("test_module_name_attr_lib.jar", description = "The kotlin rules should support the module_name attribute") { - assertContainsEntries("META-INF/hello-module.kotlin_module") - } + @Test + fun testPropogateDeps() { + assertExecutableRunfileSucceeds( + "propagation_rt_via_export_consumer", + description = "Runtime deps should be inherited transitively from `exported` deps" + ) + assertExecutableRunfileSucceeds( + "propagation_rt_via_runtime_deps_consumer", + description = "Runtime deps should be inherited transitively from `runtime_deps`" + ) + } + + @Test + fun testModuleNaming() { + jarTestCase( + "test_module_name_bin.jar", + description = "A binary rule should support default module naming" + ) { + assertContainsEntries("META-INF/src_test_data_jvm_basic-test_module_name_bin.kotlin_module") + } + jarTestCase( + "test_module_name_lib.jar", + description = "A library rule should support default module naming" + ) { + assertContainsEntries("META-INF/src_test_data_jvm_basic-test_module_name_lib.kotlin_module") + } + jarTestCase( + "test_module_name_attr_lib.jar", + description = "The kotlin rules should support the module_name attribute" + ) { + assertContainsEntries("META-INF/hello-module.kotlin_module") } + } } diff --git a/src/test/kotlin/io/bazel/kotlin/KotlinJvmDaggerExampleTest.kt b/src/test/kotlin/io/bazel/kotlin/KotlinJvmDaggerExampleTest.kt index f236eae0c..836d20f78 100644 --- a/src/test/kotlin/io/bazel/kotlin/KotlinJvmDaggerExampleTest.kt +++ b/src/test/kotlin/io/bazel/kotlin/KotlinJvmDaggerExampleTest.kt @@ -21,11 +21,11 @@ import org.junit.Test * These tests verify properties of the example. */ class KotlinJvmDaggerExampleTest : BasicAssertionTestCase() { - @Test - fun daggerExampleIsRunnable() { - assertExecutableRunfileSucceeds( - "//examples/dagger/coffee_app", - description = "the dagger coffee_app should execute successfully" - ) - } -} \ No newline at end of file + @Test + fun daggerExampleIsRunnable() { + assertExecutableRunfileSucceeds( + "//examples/dagger/coffee_app", + description = "the dagger coffee_app should execute successfully" + ) + } +} diff --git a/src/test/kotlin/io/bazel/kotlin/KotlinJvmFriendsVisibilityTest.kt b/src/test/kotlin/io/bazel/kotlin/KotlinJvmFriendsVisibilityTest.kt index a172dabb8..32d71a936 100644 --- a/src/test/kotlin/io/bazel/kotlin/KotlinJvmFriendsVisibilityTest.kt +++ b/src/test/kotlin/io/bazel/kotlin/KotlinJvmFriendsVisibilityTest.kt @@ -1,18 +1,18 @@ package io.bazel.kotlin -import test.Service import test.DEFAULT_FRIEND +import test.Service /** * This test validates that friend visibility is working. Services and DEFAULT_FRIEND are internal another compilation * unit. */ class KotlinJvmFriendsVisibilityTest { - val service: Service = Service() + val service: Service = Service() - @org.junit.Test - fun testCanAccessFriendMembers() { - println(service.value) - println(service.iSayHolla(DEFAULT_FRIEND)) - } -} \ No newline at end of file + @org.junit.Test + fun testCanAccessFriendMembers() { + println(service.value) + println(service.iSayHolla(DEFAULT_FRIEND)) + } +} diff --git a/src/test/kotlin/io/bazel/kotlin/KotlinJvmKaptAssertionTest.kt b/src/test/kotlin/io/bazel/kotlin/KotlinJvmKaptAssertionTest.kt index 7d5fc5c11..a3085d867 100644 --- a/src/test/kotlin/io/bazel/kotlin/KotlinJvmKaptAssertionTest.kt +++ b/src/test/kotlin/io/bazel/kotlin/KotlinJvmKaptAssertionTest.kt @@ -18,63 +18,86 @@ package io.bazel.kotlin import org.junit.Test class KotlinJvmKaptAssertionTest : KotlinAssertionTestCase("src/test/data/jvm/kapt") { - @Test - fun testKotlinOnlyAnnotationProcessing() { - jarTestCase("ap_kotlin.jar", description = "annotation processing should work") { - assertContainsEntries("tests/smoke/kapt/kotlin/AutoValue_TestKtValue.class") - } - jarTestCase("ap_kotlin_mixed_no_plugin.jar", description = "annotation processing should not kick in for deps.") { - assertDoesNotContainEntries( - "tests/smoke/kapt/kotlin/AutoValue_TestKtValue.class", - "tests/smoke/kapt/java/TestAutoValue\$Builder.class" - ) - } - jarTestCase("ap_kotlin_resources.jar", description = "annotation processed artifacts should contain resources") { - assertContainsEntries("META-INF/services/tests.smoke.kapt.kotlin.TestKtService") - } + @Test + fun testKotlinOnlyAnnotationProcessing() { + jarTestCase("ap_kotlin.jar", description = "annotation processing should work") { + assertContainsEntries("tests/smoke/kapt/kotlin/AutoValue_TestKtValue.class") } + jarTestCase( + "ap_kotlin_mixed_no_plugin.jar", + description = "annotation processing should not kick in for deps." + ) { + assertDoesNotContainEntries( + "tests/smoke/kapt/kotlin/AutoValue_TestKtValue.class", + "tests/smoke/kapt/java/TestAutoValue\$Builder.class" + ) + } + jarTestCase( + "ap_kotlin_resources.jar", + description = "annotation processed artifacts should contain resources" + ) { + assertContainsEntries("META-INF/services/tests.smoke.kapt.kotlin.TestKtService") + } + } - @Test - fun testMixedModeAnnotationProcessing() { - jarTestCase("ap_kotlin_mixed.jar", description = "annotation processing should work for mixed mode targets") { - assertContainsEntries( - "tests/smoke/kapt/kotlin/AutoValue_TestKtValue.class", - "tests/smoke/kapt/java/TestAutoValue\$Builder.class" - ) - } - jarTestCase("ap_kotlin_resources_mixed.jar", description = "annotation processors generating resources should work for mixed mode") { - assertContainsEntries("META-INF/services/tests.smoke.kapt.kotlin.TestKtService", "META-INF/services/tests.smoke.kapt.java.TestJavaService") - } - jarTestCase( - "ap_kotlin_mixed_inherit_plugin_via_exported_deps.jar", - description = "annotation processors should be inherited transitively" - ) { - assertContainsEntries( - "META-INF/services/tests.smoke.kapt.kotlin.TestKtService", - "META-INF/services/tests.smoke.kapt.java.TestJavaService", - "tests/smoke/kapt/kotlin/AutoValue_TestKtValue.class", - "tests/smoke/kapt/java/TestAutoValue\$Builder.class" - ) - } + @Test + fun testMixedModeAnnotationProcessing() { + jarTestCase( + "ap_kotlin_mixed.jar", + description = "annotation processing should work for mixed mode targets" + ) { + assertContainsEntries( + "tests/smoke/kapt/kotlin/AutoValue_TestKtValue.class", + "tests/smoke/kapt/java/TestAutoValue\$Builder.class" + ) + } + jarTestCase( + "ap_kotlin_resources_mixed.jar", + description = "annotation processors generating resources should work for mixed mode" + ) { + assertContainsEntries( + "META-INF/services/tests.smoke.kapt.kotlin.TestKtService", + "META-INF/services/tests.smoke.kapt.java.TestJavaService" + ) } + jarTestCase( + "ap_kotlin_mixed_inherit_plugin_via_exported_deps.jar", + description = "annotation processors should be inherited transitively" + ) { + assertContainsEntries( + "META-INF/services/tests.smoke.kapt.kotlin.TestKtService", + "META-INF/services/tests.smoke.kapt.java.TestJavaService", + "tests/smoke/kapt/kotlin/AutoValue_TestKtValue.class", + "tests/smoke/kapt/java/TestAutoValue\$Builder.class" + ) + } + } - @Test - fun testMultiPlugins() { - jarTestCase("ap_kotlin_mixed_multiple_plugins.jar", description = "annotation processing should work for multiple plugins") { - assertContainsEntries( - "META-INF/services/tests.smoke.kapt.kotlin.TestKtService", - "META-INF/services/tests.smoke.kapt.java.TestJavaService", - "tests/smoke/kapt/kotlin/AutoValue_TestKtValue.class", - "tests/smoke/kapt/java/TestAutoValue\$Builder.class" - ) - } - jarTestCase("ap_kotlin_mixed_multiple_plugins_one_without_processor_class.jar", - description = "annotation processing should not work unless a processor class is provided") { - assertContainsEntries("META-INF/services/tests.smoke.kapt.kotlin.TestKtService", "META-INF/services/tests.smoke.kapt.java.TestJavaService") - assertDoesNotContainEntries( - "tests/smoke/kapt/java/AutoValue_TestAPNoGenReferences.class", - "tests/smoke/kapt/kotlin/AutoValue_TestKtValueNoReferences.class" - ) - } + @Test + fun testMultiPlugins() { + jarTestCase( + "ap_kotlin_mixed_multiple_plugins.jar", + description = "annotation processing should work for multiple plugins" + ) { + assertContainsEntries( + "META-INF/services/tests.smoke.kapt.kotlin.TestKtService", + "META-INF/services/tests.smoke.kapt.java.TestJavaService", + "tests/smoke/kapt/kotlin/AutoValue_TestKtValue.class", + "tests/smoke/kapt/java/TestAutoValue\$Builder.class" + ) + } + jarTestCase( + "ap_kotlin_mixed_multiple_plugins_one_without_processor_class.jar", + description = "annotation processing should not work unless a processor class is provided" + ) { + assertContainsEntries( + "META-INF/services/tests.smoke.kapt.kotlin.TestKtService", + "META-INF/services/tests.smoke.kapt.java.TestJavaService" + ) + assertDoesNotContainEntries( + "tests/smoke/kapt/java/AutoValue_TestAPNoGenReferences.class", + "tests/smoke/kapt/kotlin/AutoValue_TestKtValueNoReferences.class" + ) } -} \ No newline at end of file + } +} diff --git a/src/test/kotlin/io/bazel/kotlin/KotlinNormalizationAssertionTest.kt b/src/test/kotlin/io/bazel/kotlin/KotlinNormalizationAssertionTest.kt index fde10d161..1124c21f1 100644 --- a/src/test/kotlin/io/bazel/kotlin/KotlinNormalizationAssertionTest.kt +++ b/src/test/kotlin/io/bazel/kotlin/KotlinNormalizationAssertionTest.kt @@ -18,37 +18,36 @@ package io.bazel.kotlin import org.junit.Ignore import org.junit.Test - class KotlinNormalizationAssertionTest : KotlinAssertionTestCase("src/test/data/jvm/basic") { - /* - * (hsyed) This test is running locally because things hash differently on the ci servers. Don't have the time to - * look into it. - * - * The hashes can change between kotlin compiler versions so this approach isn't sustainable. - */ - // (cgruber) per the above, this relies on hashes, which are volatile between kotlinc versions, - // so I'm disabling it. - @Ignore - @Test - fun testJarNormalization() { - jarTestCase( - name = "test_module_name_lib.jar", - description = "Builder jars should be normalized with and include stamp data" - ) { - validateFileSha256("1d26035bda6f384b9cc6bbe5a5bf0727b4da0aeec59545c421de32775149d4cf") - assertManifestStamped() - assertEntryCompressedAndNormalizedTimestampYear("helloworld/Main.class") - } - jarTestCase( - name = "test_embed_resources.jar", - description = "Merging resources into the main output jar should still result in a normalized jar" - ) { - validateFileSha256("ff35e9779be25c5803ab74cd5cee46bfd35da9412fe78395d1ebc2fb2e20880a") - assertManifestStamped() - assertEntryCompressedAndNormalizedTimestampYear("testresources/AClass.class") - assertEntryCompressedAndNormalizedTimestampYear( - "src/test/data/jvm/basic/testresources/resources/one/two/aFile.txt" - ) - } + /* + * (hsyed) This test is running locally because things hash differently on the ci servers. Don't have the time to + * look into it. + * + * The hashes can change between kotlin compiler versions so this approach isn't sustainable. + */ + // (cgruber) per the above, this relies on hashes, which are volatile between kotlinc versions, + // so I'm disabling it. + @Ignore + @Test + fun testJarNormalization() { + jarTestCase( + name = "test_module_name_lib.jar", + description = "Builder jars should be normalized with and include stamp data" + ) { + validateFileSha256("1d26035bda6f384b9cc6bbe5a5bf0727b4da0aeec59545c421de32775149d4cf") + assertManifestStamped() + assertEntryCompressedAndNormalizedTimestampYear("helloworld/Main.class") + } + jarTestCase( + name = "test_embed_resources.jar", + description = "Merging resources into the main output jar should still result in a normalized jar" + ) { + validateFileSha256("ff35e9779be25c5803ab74cd5cee46bfd35da9412fe78395d1ebc2fb2e20880a") + assertManifestStamped() + assertEntryCompressedAndNormalizedTimestampYear("testresources/AClass.class") + assertEntryCompressedAndNormalizedTimestampYear( + "src/test/data/jvm/basic/testresources/resources/one/two/aFile.txt" + ) } -} \ No newline at end of file + } +} diff --git a/src/test/kotlin/io/bazel/kotlin/builder/BUILD b/src/test/kotlin/io/bazel/kotlin/builder/BUILD index 9c366abfb..6ae01a275 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/BUILD +++ b/src/test/kotlin/io/bazel/kotlin/builder/BUILD @@ -18,7 +18,7 @@ load("//src/test/kotlin/io/bazel/kotlin:defs.bzl", "kt_rules_test") _COMMON_DEPS = [ "//src/main/kotlin/io/bazel/kotlin/builder", - "//src/main/kotlin/io/bazel/kotlin/builder/toolchain", + "//src/main/kotlin/io/bazel/kotlin/builder/toolchain", "//src/main/kotlin/io/bazel/kotlin/builder/utils:utils", "//src/main/protobuf:kotlin_model_java_proto", "//src/main/protobuf:deps_java_proto", @@ -57,8 +57,8 @@ java_library( test_suite( name = "builder_tests", tests = [ - "//src/test/kotlin/io/bazel/kotlin/builder/utils", "//src/test/kotlin/io/bazel/kotlin/builder/tasks", + "//src/test/kotlin/io/bazel/kotlin/builder/utils", ], visibility = ["//visibility:public"], ) diff --git a/src/test/kotlin/io/bazel/kotlin/builder/Deps.java b/src/test/kotlin/io/bazel/kotlin/builder/Deps.java index 7f754cfe4..4a188f384 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/Deps.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/Deps.java @@ -19,135 +19,136 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import io.bazel.kotlin.builder.utils.BazelRunFiles; + +import javax.annotation.Nullable; import java.util.List; import java.util.Optional; import java.util.Properties; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.annotation.Nullable; public final class Deps { - @SuppressWarnings({"WeakerAccess", "unused"}) - @AutoValue - public abstract static class Dep { - public abstract String label(); + @SuppressWarnings({"WeakerAccess", "unused"}) + @AutoValue + public abstract static class Dep { + public static Builder builder() { + return new AutoValue_Deps_Dep.Builder().runtimeDeps(ImmutableList.of()); + } - public abstract String moduleName(); + /** + * Collect all of the compile jars of all the dependencies. + */ + public static Stream classpathOf(Dep... dependencies) { + return Stream.of(dependencies).flatMap(it -> it.compileJars().stream()); + } - public abstract List runtimeDeps(); + /** + * Import a single dep. Similar to a `kt_jvm_import` or a `kt_js_import`. + */ + public static Dep importJar(String label, String compileJar) { + return Dep.builder() + .label(label) + .compileJars( + ImmutableList.of(BazelRunFiles.resolveVerified(compileJar).getAbsolutePath())) + .build(); + } - public abstract List compileJars(); + /** + * Reads dependency path from jvm_args for a given label, provided that the label has been added + * as a jvm property. + *

+ * See src/test/kotlin/io/bazel/kotlin/defs.bzl for an example of proper label and runfile + * passing. + * + * @param label The label of the resource expected to be included + * @return Dep reprenseting the resource + * @throws IllegalArgumentException if the label does not exist. + */ + protected static Dep fromLabel(String label) { + // jvm properties do not allow slashes or :. + String key = label.replaceAll("/", ".").replaceAll(":", "."); + Properties properties = System.getProperties(); + Preconditions.checkArgument(properties.containsKey(key), + String.format("Unable to find %s in properties:\n%s", key, + properties.keySet() + .stream() + .map(Object::toString) + .collect(Collectors.joining("\n")))); + return Dep.builder() + .label(label) + .compileJars( + ImmutableList.of( + BazelRunFiles.resolveVerified(properties.getProperty(key)).getPath())) + .build(); + } - @Nullable - public abstract String sourceJar(); + public abstract String label(); - @Nullable - public abstract String jdeps(); + public abstract String moduleName(); - public static Builder builder() { - return new AutoValue_Deps_Dep.Builder().runtimeDeps(ImmutableList.of()); - } + public abstract List runtimeDeps(); - public final String singleCompileJar() { - Preconditions.checkState(compileJars().size() == 1); - return compileJars().get(0); - } + public abstract List compileJars(); - @SuppressWarnings("UnusedReturnValue") - @AutoValue.Builder - public abstract static class Builder { - public abstract Builder compileJars(List compileJars); + @Nullable + public abstract String sourceJar(); - public abstract Builder label(String label); + @Nullable + public abstract String jdeps(); - public abstract Builder runtimeDeps(List runtimeDeps); + public final String singleCompileJar() { + Preconditions.checkState(compileJars().size() == 1); + return compileJars().get(0); + } - public abstract Builder moduleName(String moduleName); + @SuppressWarnings("UnusedReturnValue") + @AutoValue.Builder + public abstract static class Builder { + public abstract Builder compileJars(List compileJars); - abstract String label(); + public abstract Builder label(String label); - abstract Optional moduleName(); + public abstract Builder runtimeDeps(List runtimeDeps); - abstract Dep autoBuild(); + public abstract Builder moduleName(String moduleName); - public abstract Builder sourceJar(String sourceJar); + abstract String label(); - public abstract Builder jdeps(String jdeps); + abstract Optional moduleName(); - public Dep build() { - if (!moduleName().isPresent()) { - moduleName(label()); - } - return autoBuild(); - } - } + abstract Dep autoBuild(); - /** - * Collect all of the compile jars of all the dependencies. - */ - public static Stream classpathOf(Dep... dependencies) { - return Stream.of(dependencies).flatMap(it -> it.compileJars().stream()); - } + public abstract Builder sourceJar(String sourceJar); - /** - * Import a single dep. Similar to a `kt_jvm_import` or a `kt_js_import`. - */ - public static Dep importJar(String label, String compileJar) { - return Dep.builder() - .label(label) - .compileJars( - ImmutableList.of(BazelRunFiles.resolveVerified(compileJar).getAbsolutePath())) - .build(); - } + public abstract Builder jdeps(String jdeps); - /** - * Reads dependency path from jvm_args for a given label, provided that the label has been added - * as a jvm property. - *

- * See src/test/kotlin/io/bazel/kotlin/defs.bzl for an example of proper label and runfile - * passing. - * - * @param label The label of the resource expected to be included - * @return Dep reprenseting the resource - * @throws IllegalArgumentException if the label does not exist. - */ - protected static Dep fromLabel(String label) { - // jvm properties do not allow slashes or :. - String key = label.replaceAll("/", ".").replaceAll(":", "."); - Properties properties = System.getProperties(); - Preconditions.checkArgument(properties.containsKey(key), - String.format("Unable to find %s in properties:\n%s", key, - properties.keySet() - .stream() - .map(Object::toString) - .collect(Collectors.joining("\n")))); - return Dep.builder() - .label(label) - .compileJars( - ImmutableList.of( - BazelRunFiles.resolveVerified(properties.getProperty(key)).getPath())) - .build(); + public Dep build() { + if (!moduleName().isPresent()) { + moduleName(label()); + } + return autoBuild(); + } + } } - } - @AutoValue - public abstract static class AnnotationProcessor { - abstract String processClass(); + @AutoValue + public abstract static class AnnotationProcessor { + public static Builder builder() { + return new AutoValue_Deps_AnnotationProcessor.Builder(); + } - abstract Set processorPath(); + abstract String processClass(); - public static Builder builder() { - return new AutoValue_Deps_AnnotationProcessor.Builder(); - } + abstract Set processorPath(); - @AutoValue.Builder - public abstract static class Builder { - public abstract Builder processClass(String processClass); + @AutoValue.Builder + public abstract static class Builder { + public abstract Builder processClass(String processClass); - public abstract Builder processorPath(Set processorPath); + public abstract Builder processorPath(Set processorPath); - public abstract AnnotationProcessor build(); + public abstract AnnotationProcessor build(); + } } - } } diff --git a/src/test/kotlin/io/bazel/kotlin/builder/DirectoryType.java b/src/test/kotlin/io/bazel/kotlin/builder/DirectoryType.java index 10e19ce7c..6f84666d9 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/DirectoryType.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/DirectoryType.java @@ -8,31 +8,31 @@ import java.util.EnumSet; public enum DirectoryType { - SOURCES("sources", Paths.get("sources")), - CLASSES("compiled classes", Paths.get("classes")), - GENERATED_CLASSES("generated classes", Paths.get("generated_classes")), - TEMP("temp directory", Paths.get("temp")), - SOURCE_GEN("generated sources directory", Paths.get("generated_sources")); + SOURCES("sources", Paths.get("sources")), + CLASSES("compiled classes", Paths.get("classes")), + GENERATED_CLASSES("generated classes", Paths.get("generated_classes")), + TEMP("temp directory", Paths.get("temp")), + SOURCE_GEN("generated sources directory", Paths.get("generated_sources")); - final String name; - final Path relativePath; + final String name; + final Path relativePath; - DirectoryType(String name, Path relativePath) { - this.name = name; - this.relativePath = relativePath; - } + DirectoryType(String name, Path relativePath) { + this.name = name; + this.relativePath = relativePath; + } - Path resolve(Path root) { - return root.resolve(relativePath); - } + static void createAll(Path root, EnumSet types) { + for (DirectoryType instanceType : types) { + try { + Files.createDirectory(instanceType.resolve(root)); + } catch (IOException e) { + throw new UncheckedIOException(instanceType.name, e); + } + } + } - static void createAll(Path root, EnumSet types) { - for (DirectoryType instanceType : types) { - try { - Files.createDirectory(instanceType.resolve(root)); - } catch (IOException e) { - throw new UncheckedIOException(instanceType.name, e); - } + Path resolve(Path root) { + return root.resolve(relativePath); } - } } diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java index 0569e975e..f89145d7b 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java @@ -21,14 +21,8 @@ import io.bazel.kotlin.model.KotlinToolchainInfo; import io.bazel.kotlin.model.Platform; import io.bazel.kotlin.model.RuleKind; -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintStream; -import java.io.UncheckedIOException; + +import java.io.*; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; @@ -47,184 +41,184 @@ import static java.nio.charset.StandardCharsets.UTF_8; abstract class KotlinAbstractTestBuilder { - private static final Path BAZEL_TEST_DIR = - FileSystems.getDefault().getPath(System.getenv("TEST_TMPDIR")); - - private static final AtomicInteger counter = new AtomicInteger(0); - private final CompilationTaskInfo.Builder infoBuilder = CompilationTaskInfo.newBuilder(); - private Path instanceRoot = null; - private String label = null; - private List outLines = null; - - abstract void setupForNext(CompilationTaskInfo.Builder infoBuilder); - - abstract T buildTask(); - - final String label() { - return Objects.requireNonNull(label); - } - - final Path instanceRoot() { - return Objects.requireNonNull(instanceRoot); - } - - @SuppressWarnings("WeakerAccess") - public final List outLines() { - return outLines; - } - - public final void resetForNext() { - outLines = null; - label = "a_test_" + counter.incrementAndGet(); - infoBuilder - .setLabel("//some/bogus:" + label()) - .setModuleName("some_bogus_module") - .setPlatform(Platform.JVM) - .setRuleKind(RuleKind.LIBRARY) - .setToolchainInfo( - KotlinToolchainInfo.newBuilder() - .setCommon( - KotlinToolchainInfo.Common.newBuilder() - .setApiVersion("1.2") - .setCoroutines("enabled") - .setLanguageVersion("1.2")) - .setJvm(KotlinToolchainInfo.Jvm.newBuilder().setJvmTarget("1.8"))); - try { - this.instanceRoot = Files.createTempDirectory(BAZEL_TEST_DIR, label); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - setupForNext(infoBuilder); - } - - final Path directory(DirectoryType type) { - return type.resolve(instanceRoot); - } - - @SuppressWarnings("unused") - public final void setDebugTags(String... tags) { - infoBuilder.addAllDebug(Arrays.asList(tags)); - } - - final Path writeFile(DirectoryType dirType, String filename, String[] lines) { - Path path = directory(dirType).resolve(filename).toAbsolutePath(); - try (FileOutputStream fos = new FileOutputStream(path.toFile())) { - fos.write(String.join("\n", lines).getBytes(UTF_8)); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - return path; - } - - public final Path writeSourceFile(String filename, String[] lines) { - return writeFile(DirectoryType.SOURCES, filename, lines); - } - - public final Path writeGeneratedSourceFile(String filename, String[] lines) { - return writeFile(DirectoryType.SOURCE_GEN, filename, lines); - } - - private R runCompileTask( - CompilationTaskInfo info, T task, BiFunction operation) { - String curDir = System.getProperty("user.dir"); - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - try (PrintStream outputStream = new PrintStream(byteArrayOutputStream)) { - System.setProperty("user.dir", instanceRoot().toAbsolutePath().toString()); - return operation.apply(new CompilationTaskContext(info, outputStream), task); - } finally { - System.setProperty("user.dir", curDir); - outLines = - Collections.unmodifiableList( - new BufferedReader( - new InputStreamReader( - new ByteArrayInputStream(byteArrayOutputStream.toByteArray()))) - .lines() - .peek(System.err::println) - .collect(Collectors.toList())); - } - } - - final R runCompileTask(BiFunction operation) { - T task = buildTask(); - return runCompileTask(infoBuilder.build(), task, (ctx, t) -> operation.apply(ctx, task)); - } - - /** - * Run a compilation task expecting it to fail with a {@link CompilationStatusException}. - * - * @param task the compilation task - * @param validator a consumer for the output produced by the task. - */ - public final void runFailingCompileTaskAndValidateOutput( - Runnable task, Consumer> validator) { - try { - task.run(); - } catch (CompilationStatusException ex) { - validator.accept(outLines()); - return; - } - throw new RuntimeException("compilation task should have failed."); - } - - public final void assertFilesExist(DirectoryType dir, String... paths) { - assertFileExistence(resolved(dir, paths), true); - } - - final void assertFilesExist(String... paths) { - assertFileExistence(Stream.of(paths).map(Paths::get), true); - } - - @SuppressWarnings("unused") - public final void assertFilesDoNotExist(DirectoryType dir, String... filePath) { - assertFileExistence(resolved(dir, filePath), false); - } - - private static void assertFileExistence(Stream pathStream, boolean shouldExist) { - pathStream.forEach( - path -> { - if (shouldExist) - assertWithMessage("file did not exist: " + path).that(path.toFile().exists()).isTrue(); - else assertWithMessage("file existed: " + path).that(path.toFile().exists()).isFalse(); - }); - } - - private Stream resolved(DirectoryType dir, String... filePath) { - Path directory = directory(dir); - return Stream.of(filePath).map(f -> directory.resolve(toPlatformPath(f))); - } - - /** - * Normalize a path string. - * - * @param path a path using '/' as the separator. - * @return a path string suitable for the target platform. - */ - private static Path toPlatformPath(String path) { - assert !path.startsWith("/") : path + " is an absolute path"; - String[] parts = path.split("/"); - return parts.length == 1 - ? Paths.get(parts[0]) - : Paths.get(parts[0], Arrays.copyOfRange(parts, 1, parts.length)); - } - - public final String toPlatform(String path) { - return KotlinAbstractTestBuilder.toPlatformPath(path).toString(); - } - - @SuppressWarnings("unused") - private Stream directoryContents(DirectoryType type) { - try { - return Files.walk(directory(type)).map(p -> directory(type).relativize(p)); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - @SuppressWarnings("unused") - public final void logDirectoryContents(DirectoryType type) { - System.out.println( - directoryContents(type) - .map(Path::toString) - .collect(Collectors.joining("\n", "directory " + type.name + " contents:\n", ""))); - } + private static final Path BAZEL_TEST_DIR = + FileSystems.getDefault().getPath(System.getenv("TEST_TMPDIR")); + + private static final AtomicInteger counter = new AtomicInteger(0); + private final CompilationTaskInfo.Builder infoBuilder = CompilationTaskInfo.newBuilder(); + private Path instanceRoot = null; + private String label = null; + private List outLines = null; + + private static void assertFileExistence(Stream pathStream, boolean shouldExist) { + pathStream.forEach( + path -> { + if (shouldExist) + assertWithMessage("file did not exist: " + path).that(path.toFile().exists()).isTrue(); + else assertWithMessage("file existed: " + path).that(path.toFile().exists()).isFalse(); + }); + } + + /** + * Normalize a path string. + * + * @param path a path using '/' as the separator. + * @return a path string suitable for the target platform. + */ + private static Path toPlatformPath(String path) { + assert !path.startsWith("/") : path + " is an absolute path"; + String[] parts = path.split("/"); + return parts.length == 1 + ? Paths.get(parts[0]) + : Paths.get(parts[0], Arrays.copyOfRange(parts, 1, parts.length)); + } + + abstract void setupForNext(CompilationTaskInfo.Builder infoBuilder); + + abstract T buildTask(); + + final String label() { + return Objects.requireNonNull(label); + } + + final Path instanceRoot() { + return Objects.requireNonNull(instanceRoot); + } + + @SuppressWarnings("WeakerAccess") + public final List outLines() { + return outLines; + } + + public final void resetForNext() { + outLines = null; + label = "a_test_" + counter.incrementAndGet(); + infoBuilder + .setLabel("//some/bogus:" + label()) + .setModuleName("some_bogus_module") + .setPlatform(Platform.JVM) + .setRuleKind(RuleKind.LIBRARY) + .setToolchainInfo( + KotlinToolchainInfo.newBuilder() + .setCommon( + KotlinToolchainInfo.Common.newBuilder() + .setApiVersion("1.2") + .setCoroutines("enabled") + .setLanguageVersion("1.2")) + .setJvm(KotlinToolchainInfo.Jvm.newBuilder().setJvmTarget("1.8"))); + try { + this.instanceRoot = Files.createTempDirectory(BAZEL_TEST_DIR, label); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + setupForNext(infoBuilder); + } + + final Path directory(DirectoryType type) { + return type.resolve(instanceRoot); + } + + @SuppressWarnings("unused") + public final void setDebugTags(String... tags) { + infoBuilder.addAllDebug(Arrays.asList(tags)); + } + + final Path writeFile(DirectoryType dirType, String filename, String[] lines) { + Path path = directory(dirType).resolve(filename).toAbsolutePath(); + try (FileOutputStream fos = new FileOutputStream(path.toFile())) { + fos.write(String.join("\n", lines).getBytes(UTF_8)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + return path; + } + + public final Path writeSourceFile(String filename, String[] lines) { + return writeFile(DirectoryType.SOURCES, filename, lines); + } + + public final Path writeGeneratedSourceFile(String filename, String[] lines) { + return writeFile(DirectoryType.SOURCE_GEN, filename, lines); + } + + private R runCompileTask( + CompilationTaskInfo info, T task, BiFunction operation) { + String curDir = System.getProperty("user.dir"); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + try (PrintStream outputStream = new PrintStream(byteArrayOutputStream)) { + System.setProperty("user.dir", instanceRoot().toAbsolutePath().toString()); + return operation.apply(new CompilationTaskContext(info, outputStream), task); + } finally { + System.setProperty("user.dir", curDir); + outLines = + Collections.unmodifiableList( + new BufferedReader( + new InputStreamReader( + new ByteArrayInputStream(byteArrayOutputStream.toByteArray()))) + .lines() + .peek(System.err::println) + .collect(Collectors.toList())); + } + } + + final R runCompileTask(BiFunction operation) { + T task = buildTask(); + return runCompileTask(infoBuilder.build(), task, (ctx, t) -> operation.apply(ctx, task)); + } + + /** + * Run a compilation task expecting it to fail with a {@link CompilationStatusException}. + * + * @param task the compilation task + * @param validator a consumer for the output produced by the task. + */ + public final void runFailingCompileTaskAndValidateOutput( + Runnable task, Consumer> validator) { + try { + task.run(); + } catch (CompilationStatusException ex) { + validator.accept(outLines()); + return; + } + throw new RuntimeException("compilation task should have failed."); + } + + public final void assertFilesExist(DirectoryType dir, String... paths) { + assertFileExistence(resolved(dir, paths), true); + } + + final void assertFilesExist(String... paths) { + assertFileExistence(Stream.of(paths).map(Paths::get), true); + } + + @SuppressWarnings("unused") + public final void assertFilesDoNotExist(DirectoryType dir, String... filePath) { + assertFileExistence(resolved(dir, filePath), false); + } + + private Stream resolved(DirectoryType dir, String... filePath) { + Path directory = directory(dir); + return Stream.of(filePath).map(f -> directory.resolve(toPlatformPath(f))); + } + + public final String toPlatform(String path) { + return KotlinAbstractTestBuilder.toPlatformPath(path).toString(); + } + + @SuppressWarnings("unused") + private Stream directoryContents(DirectoryType type) { + try { + return Files.walk(directory(type)).map(p -> directory(type).relativize(p)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @SuppressWarnings("unused") + public final void logDirectoryContents(DirectoryType type) { + System.out.println( + directoryContents(type) + .map(Path::toString) + .collect(Collectors.joining("\n", "directory " + type.name + " contents:\n", ""))); + } } diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinJsTestBuilder.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinJsTestBuilder.java index c7a79ef7f..e9d3e4a5c 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinJsTestBuilder.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinJsTestBuilder.java @@ -25,53 +25,52 @@ import java.util.function.Consumer; public final class KotlinJsTestBuilder extends KotlinAbstractTestBuilder { - private static final List PASSTHROUGH_FLAGS = - Arrays.asList("-source-map", "-meta-info", "-module-kind", "commonjs", "-target", "v5"); - private static final JsCompilationTask.Builder taskBuilder = JsCompilationTask.newBuilder(); - private static final KotlinBuilderComponent component = - DaggerKotlinBuilderComponent.builder().toolchain(KotlinToolchain.createToolchain()).build(); - private static final EnumSet ALL_DIRECTORY_TYPES = - EnumSet.of(DirectoryType.SOURCES); + private static final List PASSTHROUGH_FLAGS = + Arrays.asList("-source-map", "-meta-info", "-module-kind", "commonjs", "-target", "v5"); + private static final JsCompilationTask.Builder taskBuilder = JsCompilationTask.newBuilder(); + private static final KotlinBuilderComponent component = + DaggerKotlinBuilderComponent.builder().toolchain(KotlinToolchain.createToolchain()).build(); + private static final EnumSet ALL_DIRECTORY_TYPES = + EnumSet.of(DirectoryType.SOURCES); + private final TaskBuilder taskBuilderInstance = new TaskBuilder(); - @Override - JsCompilationTask buildTask() { - return taskBuilder.build(); - } - - @Override - void setupForNext(CompilationTaskInfo.Builder infoBuilder) { - taskBuilder.clear().setInfo(infoBuilder); - DirectoryType.createAll(instanceRoot(), ALL_DIRECTORY_TYPES); - taskBuilder.addAllPassThroughFlags(PASSTHROUGH_FLAGS); - taskBuilder - .getOutputsBuilder() - .setJar(instanceRoot().resolve(label() + ".jar").toAbsolutePath().toString()) - .setSrcjar(instanceRoot().resolve(label() + "-sources.jar").toAbsolutePath().toString()) - .setJs(instanceRoot().resolve(label() + ".js").toAbsolutePath().toString()); - } + @Override + JsCompilationTask buildTask() { + return taskBuilder.build(); + } - public final class TaskBuilder { - public void addSource(String filename, String... lines) { - taskBuilder.getInputsBuilder().addKotlinSources(writeSourceFile(filename, lines).toString()); + @Override + void setupForNext(CompilationTaskInfo.Builder infoBuilder) { + taskBuilder.clear().setInfo(infoBuilder); + DirectoryType.createAll(instanceRoot(), ALL_DIRECTORY_TYPES); + taskBuilder.addAllPassThroughFlags(PASSTHROUGH_FLAGS); + taskBuilder + .getOutputsBuilder() + .setJar(instanceRoot().resolve(label() + ".jar").toAbsolutePath().toString()) + .setSrcjar(instanceRoot().resolve(label() + "-sources.jar").toAbsolutePath().toString()) + .setJs(instanceRoot().resolve(label() + ".js").toAbsolutePath().toString()); } - } - private final TaskBuilder taskBuilderInstance = new TaskBuilder(); + public void runCompilationTask(Consumer setup) { + resetForNext(); + setup.accept(taskBuilderInstance); + runCompileTask( + (taskContext, task) -> { + component.jsTaskExecutor().execute(taskContext, task); + String jsFile = task.getOutputs().getJs(); + assertFilesExist( + jsFile, + jsFile + ".map", + jsFile.substring(0, jsFile.length() - 3) + ".meta.js", + task.getOutputs().getJar(), + task.getOutputs().getSrcjar()); + return null; + }); + } - public void runCompilationTask(Consumer setup) { - resetForNext(); - setup.accept(taskBuilderInstance); - runCompileTask( - (taskContext, task) -> { - component.jsTaskExecutor().execute(taskContext, task); - String jsFile = task.getOutputs().getJs(); - assertFilesExist( - jsFile, - jsFile + ".map", - jsFile.substring(0, jsFile.length() - 3) + ".meta.js", - task.getOutputs().getJar(), - task.getOutputs().getSrcjar()); - return null; - }); - } + public final class TaskBuilder { + public void addSource(String filename, String... lines) { + taskBuilder.getInputsBuilder().addKotlinSources(writeSourceFile(filename, lines).toString()); + } + } } diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java index c9c9f66a3..598bd14ff 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java @@ -23,6 +23,7 @@ import io.bazel.kotlin.builder.toolchain.KotlinToolchain; import io.bazel.kotlin.model.CompilationTaskInfo; import io.bazel.kotlin.model.JvmCompilationTask; + import java.util.EnumSet; import java.util.HashSet; import java.util.function.BiConsumer; @@ -32,137 +33,136 @@ public final class KotlinJvmTestBuilder extends KotlinAbstractTestBuilder { - @SuppressWarnings({"unused", "WeakerAccess"}) - public static Dep - KOTLIN_ANNOTATIONS = Dep.fromLabel("@com_github_jetbrains_kotlin//:annotations"), - KOTLIN_STDLIB = Dep.fromLabel("@com_github_jetbrains_kotlin//:kotlin-stdlib"), - KOTLIN_STDLIB_JDK7 = Dep.fromLabel("@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk7"), - KOTLIN_STDLIB_JDK8 = Dep.fromLabel("@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk8"); - - private static final JvmCompilationTask.Builder taskBuilder = JvmCompilationTask.newBuilder(); - private static final EnumSet ALL_DIRECTORY_TYPES = - EnumSet.of( - DirectoryType.SOURCES, - DirectoryType.CLASSES, - DirectoryType.SOURCE_GEN, - DirectoryType.GENERATED_CLASSES, - DirectoryType.TEMP); - - @Override - void setupForNext(CompilationTaskInfo.Builder taskInfo) { - taskBuilder.clear().setInfo(taskInfo); - - DirectoryType.createAll(instanceRoot(), ALL_DIRECTORY_TYPES); - - taskBuilder - .getDirectoriesBuilder() - .setClasses(directory(DirectoryType.CLASSES).toAbsolutePath().toString()) - .setGeneratedSources(directory(DirectoryType.SOURCE_GEN).toAbsolutePath().toString()) - .setTemp(directory(DirectoryType.TEMP).toAbsolutePath().toString()) - .setGeneratedClasses( - directory(DirectoryType.GENERATED_CLASSES).toAbsolutePath().toString()); - } - - @Override - public JvmCompilationTask buildTask() { - return taskBuilder.build(); - } - - private TaskBuilder taskBuilderInstance = new TaskBuilder(); - - @SafeVarargs - public final Dep runCompileTask(Consumer... setup) { - return executeTask(component().jvmTaskExecutor()::execute, setup); - } - - private KotlinBuilderComponent component() { - return DaggerKotlinBuilderComponent.builder() - .toolchain(KotlinToolchain.createToolchain()) - .build(); - } - - private Dep executeTask( - BiConsumer executor, - Consumer[] setup) { - resetForNext(); - Stream.of(setup).forEach(it -> it.accept(taskBuilderInstance)); - return runCompileTask( - (taskContext, task) -> { - executor.accept(taskContext, task); - - JvmCompilationTask.Outputs outputs = task.getOutputs(); - assertFilesExist( - Stream.of( - outputs.getJar(), - outputs.getJdeps(), - outputs.getSrcjar()) - .filter(p -> !p.isEmpty()) - .toArray(String[]::new) - ); - - return Dep.builder() - .label(taskBuilder.getInfo().getLabel()) - .compileJars(ImmutableList.of(outputs.getJar())) - .runtimeDeps(ImmutableList.copyOf(taskBuilder.getInputs().getClasspathList())) - .sourceJar(taskBuilder.getOutputs().getSrcjar()) - .build(); - }); - } - - public class TaskBuilder { - public TaskBuilder() {} - - public void setLabel(String label) { - taskBuilder.getInfoBuilder().setLabel(label); - } - - public void addSource(String filename, String... lines) { - String pathAsString = writeSourceFile(filename, lines).toString(); - if (pathAsString.endsWith(".kt")) { - taskBuilder.getInputsBuilder().addKotlinSources(pathAsString); - } else if (pathAsString.endsWith(".java")) { - taskBuilder.getInputsBuilder().addJavaSources(pathAsString); - } else { - throw new RuntimeException("unhandled file type: " + pathAsString); - } + private static final JvmCompilationTask.Builder taskBuilder = JvmCompilationTask.newBuilder(); + private static final EnumSet ALL_DIRECTORY_TYPES = + EnumSet.of( + DirectoryType.SOURCES, + DirectoryType.CLASSES, + DirectoryType.SOURCE_GEN, + DirectoryType.GENERATED_CLASSES, + DirectoryType.TEMP); + @SuppressWarnings({"unused", "WeakerAccess"}) + public static Dep + KOTLIN_ANNOTATIONS = Dep.fromLabel("@com_github_jetbrains_kotlin//:annotations"), + KOTLIN_STDLIB = Dep.fromLabel("@com_github_jetbrains_kotlin//:kotlin-stdlib"), + KOTLIN_STDLIB_JDK7 = Dep.fromLabel("@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk7"), + KOTLIN_STDLIB_JDK8 = Dep.fromLabel("@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk8"); + private TaskBuilder taskBuilderInstance = new TaskBuilder(); + + @Override + void setupForNext(CompilationTaskInfo.Builder taskInfo) { + taskBuilder.clear().setInfo(taskInfo); + + DirectoryType.createAll(instanceRoot(), ALL_DIRECTORY_TYPES); + + taskBuilder + .getDirectoriesBuilder() + .setClasses(directory(DirectoryType.CLASSES).toAbsolutePath().toString()) + .setGeneratedSources(directory(DirectoryType.SOURCE_GEN).toAbsolutePath().toString()) + .setTemp(directory(DirectoryType.TEMP).toAbsolutePath().toString()) + .setGeneratedClasses( + directory(DirectoryType.GENERATED_CLASSES).toAbsolutePath().toString()); } - public void addAnnotationProcessors(AnnotationProcessor... annotationProcessors) { - Preconditions.checkState( - taskBuilder.getInputs().getProcessorsList().isEmpty(), "processors already set"); - HashSet processorClasses = new HashSet<>(); - taskBuilder - .getInputsBuilder() - .addAllProcessorpaths( - Stream.of(annotationProcessors) - .peek(it -> processorClasses.add(it.processClass())) - .flatMap(it -> it.processorPath().stream()) - .distinct() - .collect(Collectors.toList())) - .addAllProcessors(processorClasses); + @Override + public JvmCompilationTask buildTask() { + return taskBuilder.build(); } - public void addDirectDependencies(Dep... dependencies) { - Dep.classpathOf(dependencies) - .forEach((dependency) -> taskBuilder.getInputsBuilder().addClasspath(dependency)); + @SafeVarargs + public final Dep runCompileTask(Consumer... setup) { + return executeTask(component().jvmTaskExecutor()::execute, setup); } - public TaskBuilder outputSrcJar() { - taskBuilder.getOutputsBuilder() - .setSrcjar(instanceRoot().resolve("jar_file-sources.jar").toAbsolutePath().toString()); - return this; + private KotlinBuilderComponent component() { + return DaggerKotlinBuilderComponent.builder() + .toolchain(KotlinToolchain.createToolchain()) + .build(); } - public TaskBuilder outputJar() { - taskBuilder.getOutputsBuilder() - .setJar(instanceRoot().resolve("jar_file.jar").toAbsolutePath().toString()); - return this; + private Dep executeTask( + BiConsumer executor, + Consumer[] setup) { + resetForNext(); + Stream.of(setup).forEach(it -> it.accept(taskBuilderInstance)); + return runCompileTask( + (taskContext, task) -> { + executor.accept(taskContext, task); + + JvmCompilationTask.Outputs outputs = task.getOutputs(); + assertFilesExist( + Stream.of( + outputs.getJar(), + outputs.getJdeps(), + outputs.getSrcjar()) + .filter(p -> !p.isEmpty()) + .toArray(String[]::new) + ); + + return Dep.builder() + .label(taskBuilder.getInfo().getLabel()) + .compileJars(ImmutableList.of(outputs.getJar())) + .runtimeDeps(ImmutableList.copyOf(taskBuilder.getInputs().getClasspathList())) + .sourceJar(taskBuilder.getOutputs().getSrcjar()) + .build(); + }); } - public TaskBuilder outputJdeps() { - taskBuilder.getOutputsBuilder() - .setJdeps(instanceRoot().resolve("jdeps_file.jdeps").toAbsolutePath().toString()); - return this; + public class TaskBuilder { + public TaskBuilder() { + } + + public void setLabel(String label) { + taskBuilder.getInfoBuilder().setLabel(label); + } + + public void addSource(String filename, String... lines) { + String pathAsString = writeSourceFile(filename, lines).toString(); + if (pathAsString.endsWith(".kt")) { + taskBuilder.getInputsBuilder().addKotlinSources(pathAsString); + } else if (pathAsString.endsWith(".java")) { + taskBuilder.getInputsBuilder().addJavaSources(pathAsString); + } else { + throw new RuntimeException("unhandled file type: " + pathAsString); + } + } + + public void addAnnotationProcessors(AnnotationProcessor... annotationProcessors) { + Preconditions.checkState( + taskBuilder.getInputs().getProcessorsList().isEmpty(), "processors already set"); + HashSet processorClasses = new HashSet<>(); + taskBuilder + .getInputsBuilder() + .addAllProcessorpaths( + Stream.of(annotationProcessors) + .peek(it -> processorClasses.add(it.processClass())) + .flatMap(it -> it.processorPath().stream()) + .distinct() + .collect(Collectors.toList())) + .addAllProcessors(processorClasses); + } + + public void addDirectDependencies(Dep... dependencies) { + Dep.classpathOf(dependencies) + .forEach((dependency) -> taskBuilder.getInputsBuilder().addClasspath(dependency)); + } + + public TaskBuilder outputSrcJar() { + taskBuilder.getOutputsBuilder() + .setSrcjar(instanceRoot().resolve("jar_file-sources.jar").toAbsolutePath().toString()); + return this; + } + + public TaskBuilder outputJar() { + taskBuilder.getOutputsBuilder() + .setJar(instanceRoot().resolve("jar_file.jar").toAbsolutePath().toString()); + return this; + } + + public TaskBuilder outputJdeps() { + taskBuilder.getOutputsBuilder() + .setJdeps(instanceRoot().resolve("jdeps_file.jdeps").toAbsolutePath().toString()); + return this; + } } - } } diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel b/src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel index 7da6e958b..567921052 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel +++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel @@ -19,7 +19,7 @@ kt_rules_test( srcs = ["jvm/JdepsParserTest.java"], deps = [ "//src/main/kotlin/io/bazel/kotlin/builder/tasks", - ] + ], ) kt_rules_test( @@ -29,19 +29,22 @@ kt_rules_test( # TODO(bazelbuild/rules_kotlin/issues/275): Remove full jar reference when the kt_rules_test handles jvm_import data better. _MAVEN_CENTRAL_PREFIX = "@kotlin_rules_maven//:v1/https/maven-central.storage.googleapis.com/repos/central/data" + _AUTO_VALUE_PREFIX = "%s/com/google/auto/value" % _MAVEN_CENTRAL_PREFIX -_AUTO_VALUE_JAR = _AUTO_VALUE_PREFIX+ "/auto-value/1.6.5/auto-value-1.6.5.jar" -_AUTO_VALUE_ANNOTATIONS_JAR = _AUTO_VALUE_PREFIX+ "/auto-value-annotations/1.6.5/auto-value-annotations-1.6.5.jar" + +_AUTO_VALUE_JAR = _AUTO_VALUE_PREFIX + "/auto-value/1.6.5/auto-value-1.6.5.jar" + +_AUTO_VALUE_ANNOTATIONS_JAR = _AUTO_VALUE_PREFIX + "/auto-value-annotations/1.6.5/auto-value-annotations-1.6.5.jar" kt_rules_test( name = "KotlinBuilderJvmKaptTest", srcs = ["jvm/KotlinBuilderJvmKaptTest.java"], data = [ - _AUTO_VALUE_JAR, - _AUTO_VALUE_ANNOTATIONS_JAR, + _AUTO_VALUE_JAR, + _AUTO_VALUE_ANNOTATIONS_JAR, ], jvm_flags = [ - "-Dauto_value=$(location %s)" % _AUTO_VALUE_JAR, + "-Dauto_value=$(location %s)" % _AUTO_VALUE_JAR, "-Dauto_value_annotations=$(location %s)" % _AUTO_VALUE_ANNOTATIONS_JAR, ], ) @@ -53,4 +56,4 @@ kt_rules_test( test_suite( name = "tasks", -) \ No newline at end of file +) diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/js/KotlinBuilderJsTest.java b/src/test/kotlin/io/bazel/kotlin/builder/tasks/js/KotlinBuilderJsTest.java index c7e110928..d7cda48c6 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/tasks/js/KotlinBuilderJsTest.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/js/KotlinBuilderJsTest.java @@ -1,7 +1,6 @@ package io.bazel.kotlin.builder.tasks.js; import io.bazel.kotlin.builder.KotlinJsTestBuilder; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -10,20 +9,20 @@ @RunWith(JUnit4.class) public class KotlinBuilderJsTest { - private static final KotlinJsTestBuilder builder = new KotlinJsTestBuilder(); + private static final KotlinJsTestBuilder builder = new KotlinJsTestBuilder(); - @Test - public void testSimpleJsCompile() { - builder.runCompilationTask( - it -> it.addSource("AClass.kt", "package something", "class AClass{}")); - } + @Test + public void testSimpleJsCompile() { + builder.runCompilationTask( + it -> it.addSource("AClass.kt", "package something", "class AClass{}")); + } - @Test - public void testJsErrorRendering() { - builder.runFailingCompileTaskAndValidateOutput( - () -> - builder.runCompilationTask( - it -> it.addSource("AClass.kt", "package something", "class AClass{")), - lines -> assertThat(lines.get(0)).startsWith(builder.toPlatform("sources/AClass.kt"))); - } + @Test + public void testJsErrorRendering() { + builder.runFailingCompileTaskAndValidateOutput( + () -> + builder.runCompilationTask( + it -> it.addSource("AClass.kt", "package something", "class AClass{")), + lines -> assertThat(lines.get(0)).startsWith(builder.toPlatform("sources/AClass.kt"))); + } } diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParserTest.java b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParserTest.java index e3d2759f3..514946c0a 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParserTest.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParserTest.java @@ -33,120 +33,120 @@ @SuppressWarnings({"KotlinInternalInJava", "SpellCheckingInspection"}) @RunWith(JUnit4.class) public class JdepsParserTest { - private static final List JDK8_FIXTURE = - toPlatformPaths( - "alt.jar -> bazel-server-cloud/external/com_github_jetbrains_kotlin/lib/kotlin-stdlib-jdk7.jar", - "alt.jar -> bazel-server-cloud/external/com_github_jetbrains_kotlin/lib/kotlin-stdlib.jar", - "alt.jar -> bazel-bin/cloud/qa/integrationtests/pkg/extensions/postgres/postgres.jar", - "alt.jar -> bazel-server-cloud/bazel-out/darwin-fastbuild/bin/cloud/qa/integrationtests/pkg/alt/alt.runfiles/__main__/external/org_postgresql_postgresql/jar/postgresql-42.1.1.jar", - "alt.jar -> /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/rt.jar", - "alt.jar -> bazel-bin/cloud/qa/integrationtests/pkg/utils/utils.jar", - " com.axsy.testing.alt (alt.jar)", - " -> com.axsy.testing.extensions.postgres postgres.jar", - " -> com.axsy.testing.pkg.utils utils.jar", - " -> java.io ", - " -> java.lang ", - " -> java.sql ", - " -> javax.sql ", - " -> kotlin kotlin-stdlib.jar", - " -> kotlin.jdk7 kotlin-stdlib-jdk7.jar", - " -> kotlin.jvm.internal kotlin-stdlib.jar", - " -> org.postgresql.ds postgresql-42.1.1.jar", - " com.axsy.testing.alt.sub (alt.jar)", - " -> java.lang ", - " -> kotlin kotlin-stdlib.jar"); - - private static final List JDK9_FIXTURE = - toPlatformPaths( - "alt.jar -> java.base", - "alt.jar -> java.sql", - "alt.jar -> bazel-server-cloud/external/com_github_jetbrains_kotlin/lib/kotlin-stdlib-jdk7.jar", - "alt.jar -> bazel-server-cloud/external/com_github_jetbrains_kotlin/lib/kotlin-stdlib.jar", - "alt.jar -> bazel-bin/cloud/qa/integrationtests/pkg/extensions/postgres/postgres.jar", - "alt.jar -> bazel-server-cloud/bazel-out/darwin-fastbuild/bin/cloud/qa/integrationtests/pkg/alt/alt.runfiles/__main__/external/org_postgresql_postgresql/jar/postgresql-42.1.1.jar", - "alt.jar -> bazel-bin/cloud/qa/integrationtests/pkg/utils/utils.jar", - " com.axsy.testing.alt -> com.axsy.testing.extensions.postgres postgres.jar", - " com.axsy.testing.alt -> com.axsy.testing.pkg.utils utils.jar", - " com.axsy.testing.alt -> java.io java.base", - " com.axsy.testing.alt -> java.lang java.base", - " com.axsy.testing.alt -> java.sql java.sql", - " com.axsy.testing.alt -> javax.sql java.sql", - " com.axsy.testing.alt -> kotlin kotlin-stdlib.jar", - " com.axsy.testing.alt -> kotlin.jdk7 kotlin-stdlib-jdk7.jar", - " com.axsy.testing.alt -> kotlin.jvm.internal kotlin-stdlib.jar", - " com.axsy.testing.alt -> org.postgresql.ds postgresql-42.1.1.jar", - " com.axsy.testing.alt.sub -> java.lang java.base", - " com.axsy.testing.alt.sub -> kotlin kotlin-stdlib.jar"); - - private static final List CLASSPATH = - toPlatformPaths( - "bazel-bin/cloud/qa/integrationtests/pkg/extensions/postgres/unused.jar", - "bazel-server-cloud/external/com_github_jetbrains_kotlin/lib/kotlin-stdlib-jdk8.jar", - "bazel-server-cloud/external/com_github_jetbrains_kotlin/lib/kotlin-stdlib-jdk7.jar", - "bazel-server-cloud/external/com_github_jetbrains_kotlin/lib/kotlin-stdlib.jar", - "bazel-bin/cloud/qa/integrationtests/pkg/extensions/postgres/postgres.jar", - "bazel-server-cloud/bazel-out/darwin-fastbuild/bin/cloud/qa/integrationtests/pkg/alt/alt.runfiles/__main__/external/org_postgresql_postgresql/jar/postgresql-42.1.1.jar", - "bazel-bin/cloud/qa/integrationtests/pkg/utils/utils.jar"); - - private static final String LABEL = "//cloud/qa/integrationtests/pkg/alt"; - private static final String CLASS_JAR = toPlatformPath("bazel-bin/something/alt.jar"); - - private static final Predicate IS_KOTLIN_IMPLICIT = - JdepsParser.Companion.pathSuffixMatchingPredicate( - Paths.get("external", "com_github_jetbrains_kotlin", "lib"), - "kotlin-stdlib.jar", - "kotlin-stdlib-jdk7.jar", - "kotlin-stdlib-jdk8.jar"); - - @Test - public void parseJDK8Format() throws IOException { - testWithFixture(JDK8_FIXTURE); - } - - @Test - public void parseJDK9Format() throws IOException { - testWithFixture(JDK9_FIXTURE); - } - - private static void testWithFixture(List fixture) throws IOException { - Deps.Dependencies result = - JdepsParser.Companion.parse(LABEL, CLASS_JAR, CLASSPATH, fixture, IS_KOTLIN_IMPLICIT); - - Assert.assertEquals(LABEL, result.getRuleLabel()); - - Truth.assertThat( - result + private static final List JDK8_FIXTURE = + toPlatformPaths( + "alt.jar -> bazel-server-cloud/external/com_github_jetbrains_kotlin/lib/kotlin-stdlib-jdk7.jar", + "alt.jar -> bazel-server-cloud/external/com_github_jetbrains_kotlin/lib/kotlin-stdlib.jar", + "alt.jar -> bazel-bin/cloud/qa/integrationtests/pkg/extensions/postgres/postgres.jar", + "alt.jar -> bazel-server-cloud/bazel-out/darwin-fastbuild/bin/cloud/qa/integrationtests/pkg/alt/alt.runfiles/__main__/external/org_postgresql_postgresql/jar/postgresql-42.1.1.jar", + "alt.jar -> /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/rt.jar", + "alt.jar -> bazel-bin/cloud/qa/integrationtests/pkg/utils/utils.jar", + " com.axsy.testing.alt (alt.jar)", + " -> com.axsy.testing.extensions.postgres postgres.jar", + " -> com.axsy.testing.pkg.utils utils.jar", + " -> java.io ", + " -> java.lang ", + " -> java.sql ", + " -> javax.sql ", + " -> kotlin kotlin-stdlib.jar", + " -> kotlin.jdk7 kotlin-stdlib-jdk7.jar", + " -> kotlin.jvm.internal kotlin-stdlib.jar", + " -> org.postgresql.ds postgresql-42.1.1.jar", + " com.axsy.testing.alt.sub (alt.jar)", + " -> java.lang ", + " -> kotlin kotlin-stdlib.jar"); + + private static final List JDK9_FIXTURE = + toPlatformPaths( + "alt.jar -> java.base", + "alt.jar -> java.sql", + "alt.jar -> bazel-server-cloud/external/com_github_jetbrains_kotlin/lib/kotlin-stdlib-jdk7.jar", + "alt.jar -> bazel-server-cloud/external/com_github_jetbrains_kotlin/lib/kotlin-stdlib.jar", + "alt.jar -> bazel-bin/cloud/qa/integrationtests/pkg/extensions/postgres/postgres.jar", + "alt.jar -> bazel-server-cloud/bazel-out/darwin-fastbuild/bin/cloud/qa/integrationtests/pkg/alt/alt.runfiles/__main__/external/org_postgresql_postgresql/jar/postgresql-42.1.1.jar", + "alt.jar -> bazel-bin/cloud/qa/integrationtests/pkg/utils/utils.jar", + " com.axsy.testing.alt -> com.axsy.testing.extensions.postgres postgres.jar", + " com.axsy.testing.alt -> com.axsy.testing.pkg.utils utils.jar", + " com.axsy.testing.alt -> java.io java.base", + " com.axsy.testing.alt -> java.lang java.base", + " com.axsy.testing.alt -> java.sql java.sql", + " com.axsy.testing.alt -> javax.sql java.sql", + " com.axsy.testing.alt -> kotlin kotlin-stdlib.jar", + " com.axsy.testing.alt -> kotlin.jdk7 kotlin-stdlib-jdk7.jar", + " com.axsy.testing.alt -> kotlin.jvm.internal kotlin-stdlib.jar", + " com.axsy.testing.alt -> org.postgresql.ds postgresql-42.1.1.jar", + " com.axsy.testing.alt.sub -> java.lang java.base", + " com.axsy.testing.alt.sub -> kotlin kotlin-stdlib.jar"); + + private static final List CLASSPATH = + toPlatformPaths( + "bazel-bin/cloud/qa/integrationtests/pkg/extensions/postgres/unused.jar", + "bazel-server-cloud/external/com_github_jetbrains_kotlin/lib/kotlin-stdlib-jdk8.jar", + "bazel-server-cloud/external/com_github_jetbrains_kotlin/lib/kotlin-stdlib-jdk7.jar", + "bazel-server-cloud/external/com_github_jetbrains_kotlin/lib/kotlin-stdlib.jar", + "bazel-bin/cloud/qa/integrationtests/pkg/extensions/postgres/postgres.jar", + "bazel-server-cloud/bazel-out/darwin-fastbuild/bin/cloud/qa/integrationtests/pkg/alt/alt.runfiles/__main__/external/org_postgresql_postgresql/jar/postgresql-42.1.1.jar", + "bazel-bin/cloud/qa/integrationtests/pkg/utils/utils.jar"); + + private static final String LABEL = "//cloud/qa/integrationtests/pkg/alt"; + private static final String CLASS_JAR = toPlatformPath("bazel-bin/something/alt.jar"); + + private static final Predicate IS_KOTLIN_IMPLICIT = + JdepsParser.Companion.pathSuffixMatchingPredicate( + Paths.get("external", "com_github_jetbrains_kotlin", "lib"), + "kotlin-stdlib.jar", + "kotlin-stdlib-jdk7.jar", + "kotlin-stdlib-jdk8.jar"); + + private static void testWithFixture(List fixture) throws IOException { + Deps.Dependencies result = + JdepsParser.Companion.parse(LABEL, CLASS_JAR, CLASSPATH, fixture, IS_KOTLIN_IMPLICIT); + + Assert.assertEquals(LABEL, result.getRuleLabel()); + + Truth.assertThat( + result + .getDependencyList() + .stream() + .map(Deps.Dependency::getPath) + .collect(Collectors.toSet())) + .containsExactlyElementsIn(CLASSPATH); + + Assert.assertEquals(7, result.getDependencyCount()); + Assert.assertEquals(1, depKinds(result, Deps.Dependency.Kind.UNUSED).size()); + Assert.assertEquals(3, depKinds(result, Deps.Dependency.Kind.IMPLICIT).size()); + Assert.assertEquals(3, depKinds(result, Deps.Dependency.Kind.EXPLICIT).size()); + + Assert.assertEquals(2, result.getContainedPackageCount()); + + result.writeTo(System.out); + System.out.flush(); + } + + private static List toPlatformPaths(String... lines) { + return Stream.of(lines).map(JdepsParserTest::toPlatformPath).collect(Collectors.toList()); + } + + // on windows translate absolute paths to c:\ . Also swap the seperators from "/" to "\". + private static String toPlatformPath(String it) { + return File.separatorChar != '/' ? it.replace(" /", "c:\\").replace("/", File.separator) : it; + } + + private static List depKinds(Deps.Dependencies result, Deps.Dependency.Kind kind) { + return result .getDependencyList() .stream() - .map(Deps.Dependency::getPath) - .collect(Collectors.toSet())) - .containsExactlyElementsIn(CLASSPATH); - - Assert.assertEquals(7, result.getDependencyCount()); - Assert.assertEquals(1, depKinds(result, Deps.Dependency.Kind.UNUSED).size()); - Assert.assertEquals(3, depKinds(result, Deps.Dependency.Kind.IMPLICIT).size()); - Assert.assertEquals(3, depKinds(result, Deps.Dependency.Kind.EXPLICIT).size()); - - Assert.assertEquals(2, result.getContainedPackageCount()); - - result.writeTo(System.out); - System.out.flush(); - } - - private static List toPlatformPaths(String... lines) { - return Stream.of(lines).map(JdepsParserTest::toPlatformPath).collect(Collectors.toList()); - } - - // on windows translate absolute paths to c:\ . Also swap the seperators from "/" to "\". - private static String toPlatformPath(String it) { - return File.separatorChar != '/' ? it.replace(" /", "c:\\").replace("/", File.separator) : it; - } - - private static List depKinds(Deps.Dependencies result, Deps.Dependency.Kind kind) { - return result - .getDependencyList() - .stream() - .filter(x -> x.getKind() == kind) - .collect(Collectors.toList()); - } + .filter(x -> x.getKind() == kind) + .collect(Collectors.toList()); + } + + @Test + public void parseJDK8Format() throws IOException { + testWithFixture(JDK8_FIXTURE); + } + + @Test + public void parseJDK9Format() throws IOException { + testWithFixture(JDK9_FIXTURE); + } } diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmBasicTest.java b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmBasicTest.java index dc21fafdb..91926aab4 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmBasicTest.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmBasicTest.java @@ -18,143 +18,144 @@ import io.bazel.kotlin.builder.Deps; import io.bazel.kotlin.builder.DirectoryType; import io.bazel.kotlin.builder.KotlinJvmTestBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.function.Consumer; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; import static com.google.common.truth.Truth.assertThat; @RunWith(JUnit4.class) public class KotlinBuilderJvmBasicTest { - private static final KotlinJvmTestBuilder ctx = new KotlinJvmTestBuilder(); + private static final KotlinJvmTestBuilder ctx = new KotlinJvmTestBuilder(); - private static final Consumer SETUP_NORMALIZATION_TEST_SOURCES = - ctx -> { - ctx.addSource("AClass.kt", "package something;\n" + "class AClass{}"); - ctx.addSource("BClass.kt", "package something;\n" + "class BClass{}"); - ctx.outputJar().outputSrcJar(); - }; + private static final Consumer SETUP_NORMALIZATION_TEST_SOURCES = + ctx -> { + ctx.addSource("AClass.kt", "package something;\n" + "class AClass{}"); + ctx.addSource("BClass.kt", "package something;\n" + "class BClass{}"); + ctx.outputJar().outputSrcJar(); + }; - @Test - public void testSimpleMixedModeCompile() { - ctx.runCompileTask( - c -> { - c.addSource("AClass.kt", "package something;" + "class AClass{}"); - c.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{}"); - c.outputJar().outputSrcJar(); - }); - ctx.assertFilesExist( - DirectoryType.CLASSES, "something/AClass.class", "something/AnotherClass.class"); - } + private static String hashDep(String path) { + try { + //noinspection UnstableApiUsage + return com.google.common.hash.Hashing.sha256() + .hashBytes(Files.readAllBytes(Paths.get(path))) + .toString(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } - @Test - public void testGeneratesJDeps() { - ctx.runCompileTask( - c -> { - c.addSource("AClass.kt", "package something;" + "class AClass{}"); - c.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{}"); - // declaring outputJdeps also asserts existance after compile. - c.outputJar().outputSrcJar().outputJdeps(); - }); - } + @Test + public void testSimpleMixedModeCompile() { + ctx.runCompileTask( + c -> { + c.addSource("AClass.kt", "package something;" + "class AClass{}"); + c.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{}"); + c.outputJar().outputSrcJar(); + }); + ctx.assertFilesExist( + DirectoryType.CLASSES, "something/AClass.class", "something/AnotherClass.class"); + } - @Test - public void testKotlinErrorRendering() { - ctx.runFailingCompileTaskAndValidateOutput( - () -> - ctx.runCompileTask( + @Test + public void testGeneratesJDeps() { + ctx.runCompileTask( c -> { - c.addSource("AClass.kt", "package something;" + "class AClass{"); - c.outputJar().outputSrcJar(); - }), - lines -> assertThat(lines.get(0)).startsWith(ctx.toPlatform("sources/AClass"))); - } + c.addSource("AClass.kt", "package something;" + "class AClass{}"); + c.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{}"); + // declaring outputJdeps also asserts existance after compile. + c.outputJar().outputSrcJar().outputJdeps(); + }); + } - @Test - public void testMixedBiReferences() { - ctx.runCompileTask( - ctx -> { - ctx.addSource( - "AClass.java", - "package a;", - "", - "import b.BClass;", - "", - "public class AClass {", - " static BClass b = new BClass();", - "}"); - ctx.addSource( - "BClass.kt", - "package b", - "", - "import a.AClass", - "", - "class BClass() {", - " val a = AClass()", - "}"); - ctx.outputSrcJar() - .outputJar(); - }); - ctx.assertFilesExist(DirectoryType.CLASSES, "a/AClass.class", "b/BClass.class"); - } + @Test + public void testKotlinErrorRendering() { + ctx.runFailingCompileTaskAndValidateOutput( + () -> + ctx.runCompileTask( + c -> { + c.addSource("AClass.kt", "package something;" + "class AClass{"); + c.outputJar().outputSrcJar(); + }), + lines -> assertThat(lines.get(0)).startsWith(ctx.toPlatform("sources/AClass"))); + } - @Test - public void testCompileSingleJavaFile() { - ctx.runCompileTask( - (ctx) -> { - ctx.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{}"); - ctx.outputSrcJar() - .outputJar(); - }); - } + @Test + public void testMixedBiReferences() { + ctx.runCompileTask( + ctx -> { + ctx.addSource( + "AClass.java", + "package a;", + "", + "import b.BClass;", + "", + "public class AClass {", + " static BClass b = new BClass();", + "}"); + ctx.addSource( + "BClass.kt", + "package b", + "", + "import a.AClass", + "", + "class BClass() {", + " val a = AClass()", + "}"); + ctx.outputSrcJar() + .outputJar(); + }); + ctx.assertFilesExist(DirectoryType.CLASSES, "a/AClass.class", "b/BClass.class"); + } - @Test - public void testJavaErrorRendering() { - ctx.runFailingCompileTaskAndValidateOutput( - () -> - ctx.runCompileTask( - c -> { - c.addSource("AClass.kt", "package something;" + "class AClass{}"); - c.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{"); - c.outputJar().outputSrcJar(); - }), - lines -> assertThat(lines.get(0)).startsWith(ctx.toPlatform("sources/AnotherClass"))); - } + @Test + public void testCompileSingleJavaFile() { + ctx.runCompileTask( + (ctx) -> { + ctx.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{}"); + ctx.outputSrcJar() + .outputJar(); + }); + } - @Test - public void testCompiledJarIsNormalized() { - Deps.Dep previous = ctx.runCompileTask(SETUP_NORMALIZATION_TEST_SOURCES); - Deps.Dep recompiled = - ctx.runCompileTask(ctx -> ctx.setLabel(previous.label()), SETUP_NORMALIZATION_TEST_SOURCES); - assertThat(previous.label()).isEqualTo(recompiled.label()); - assertThat(hashDep(previous.singleCompileJar())) - .isEqualTo(hashDep(recompiled.singleCompileJar())); - assertThat(previous.sourceJar()).isNotEmpty(); - assertThat(hashDep(previous.sourceJar())).isEqualTo(hashDep(recompiled.sourceJar())); - } + @Test + public void testJavaErrorRendering() { + ctx.runFailingCompileTaskAndValidateOutput( + () -> + ctx.runCompileTask( + c -> { + c.addSource("AClass.kt", "package something;" + "class AClass{}"); + c.addSource("AnotherClass.java", "package something;", "", "class AnotherClass{"); + c.outputJar().outputSrcJar(); + }), + lines -> assertThat(lines.get(0)).startsWith(ctx.toPlatform("sources/AnotherClass"))); + } - @Test - public void testSourceJarIsNormalized() { - Deps.Dep previous = ctx.runCompileTask(SETUP_NORMALIZATION_TEST_SOURCES); - Deps.Dep recompiled = - ctx.runCompileTask(ctx -> ctx.setLabel(previous.label()), SETUP_NORMALIZATION_TEST_SOURCES); - assertThat(previous.sourceJar()).isNotEmpty(); - assertThat(hashDep(previous.sourceJar())).isEqualTo(hashDep(recompiled.sourceJar())); - } + @Test + public void testCompiledJarIsNormalized() { + Deps.Dep previous = ctx.runCompileTask(SETUP_NORMALIZATION_TEST_SOURCES); + Deps.Dep recompiled = + ctx.runCompileTask(ctx -> ctx.setLabel(previous.label()), SETUP_NORMALIZATION_TEST_SOURCES); + assertThat(previous.label()).isEqualTo(recompiled.label()); + assertThat(hashDep(previous.singleCompileJar())) + .isEqualTo(hashDep(recompiled.singleCompileJar())); + assertThat(previous.sourceJar()).isNotEmpty(); + assertThat(hashDep(previous.sourceJar())).isEqualTo(hashDep(recompiled.sourceJar())); + } - private static String hashDep(String path) { - try { - //noinspection UnstableApiUsage - return com.google.common.hash.Hashing.sha256() - .hashBytes(Files.readAllBytes(Paths.get(path))) - .toString(); - } catch (IOException e) { - throw new UncheckedIOException(e); + @Test + public void testSourceJarIsNormalized() { + Deps.Dep previous = ctx.runCompileTask(SETUP_NORMALIZATION_TEST_SOURCES); + Deps.Dep recompiled = + ctx.runCompileTask(ctx -> ctx.setLabel(previous.label()), SETUP_NORMALIZATION_TEST_SOURCES); + assertThat(previous.sourceJar()).isNotEmpty(); + assertThat(hashDep(previous.sourceJar())).isEqualTo(hashDep(recompiled.sourceJar())); } - } } diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmKaptTest.java b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmKaptTest.java index 311c26047..575b019e1 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmKaptTest.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmKaptTest.java @@ -19,133 +19,134 @@ import io.bazel.kotlin.builder.Deps.Dep; import io.bazel.kotlin.builder.DirectoryType; import io.bazel.kotlin.builder.KotlinJvmTestBuilder; -import java.io.File; -import java.util.function.Consumer; -import java.util.stream.Collectors; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import java.io.File; +import java.util.function.Consumer; +import java.util.stream.Collectors; + import static io.bazel.kotlin.builder.KotlinJvmTestBuilder.KOTLIN_ANNOTATIONS; import static io.bazel.kotlin.builder.KotlinJvmTestBuilder.KOTLIN_STDLIB; @RunWith(JUnit4.class) public class KotlinBuilderJvmKaptTest { - private static final Dep AUTO_VALUE_ANNOTATIONS = - Dep.importJar( - "autovalue_annotations", - System.getProperty("auto_value_annotations") - .replaceFirst("external" + File.separator, "")); - private static final Dep AUTO_VALUE = - Dep.importJar( - "autovalue", - System.getProperty("auto_value") - .replaceFirst("external" + File.separator, "")); - private static final AnnotationProcessor AUTO_VALUE_ANNOTATION_PROCESSOR = - AnnotationProcessor.builder() - .processClass("com.google.auto.value.processor.AutoValueProcessor") - .processorPath( - Dep.classpathOf(AUTO_VALUE_ANNOTATIONS, AUTO_VALUE, KOTLIN_ANNOTATIONS) - .collect(Collectors.toSet())) - .build(); + private static final Dep AUTO_VALUE_ANNOTATIONS = + Dep.importJar( + "autovalue_annotations", + System.getProperty("auto_value_annotations") + .replaceFirst("external" + File.separator, "")); + private static final Dep AUTO_VALUE = + Dep.importJar( + "autovalue", + System.getProperty("auto_value") + .replaceFirst("external" + File.separator, "")); + private static final AnnotationProcessor AUTO_VALUE_ANNOTATION_PROCESSOR = + AnnotationProcessor.builder() + .processClass("com.google.auto.value.processor.AutoValueProcessor") + .processorPath( + Dep.classpathOf(AUTO_VALUE_ANNOTATIONS, AUTO_VALUE, KOTLIN_ANNOTATIONS) + .collect(Collectors.toSet())) + .build(); - private static final KotlinJvmTestBuilder ctx = new KotlinJvmTestBuilder(); + private static final KotlinJvmTestBuilder ctx = new KotlinJvmTestBuilder(); - private static final Consumer ADD_AUTO_VALUE_PLUGIN = - (c) -> { - c.addAnnotationProcessors(AUTO_VALUE_ANNOTATION_PROCESSOR); - c.addDirectDependencies(AUTO_VALUE_ANNOTATIONS, KOTLIN_ANNOTATIONS, KOTLIN_STDLIB); - }; + private static final Consumer ADD_AUTO_VALUE_PLUGIN = + (c) -> { + c.addAnnotationProcessors(AUTO_VALUE_ANNOTATION_PROCESSOR); + c.addDirectDependencies(AUTO_VALUE_ANNOTATIONS, KOTLIN_ANNOTATIONS, KOTLIN_STDLIB); + }; - @Test - public void testKaptKt() { - ctx.runCompileTask( - ADD_AUTO_VALUE_PLUGIN, - c -> { - c.addSource( - "TestKtValue.kt", - "package autovalue\n" - + "\n" - + "import com.google.auto.value.AutoValue\n" - + "\n" - + "@AutoValue\n" - + "abstract class TestKtValue {\n" - + " abstract fun name(): String\n" - + " fun builder(): Builder = AutoValue_TestKtValue.Builder()\n" - + "\n" - + " @AutoValue.Builder\n" - + " abstract class Builder {\n" - + " abstract fun setName(name: String): Builder\n" - + " abstract fun build(): TestKtValue\n" - + " }\n" - + "}"); - c.outputJar().outputSrcJar(); - } - ); + @Test + public void testKaptKt() { + ctx.runCompileTask( + ADD_AUTO_VALUE_PLUGIN, + c -> { + c.addSource( + "TestKtValue.kt", + "package autovalue\n" + + "\n" + + "import com.google.auto.value.AutoValue\n" + + "\n" + + "@AutoValue\n" + + "abstract class TestKtValue {\n" + + " abstract fun name(): String\n" + + " fun builder(): Builder = AutoValue_TestKtValue.Builder()\n" + + "\n" + + " @AutoValue.Builder\n" + + " abstract class Builder {\n" + + " abstract fun setName(name: String): Builder\n" + + " abstract fun build(): TestKtValue\n" + + " }\n" + + "}"); + c.outputJar().outputSrcJar(); + } + ); - ctx.assertFilesExist( - DirectoryType.CLASSES, - "autovalue/TestKtValue.class", - "autovalue/AutoValue_TestKtValue.class"); - ctx.assertFilesExist(DirectoryType.SOURCE_GEN, "autovalue/AutoValue_TestKtValue.java"); - } + ctx.assertFilesExist( + DirectoryType.CLASSES, + "autovalue/TestKtValue.class", + "autovalue/AutoValue_TestKtValue.class"); + ctx.assertFilesExist(DirectoryType.SOURCE_GEN, "autovalue/AutoValue_TestKtValue.java"); + } - @Test - public void testMixedKaptBiReferences() { - ctx.runCompileTask( - ADD_AUTO_VALUE_PLUGIN, - ctx -> { - ctx.addSource( - "TestKtValue.kt", - "package autovalue.a\n" - + "\n" - + "import com.google.auto.value.AutoValue\n" - + "import autovalue.b.TestAutoValue\n" - + "\n" - + "@AutoValue\n" - + "abstract class TestKtValue {\n" - + " abstract fun name(): String\n" - + " fun builder(): Builder = AutoValue_TestKtValue.Builder()\n" - + "\n" - + " @AutoValue.Builder\n" - + " abstract class Builder {\n" - + " abstract fun setName(name: String): Builder\n" - + " abstract fun build(): TestKtValue\n" - + " }\n" - + "}"); + @Test + public void testMixedKaptBiReferences() { + ctx.runCompileTask( + ADD_AUTO_VALUE_PLUGIN, + ctx -> { + ctx.addSource( + "TestKtValue.kt", + "package autovalue.a\n" + + "\n" + + "import com.google.auto.value.AutoValue\n" + + "import autovalue.b.TestAutoValue\n" + + "\n" + + "@AutoValue\n" + + "abstract class TestKtValue {\n" + + " abstract fun name(): String\n" + + " fun builder(): Builder = AutoValue_TestKtValue.Builder()\n" + + "\n" + + " @AutoValue.Builder\n" + + " abstract class Builder {\n" + + " abstract fun setName(name: String): Builder\n" + + " abstract fun build(): TestKtValue\n" + + " }\n" + + "}"); - ctx.addSource( - "TestAutoValue.java", - "package autovalue.b;\n" - + "\n" - + "import com.google.auto.value.AutoValue;\n" - + "import autovalue.a.TestKtValue;\n" - + "\n" - + "@AutoValue\n" - + "public abstract class TestAutoValue {\n" - + " abstract String name();\n" - + "\n" - + "\n" - + " static Builder builder() {\n" - + " return new AutoValue_TestAutoValue.Builder();\n" - + " }\n" - + "\n" - + " @AutoValue.Builder\n" - + " abstract static class Builder {\n" - + " abstract Builder setName(String name);\n" - + " abstract TestAutoValue build();\n" - + " }\n" - + "\n" - + "}"); - ctx.outputJar().outputSrcJar(); - }); - ctx.assertFilesExist( - DirectoryType.SOURCE_GEN, - "autovalue/a/AutoValue_TestKtValue.java", - "autovalue/b/AutoValue_TestAutoValue.java"); - ctx.assertFilesExist( - DirectoryType.CLASSES, - "autovalue/a/AutoValue_TestKtValue.class", - "autovalue/b/AutoValue_TestAutoValue.class"); - } + ctx.addSource( + "TestAutoValue.java", + "package autovalue.b;\n" + + "\n" + + "import com.google.auto.value.AutoValue;\n" + + "import autovalue.a.TestKtValue;\n" + + "\n" + + "@AutoValue\n" + + "public abstract class TestAutoValue {\n" + + " abstract String name();\n" + + "\n" + + "\n" + + " static Builder builder() {\n" + + " return new AutoValue_TestAutoValue.Builder();\n" + + " }\n" + + "\n" + + " @AutoValue.Builder\n" + + " abstract static class Builder {\n" + + " abstract Builder setName(String name);\n" + + " abstract TestAutoValue build();\n" + + " }\n" + + "\n" + + "}"); + ctx.outputJar().outputSrcJar(); + }); + ctx.assertFilesExist( + DirectoryType.SOURCE_GEN, + "autovalue/a/AutoValue_TestKtValue.java", + "autovalue/b/AutoValue_TestAutoValue.java"); + ctx.assertFilesExist( + DirectoryType.CLASSES, + "autovalue/a/AutoValue_TestKtValue.class", + "autovalue/b/AutoValue_TestAutoValue.class"); + } } diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutorTest.kt b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutorTest.kt index 96f7a2758..18ec9a7e4 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutorTest.kt +++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutorTest.kt @@ -1,8 +1,6 @@ package io.bazel.kotlin.builder.tasks.jvm -import io.bazel.kotlin.builder.KotlinJsTestBuilder import io.bazel.kotlin.builder.KotlinJvmTestBuilder -import io.bazel.kotlin.model.JvmCompilationTask import org.junit.Test import kotlin.test.assertEquals import kotlin.test.assertFalse @@ -11,40 +9,47 @@ import kotlin.test.assertTrue class KotlinJvmTaskExecutorTest { - private val ctx = KotlinJvmTestBuilder() - - @Test - fun testSimpleGeneratedNonJvmSourcesIgnored() { - ctx.resetForNext() - ctx.writeGeneratedSourceFile( - "AGenClass.kt", - arrayOf("package something.gen;", "class AGenClass{}")) - ctx.writeGeneratedSourceFile( - "AnotherGenClass.java", - arrayOf("package something.gen;", "class AnotherGenClass{}")) - ctx.writeGeneratedSourceFile( - "ignore-me.txt", - arrayOf("contents do not matter")) - ctx.writeSourceFile( - "ignore-me-regular-src.kt", - arrayOf("contents do not matter")) - ctx.writeSourceFile( - "ignore-me-another-regular-src.java", - arrayOf("contents do not matter")) - val compileTask = ctx.buildTask() - - assertFalse(compileTask.hasInputs()) - - val expandedCompileTask = compileTask.expandWithGeneratedSources() - - assertFalse(compileTask.hasInputs()) - - assertTrue(expandedCompileTask.hasInputs()) - assertNotNull(expandedCompileTask.inputs.javaSourcesList.find { - path -> path.endsWith("a_test_1/generated_sources/AnotherGenClass.java") }) - assertEquals(expandedCompileTask.inputs.javaSourcesCount, 1) - assertNotNull(expandedCompileTask.inputs.kotlinSourcesList.find { - path -> path.endsWith("a_test_1/generated_sources/AGenClass.kt") }) - assertEquals(expandedCompileTask.inputs.kotlinSourcesCount, 1) - } -} \ No newline at end of file + private val ctx = KotlinJvmTestBuilder() + + @Test + fun testSimpleGeneratedNonJvmSourcesIgnored() { + ctx.resetForNext() + ctx.writeGeneratedSourceFile( + "AGenClass.kt", + arrayOf("package something.gen;", "class AGenClass{}") + ) + ctx.writeGeneratedSourceFile( + "AnotherGenClass.java", + arrayOf("package something.gen;", "class AnotherGenClass{}") + ) + ctx.writeGeneratedSourceFile( + "ignore-me.txt", + arrayOf("contents do not matter") + ) + ctx.writeSourceFile( + "ignore-me-regular-src.kt", + arrayOf("contents do not matter") + ) + ctx.writeSourceFile( + "ignore-me-another-regular-src.java", + arrayOf("contents do not matter") + ) + val compileTask = ctx.buildTask() + + assertFalse(compileTask.hasInputs()) + + val expandedCompileTask = compileTask.expandWithGeneratedSources() + + assertFalse(compileTask.hasInputs()) + + assertTrue(expandedCompileTask.hasInputs()) + assertNotNull(expandedCompileTask.inputs.javaSourcesList.find { path -> + path.endsWith("a_test_1/generated_sources/AnotherGenClass.java") + }) + assertEquals(expandedCompileTask.inputs.javaSourcesCount, 1) + assertNotNull(expandedCompileTask.inputs.kotlinSourcesList.find { path -> + path.endsWith("a_test_1/generated_sources/AGenClass.kt") + }) + assertEquals(expandedCompileTask.inputs.kotlinSourcesCount, 1) + } +} diff --git a/src/test/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarCreatorTest.java b/src/test/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarCreatorTest.java index 4f1093ee7..8e5b39191 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarCreatorTest.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarCreatorTest.java @@ -24,29 +24,29 @@ import static com.google.common.truth.Truth.assertWithMessage; public class SourceJarCreatorTest { - private final String expectedPackage = "iO.some1.package"; + private final String expectedPackage = "iO.some1.package"; - private final List cases = - Arrays.asList( - "package iO.some1.package", - "package iO.some1.package ", - "package iO.some1.package;", - " package iO.some1.package; ", - " /* a comment*/ package iO.some1.package; ", - " /** a comment*/ package iO.some1.package; ", - " /* a comment*//*blah*/package iO.some1.package; ", - " /* a comment*//*blah*/ package iO.some1.package; ", - " /* a comment*/package /* blah */ iO.some1.package /*lala*/; ", - "/* a comment*/package/**/iO.some1.package/*b*/;"); + private final List cases = + Arrays.asList( + "package iO.some1.package", + "package iO.some1.package ", + "package iO.some1.package;", + " package iO.some1.package; ", + " /* a comment*/ package iO.some1.package; ", + " /** a comment*/ package iO.some1.package; ", + " /* a comment*//*blah*/package iO.some1.package; ", + " /* a comment*//*blah*/ package iO.some1.package; ", + " /* a comment*/package /* blah */ iO.some1.package /*lala*/; ", + "/* a comment*/package/**/iO.some1.package/*b*/;"); - @Test - public void testPackageNameRegex() { - cases.forEach( - (testCase) -> { - String pkg = SourceJarCreator.Companion.extractPackage(testCase); - StandardSubjectBuilder subj = assertWithMessage("positive test case: " + testCase); - subj.that(pkg).isNotNull(); - subj.that(pkg).isEqualTo(expectedPackage); - }); - } + @Test + public void testPackageNameRegex() { + cases.forEach( + (testCase) -> { + String pkg = SourceJarCreator.Companion.extractPackage(testCase); + StandardSubjectBuilder subj = assertWithMessage("positive test case: " + testCase); + subj.that(pkg).isNotNull(); + subj.that(pkg).isEqualTo(expectedPackage); + }); + } } diff --git a/src/test/kotlin/io/bazel/kotlin/defs.bzl b/src/test/kotlin/io/bazel/kotlin/defs.bzl index 2e4132963..0f07a8e73 100644 --- a/src/test/kotlin/io/bazel/kotlin/defs.bzl +++ b/src/test/kotlin/io/bazel/kotlin/defs.bzl @@ -38,7 +38,7 @@ def kt_rules_test(name, **kwargs): ] + args["data"]: if dep not in args["data"]: args["data"] += [dep] - args["jvm_flags"] += ["-D%s=$(rootpath %s)" %(dep.replace("/",".").replace(":","."), dep)] + args["jvm_flags"] += ["-D%s=$(rootpath %s)" % (dep.replace("/", ".").replace(":", "."), dep)] args.setdefault("test_class", _get_class_name(kwargs)) for f in args.get("srcs"): From e234ac6956006c47b78a16b8f5c1b06e64f90342 Mon Sep 17 00:00:00 2001 From: Corbin McNeely-Smith <58151731+restingbull@users.noreply.github.com> Date: Fri, 3 Apr 2020 13:10:30 -0400 Subject: [PATCH 14/16] Ensure that KotlionBuilder workers use a clean directory for each compilation. (#298) * Create WorkingDirectoryContext to handle compilation directory lifecycle. * Thread the working directory to all intermediate directories to ensure hermetic compilation. * Added test for worker hermiticity. * Restructured BazelWorker.kt for easier testing by pulling out the delegation invoker. * Changed the flag enums to be public and static. * Create KotlinBuilderTestComponent for retrieving configured instances for test. * Replaced the use of system user.dir with a more robust path usage. * Ensure js has a clean working area. --- .../builder/KotlinBuilderComponent.java | 17 +- .../bazel/kotlin/builder/tasks/BazelWorker.kt | 130 ++++++------ .../kotlin/builder/tasks/KotlinBuilder.kt | 200 ++++++++++-------- .../builder/tasks/js/Kotlin2JsTaskExecutor.kt | 42 +++- .../builder/tasks/jvm/compilation_task.kt | 20 +- .../toolchain/CompilationTaskContext.kt | 29 +-- .../io/bazel/kotlin/builder/utils/IOUtils.kt | 38 ++-- .../builder/utils/WorkingDirectoryContext.kt | 34 +++ src/main/protobuf/kotlin_model.proto | 9 + src/test/kotlin/io/bazel/kotlin/builder/BUILD | 4 +- .../builder/KotlinAbstractTestBuilder.java | 51 +++-- .../builder/KotlinBuilderTestComponent.java | 50 +++++ .../kotlin/builder/KotlinJvmTestBuilder.java | 17 +- .../io/bazel/kotlin/builder/tasks/BUILD.bazel | 6 + .../builder/tasks/jvm/KotlinWorkerTest.kt | 180 ++++++++++++++++ 15 files changed, 574 insertions(+), 253 deletions(-) create mode 100644 src/main/kotlin/io/bazel/kotlin/builder/utils/WorkingDirectoryContext.kt create mode 100644 src/test/kotlin/io/bazel/kotlin/builder/KotlinBuilderTestComponent.java create mode 100644 src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinWorkerTest.kt diff --git a/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java b/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java index 521a0e012..5c0018ea4 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java +++ b/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java @@ -5,13 +5,14 @@ * 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 + * 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. * - * 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. */ package io.bazel.kotlin.builder; @@ -40,7 +41,7 @@ public interface KotlinBuilderComponent { BazelWorker worker(); @Component.Builder - interface Builder { + public interface Builder { @BindsInstance KotlinBuilderComponent.Builder toolchain(KotlinToolchain toolchain); @@ -48,7 +49,7 @@ interface Builder { } @dagger.Module - class Module { + public class Module { @Provides public KotlinCompilerPluginArgsEncoder providePluginArgEncoder(KotlinToolchain toolchain) { return new KotlinCompilerPluginArgsEncoder( diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/BazelWorker.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/BazelWorker.kt index cd575ed0e..3e8f5743f 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/BazelWorker.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/BazelWorker.kt @@ -5,25 +5,27 @@ * 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 + * 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. * - * 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. */ package io.bazel.kotlin.builder.tasks import com.google.devtools.build.lib.worker.WorkerProtocol -import io.bazel.kotlin.builder.utils.rootCause +import io.bazel.kotlin.builder.utils.WorkingDirectoryContext +import io.bazel.kotlin.builder.utils.wasInterrupted import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.IOException -import java.io.InterruptedIOException import java.io.PrintStream import java.nio.charset.StandardCharsets.UTF_8 import java.nio.file.Files +import java.nio.file.Path import java.nio.file.Paths /** @@ -41,7 +43,7 @@ interface CommandLineProgram { * @param args command line arguments * @return program exit code, i.e. 0 for success, non-zero for failure */ - fun apply(args: List): Int + fun apply(workingDir: Path, args: List): Int } /** @@ -52,25 +54,27 @@ interface CommandLineProgram { * compatible with being run as a normal single-invocation command. * * @param delegate program type - */ + */ class BazelWorker( private val delegate: CommandLineProgram, private val output: PrintStream, private val mnemonic: String -) : CommandLineProgram { +) { companion object { - private const val INTERUPTED_STATUS = 0 - private const val ERROR_STATUS = 1 + const val OK = 0 + const val INTERRUPTED_STATUS = 1 + const val ERROR_STATUS = 2 } - override fun apply(args: List): Int { + fun apply(args: List): Int { return if (args.contains("--persistent_worker")) - runAsPersistentWorker(args) - else delegate.apply(loadArguments(args, false)) + runAsPersistentWorker() + else WorkingDirectoryContext.newContext().use { ctx -> + delegate.apply(ctx.dir, loadArguments(args, false)) + } } - @Suppress("UNUSED_PARAMETER") - private fun runAsPersistentWorker(ignored: List): Int { + private fun runAsPersistentWorker(): Int { val realStdIn = System.`in` val realStdOut = System.out val realStdErr = System.err @@ -81,57 +85,33 @@ class BazelWorker( System.setIn(emptyIn) System.setOut(ps) System.setErr(ps) + val invocationWorker = InvocationWorker(delegate, buffer) while (true) { - val request = WorkerProtocol.WorkRequest.parseDelimitedFrom(realStdIn) ?: return 0 - val exitCode = try { - delegate.apply(loadArguments(request.argumentsList, true)) - } catch (e: RuntimeException) { - val innerExitCode = if (wasInterrupted(e)) INTERUPTED_STATUS - else ERROR_STATUS.also { - System.err.println( - "ERROR: Worker threw uncaught exception with args: ${request.argumentsList.joinToString( - " " - )}" - ) - e.printStackTrace(System.err) - } - WorkerProtocol.WorkResponse.newBuilder() - .setOutput(buffer.toString()) - .setExitCode(innerExitCode) - .build() - .writeDelimitedTo(realStdOut) - realStdOut.flush() - return innerExitCode - } + val status = + WorkerProtocol.WorkRequest.parseDelimitedFrom(realStdIn)?.let { request -> + invocationWorker.invoke(loadArguments(request.argumentsList, true)) + }?.also { (status, log) -> + with(WorkerProtocol.WorkResponse.newBuilder()) { + exitCode = status + output = log + build().writeDelimitedTo(realStdOut) + } + }?.let { (status, _) -> status } ?: OK - WorkerProtocol.WorkResponse.newBuilder() - .setOutput(buffer.toString()) - .setExitCode(exitCode) - .build() - .writeDelimitedTo(realStdOut) - realStdOut.flush() - buffer.reset() - System.gc() // be a good little worker process and consume less memory when idle + if (status != OK) { + return status + } + System.gc() } } } } - } catch (e: IOException) { - if (wasInterrupted(e)) { - return INTERUPTED_STATUS - } - throw e - } catch (e: RuntimeException) { - if (wasInterrupted(e)) { - return INTERUPTED_STATUS - } - throw e } finally { System.setIn(realStdIn) System.setOut(realStdOut) System.setErr(realStdErr) } - throw RuntimeException("drop through") + return OK } private fun loadArguments(args: List, isWorker: Boolean): List { @@ -142,10 +122,10 @@ class BazelWorker( val pathElement = lastArg.substring(1) val flagFile = Paths.get(pathElement) if (isWorker && lastArg.startsWith("@@") || Files.exists(flagFile)) { - if (!isWorker && !mnemonic.isEmpty()) { + if (!isWorker && mnemonic.isNotEmpty()) { output.printf( - "HINT: %s will compile faster if you run: " + "echo \"build --strategy=%s=worker\" >>~/.bazelrc\n", - mnemonic, mnemonic + "HINT: %s will compile faster if you run: " + "echo \"build --strategy=%s=worker\" >>~/.bazelrc\n", + mnemonic, mnemonic ) } try { @@ -158,13 +138,25 @@ class BazelWorker( } return args } +} - private fun wasInterrupted(e: Throwable): Boolean { - val cause = e.rootCause - if (cause is InterruptedException || cause is InterruptedIOException) { - output.println("Terminating worker due to interrupt signal") - return true - } - return false - } +class InvocationWorker( + private val delegate: CommandLineProgram, + private val buffer: ByteArrayOutputStream +) { + + fun invoke(args: List): Pair = WorkingDirectoryContext.newContext() + .use { wdCtx -> + return try { + delegate.apply(wdCtx.dir, args) + } catch (e: RuntimeException) { + if (e.wasInterrupted()) BazelWorker.INTERRUPTED_STATUS + else BazelWorker.ERROR_STATUS.also { + System.err.println( + "ERROR: Worker threw uncaught exception with args: ${args}" + ) + e.printStackTrace(System.err) + } + } to buffer.toString() + } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt index b1ddd94e9..d2e8ba8a5 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt @@ -5,13 +5,14 @@ * 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 + * 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. * - * 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. */ package io.bazel.kotlin.builder.tasks @@ -23,6 +24,7 @@ import io.bazel.kotlin.builder.utils.ArgMap import io.bazel.kotlin.builder.utils.ArgMaps import io.bazel.kotlin.builder.utils.Flag import io.bazel.kotlin.builder.utils.partitionJvmSources +import io.bazel.kotlin.builder.utils.resolveNewDirectories import io.bazel.kotlin.model.CompilationTaskInfo import io.bazel.kotlin.model.JsCompilationTask import io.bazel.kotlin.model.JvmCompilationTask @@ -30,8 +32,9 @@ import io.bazel.kotlin.model.Platform import io.bazel.kotlin.model.RuleKind import java.io.PrintStream import java.nio.charset.StandardCharsets +import java.nio.file.FileSystems import java.nio.file.Files -import java.nio.file.Paths +import java.nio.file.Path import java.util.regex.Pattern import javax.inject.Inject import javax.inject.Provider @@ -47,20 +50,74 @@ class KotlinBuilder @Inject internal constructor( companion object { @JvmStatic private val FLAGFILE_RE = Pattern.compile("""^--flagfile=((.*)-(\d+).params)$""").toRegex() + + /** + * Declares the flags used by the java builder. + */ + enum class JavaBuilderFlags(override val flag: String) : Flag { + TARGET_LABEL("--target_label"), + CLASSPATH("--classpath"), + JAVAC_OPTS("--javacopts"), + DEPENDENCIES("--dependencies"), + DIRECT_DEPENDENCIES("--direct_dependencies"), + DIRECT_DEPENDENCY("--direct_dependency"), + INDIRECT_DEPENDENCY("--indirect_dependency"), + STRICT_JAVA_DEPS("--strict_java_deps"), + OUTPUT_DEPS_PROTO("--output_deps_proto"), + DEPS_ARTIFACTS("--deps_artifacts"), + REDUCE_CLASSPATH("--reduce_classpath"), + SOURCEGEN_DIR("--sourcegendir"), + GENERATED_SOURCES_OUTPUT("--generated_sources_output"), + OUTPUT_MANIFEST_PROTO("--output_manifest_proto"), + SOURCES("--sources"), + SOURCE_ROOTS("--source_roots"), + SOURCE_JARS("--source_jars"), + SOURCE_PATH("--sourcepath"), + BOOT_CLASSPATH("--bootclasspath"), + PROCESSOR_PATH("--processorpath"), + PROCESSORS("--processors"), + EXT_CLASSPATH("--extclasspath"), + EXT_DIR("--extdir"), + OUTPUT("--output"), + NATIVE_HEADER_OUTPUT("--native_header_output"), + CLASSDIR("--classdir"), + TEMPDIR("--tempdir"), + GENDIR("--gendir"), + POST_PROCESSOR("--post_processor"), + COMPRESS_JAR("--compress_jar"), + RULE_KIND("--rule_kind"), + TEST_ONLY("--testonly"); + } + + enum class KotlinBuilderFlags(override val flag: String) : Flag { + MODULE_NAME("--kotlin_module_name"), + PASSTHROUGH_FLAGS("--kotlin_passthrough_flags"), + API_VERSION("--kotlin_api_version"), + LANGUAGE_VERSION("--kotlin_language_version"), + JVM_TARGET("--kotlin_jvm_target"), + OUTPUT_SRCJAR("--kotlin_output_srcjar"), + GENERATED_CLASSDIR("--kotlin_generated_classdir"), + FRIEND_PATHS("--kotlin_friend_paths"), + OUTPUT_JDEPS("--kotlin_output_jdeps"), + OUTPUT_JS_JAR("--kotlin_output_js_jar"), + JS_PASSTHROUGH_FLAGS("--kotlin_js_passthrough_flags"), + JS_LIBRARIES("--kotlin_js_libraries"), + DEBUG("--kotlin_debug_tags"), + TASK_ID("--kotlin_task_id"); + } } - override fun apply(args: List): Int { + override fun apply(workingDir: Path, args: List): Int { val (argMap, context) = buildContext(args) var success = false var status = 0 try { @Suppress("WHEN_ENUM_CAN_BE_NULL_IN_JAVA") when (context.info.platform) { - Platform.JVM -> executeJvmTask(context, argMap) - Platform.JS -> executeJsTask(context, argMap) + Platform.JVM -> executeJvmTask(context, workingDir, argMap) + Platform.JS -> executeJsTask(context, workingDir, argMap) Platform.UNRECOGNIZED -> throw IllegalStateException( - "unrecognized platform: ${context.info}" - ) + "unrecognized platform: ${context.info}") } success = true } catch (ex: CompilationStatusException) { @@ -76,72 +133,15 @@ class KotlinBuilder @Inject internal constructor( private fun buildContext(args: List): Pair { check(args.isNotEmpty()) { "expected at least a single arg got: ${args.joinToString(" ")}" } - val (flagFileName, primaryOutputPath, _) = - checkNotNull( - FLAGFILE_RE.matchEntire(args[0]) - ) { "invalid flagfile ${args[0]}" }.destructured - val argMap = - Files.readAllLines(Paths.get(flagFileName), StandardCharsets.UTF_8).let(ArgMaps::from) - val info = buildTaskInfo(argMap).also { - it.primaryOutputPath = primaryOutputPath - }.build() - val context = CompilationTaskContext(info, outputProvider.get()) - return Pair(argMap, context) - } - - /** - * Declares the flags used by the java builder. - */ - private enum class JavaBuilderFlags(override val flag: String) : Flag { - TARGET_LABEL("--target_label"), - CLASSPATH("--classpath"), - JAVAC_OPTS("--javacopts"), - DEPENDENCIES("--dependencies"), - DIRECT_DEPENDENCIES("--direct_dependencies"), - DIRECT_DEPENDENCY("--direct_dependency"), - INDIRECT_DEPENDENCY("--indirect_dependency"), - STRICT_JAVA_DEPS("--strict_java_deps"), - OUTPUT_DEPS_PROTO("--output_deps_proto"), - DEPS_ARTIFACTS("--deps_artifacts"), - REDUCE_CLASSPATH("--reduce_classpath"), - SOURCEGEN_DIR("--sourcegendir"), - GENERATED_SOURCES_OUTPUT("--generated_sources_output"), - OUTPUT_MANIFEST_PROTO("--output_manifest_proto"), - SOURCES("--sources"), - SOURCE_ROOTS("--source_roots"), - SOURCE_JARS("--source_jars"), - SOURCE_PATH("--sourcepath"), - BOOT_CLASSPATH("--bootclasspath"), - PROCESSOR_PATH("--processorpath"), - PROCESSORS("--processors"), - EXT_CLASSPATH("--extclasspath"), - EXT_DIR("--extdir"), - OUTPUT("--output"), - NATIVE_HEADER_OUTPUT("--native_header_output"), - CLASSDIR("--classdir"), - TEMPDIR("--tempdir"), - GENDIR("--gendir"), - POST_PROCESSOR("--post_processor"), - COMPRESS_JAR("--compress_jar"), - RULE_KIND("--rule_kind"), - TEST_ONLY("--testonly"); - } + val lines = FLAGFILE_RE.matchEntire(args[0])?.groups?.get(1)?.let { + Files.readAllLines(FileSystems.getDefault().getPath(it.value), StandardCharsets.UTF_8) + } ?: args - private enum class KotlinBuilderFlags(override val flag: String) : Flag { - MODULE_NAME("--kotlin_module_name"), - PASSTHROUGH_FLAGS("--kotlin_passthrough_flags"), - API_VERSION("--kotlin_api_version"), - LANGUAGE_VERSION("--kotlin_language_version"), - JVM_TARGET("--kotlin_jvm_target"), - OUTPUT_SRCJAR("--kotlin_output_srcjar"), - GENERATED_CLASSDIR("--kotlin_generated_classdir"), - FRIEND_PATHS("--kotlin_friend_paths"), - OUTPUT_JDEPS("--kotlin_output_jdeps"), - OUTPUT_JS_JAR("--kotlin_output_js_jar"), - JS_PASSTHROUGH_FLAGS("--kotlin_js_passthrough_flags"), - JS_LIBRARIES("--kotlin_js_libraries"), - DEBUG("--kotlin_debug_tags"), - TASK_ID("--kotlin_task_id"); + val argMap = ArgMaps.from(lines) + val info = buildTaskInfo(argMap).build() + val context = + CompilationTaskContext(info, outputProvider.get()) + return Pair(argMap, context) } private fun buildTaskInfo(argMap: ArgMap): CompilationTaskInfo.Builder = @@ -170,15 +170,29 @@ class KotlinBuilder @Inject internal constructor( this } - private fun executeJsTask(context: CompilationTaskContext, argMap: ArgMap) = - buildJsTask(context.info, argMap).let { jsTask -> + private fun executeJsTask( + context: CompilationTaskContext, + workingDir: Path, + argMap: ArgMap + ) = + buildJsTask(context.info, workingDir, argMap).let { jsTask -> context.whenTracing { printProto("js task input", jsTask) } jsTaskExecutor.execute(context, jsTask) } - private fun buildJsTask(info: CompilationTaskInfo, argMap: ArgMap): JsCompilationTask = + private fun buildJsTask( + info: CompilationTaskInfo, + workingDir: Path, + argMap: ArgMap + ): JsCompilationTask = with(JsCompilationTask.newBuilder()) { this.info = info + + with(directoriesBuilder) + { + temp = workingDir.toString() + } + with(inputsBuilder) { addAllLibraries(argMap.mandatory(KotlinBuilderFlags.JS_LIBRARIES)) addAllKotlinSources(argMap.mandatory(JavaBuilderFlags.SOURCES)) @@ -192,15 +206,19 @@ class KotlinBuilder @Inject internal constructor( build() } - private fun executeJvmTask(context: CompilationTaskContext, argMap: ArgMap) { - val task = buildJvmTask(context.info, argMap) + private fun executeJvmTask(context: CompilationTaskContext, workingDir: Path, argMap: ArgMap) { + val task = buildJvmTask(context.info, workingDir, argMap) context.whenTracing { printProto("jvm task message", task) } jvmTaskExecutor.execute(context, task) } - private fun buildJvmTask(info: CompilationTaskInfo, argMap: ArgMap): JvmCompilationTask = + private fun buildJvmTask( + info: CompilationTaskInfo, + workingDir: Path, + argMap: ArgMap + ): JvmCompilationTask = JvmCompilationTask.newBuilder().let { root -> root.info = info @@ -211,11 +229,17 @@ class KotlinBuilder @Inject internal constructor( argMap.optionalSingle(KotlinBuilderFlags.OUTPUT_JDEPS)?.apply { jdeps = this } } - with(root.directoriesBuilder) { - classes = argMap.mandatorySingle(JavaBuilderFlags.CLASSDIR) - generatedClasses = argMap.mandatorySingle(KotlinBuilderFlags.GENERATED_CLASSDIR) - temp = argMap.mandatorySingle(JavaBuilderFlags.TEMPDIR) - generatedSources = argMap.mandatorySingle(JavaBuilderFlags.SOURCEGEN_DIR) + with(root.directoriesBuilder) + { + classes = + workingDir.resolveNewDirectories(argMap.mandatorySingle(JavaBuilderFlags.CLASSDIR)) + .toString() + generatedClasses = workingDir.resolveNewDirectories( + argMap.mandatorySingle(KotlinBuilderFlags.GENERATED_CLASSDIR)).toString() + temp = workingDir.resolveNewDirectories(argMap.mandatorySingle(JavaBuilderFlags.TEMPDIR)) + .toString() + generatedSources = workingDir.resolveNewDirectories( + argMap.mandatorySingle(JavaBuilderFlags.SOURCEGEN_DIR)).toString() } with(root.inputsBuilder) { diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt index d2e59178b..ef7bdabd5 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt @@ -9,6 +9,8 @@ import io.bazel.kotlin.builder.utils.jars.SourceJarCreator import io.bazel.kotlin.builder.utils.resolveTwinVerified import io.bazel.kotlin.model.JsCompilationTask import java.io.FileOutputStream +import java.nio.file.FileSystem +import java.nio.file.FileSystems import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths @@ -16,16 +18,24 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class Kotlin2JsTaskExecutor @Inject constructor( - private val invoker: KotlinToolchain.K2JSCompilerInvoker -) { - fun execute(context: CompilationTaskContext, task: JsCompilationTask) { +class Kotlin2JsTaskExecutor @Inject constructor(private val invoker: KotlinToolchain.K2JSCompilerInvoker) { + + private val fileSystem: FileSystem = FileSystems.getDefault() + + fun execute( + context: CompilationTaskContext, + task: JsCompilationTask + ) { task.compile(context) - val jsPath = Paths.get(task.outputs.js) + val jsPath = fileSystem.getPath(task.outputs.js) val jsMetaFile = jsPath.resolveTwinVerified(".meta.js") - val jsDirectory = jsPath.parent.resolve(jsPath.toFile().nameWithoutExtension) - task.createJar(jsDirectory, listOf(jsPath, jsPath.resolveTwinVerified(".js.map"), jsMetaFile)) + val jsDirectory = Files.createDirectories( + fileSystem.getPath(task.directories.temp) + .resolve(jsPath.toFile().nameWithoutExtension) + ) + task.createJar(jsDirectory, + listOf(jsPath, jsPath.resolveTwinVerified(".js.map"), jsMetaFile)) // this mutates the jsPath file , so do it after creating the jar. appendMetaToPrimary(jsPath, jsMetaFile) task.createSourceJar() @@ -45,8 +55,12 @@ class Kotlin2JsTaskExecutor @Inject constructor( private fun JsCompilationTask.createSourceJar() { try { SourceJarCreator(Paths.get(outputs.srcjar), false).also { creator -> - creator.addSources(inputs.kotlinSourcesList.map { Paths.get(it) }.stream()) - }.execute() + creator.addSources( + inputs.kotlinSourcesList.map { Paths.get(it) } + .stream() + ) + } + .execute() } catch (ex: Throwable) { throw CompilationException("could not create source jar", ex) } @@ -56,7 +70,10 @@ class Kotlin2JsTaskExecutor @Inject constructor( * Append the meta file to the JS file. This is an accepted pattern, and it allows us to not have to export the * meta.js file with the js. */ - private fun appendMetaToPrimary(jsPath: Path, jsMetaFile: Path) { + private fun appendMetaToPrimary( + jsPath: Path, + jsMetaFile: Path + ) { try { FileOutputStream(jsPath.toFile(), true).use { Files.copy(jsMetaFile, it) } } catch (ex: Throwable) { @@ -64,7 +81,10 @@ class Kotlin2JsTaskExecutor @Inject constructor( } } - private fun JsCompilationTask.createJar(jsDirectoryPath: Path, rootEntries: List) { + private fun JsCompilationTask.createJar( + jsDirectoryPath: Path, + rootEntries: List + ) { try { val outputJarPath = Paths.get(outputs.jar) diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt index 72a95ae06..957fc737b 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt @@ -5,13 +5,14 @@ * 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 + * 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. * - * 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. */ // Provides extensions for the JvmCompilationTask protocol buffer. @@ -22,7 +23,6 @@ import io.bazel.kotlin.builder.toolchain.KotlinCompilerPluginArgsEncoder import io.bazel.kotlin.builder.toolchain.KotlinToolchain import io.bazel.kotlin.builder.utils.IS_JVM_SOURCE_FILE import io.bazel.kotlin.builder.utils.bazelRuleKind -import io.bazel.kotlin.builder.utils.ensureDirectories import io.bazel.kotlin.builder.utils.jars.JarCreator import io.bazel.kotlin.builder.utils.jars.SourceJarCreator import io.bazel.kotlin.builder.utils.jars.SourceJarExtractor @@ -53,12 +53,6 @@ internal fun JvmCompilationTask.baseArgs(): CompilationArgs = CompilationArgs() .flag("-module-name", info.moduleName) internal fun JvmCompilationTask.preProcessingSteps(context: CompilationTaskContext): JvmCompilationTask { - ensureDirectories( - directories.temp, - directories.generatedSources, - directories.generatedClasses, - directories.classes - ) return context.execute("expand sources") { expandWithSourceJarSources() } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt index fc0107b99..9b1675223 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt @@ -5,13 +5,14 @@ * 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 + * 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. * - * 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. */ package io.bazel.kotlin.builder.toolchain @@ -22,13 +23,15 @@ import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.File import java.io.PrintStream -import java.nio.file.Paths +import java.nio.file.FileSystems -class CompilationTaskContext(val info: CompilationTaskInfo, private val out: PrintStream) { +class CompilationTaskContext( + val info: CompilationTaskInfo, + private val out: PrintStream, + private val executionRoot: String = FileSystems.getDefault().getPath("").toAbsolutePath() + .toString() + File.separator +) { private val start = System.currentTimeMillis() - private val executionRoot: String = Paths.get( - System.getProperty("user.dir") - ).toAbsolutePath().toString() + File.separator private var timings: MutableList? private var level = -1 private val isTracing: Boolean @@ -171,9 +174,7 @@ class CompilationTaskContext(val info: CompilationTaskInfo, private val out: Pri if (successful) { timings?.also { printLines( - "Task timings for ${info.label} (total: ${System.currentTimeMillis() - start} ms)", - it - ) + "Task timings for ${info.label} (total: ${System.currentTimeMillis() - start} ms)", it) } } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/IOUtils.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/IOUtils.kt index faef6b3db..e964254f9 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/IOUtils.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/IOUtils.kt @@ -5,13 +5,14 @@ * 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 + * 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. * - * 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. */ @file:JvmName("IOUtils") @@ -19,6 +20,7 @@ package io.bazel.kotlin.builder.utils import java.io.BufferedReader import java.io.File +import java.io.InterruptedIOException import java.io.PrintStream import java.nio.file.Files import java.nio.file.Path @@ -70,23 +72,21 @@ fun Path.resolveTwinVerified(extension: String): Path = "${toFile().nameWithoutExtension}${if (extension.startsWith(".")) "" else "."}$extension" ).verified().toPath() +fun Path.resolveNewDirectories(vararg parts: String) = Files.createDirectories( + parts.fold(this, Path::resolve)) + fun Path.resolveVerified(vararg parts: String): File = resolve(Paths.get(parts[0], *Arrays.copyOfRange(parts, 1, parts.size))).verified() fun Path.resolveVerifiedToAbsoluteString(vararg parts: String): String = resolveVerified(*parts).absolutePath.toString() -fun Path.verified(): File = - this.toFile().also { check(it.exists()) { "file did not exist: $this" } } +fun Path.verified(): File = this.toFile() + .also { check(it.exists()) { "file did not exist: $this" } } -fun Path.verifiedPath(): Path = - this.toFile().also { check(it.exists()) { "file did not exist: $this" } }.toPath() +fun Path.verifiedPath(): Path = this.toFile() + .also { check(it.exists()) { "file did not exist: $this" } }.toPath() -fun ensureDirectories(vararg directories: String) { - for (directory in directories) { - Files.createDirectories(Paths.get(directory)) - } -} val Throwable.rootCause: Throwable get() { @@ -97,3 +97,11 @@ val Throwable.rootCause: Throwable } while (cause != null && result != cause) return result } + +fun Throwable.wasInterrupted(): Boolean { + val cause = rootCause + if (cause is InterruptedException || cause is InterruptedIOException) { + return true + } + return false +} diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/WorkingDirectoryContext.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/WorkingDirectoryContext.kt new file mode 100644 index 000000000..2d2bbdc9b --- /dev/null +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/WorkingDirectoryContext.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2020 The Bazel Authors. All rights reserved. + * + * Licensed 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. + * + */ + +package io.bazel.kotlin.builder.utils + +import java.io.Closeable +import java.nio.file.Files +import java.nio.file.Path + +/** WorkingDirectoryContext provides a consistent base directory that is removed on close. */ +class WorkingDirectoryContext(val dir: Path) : Closeable { + companion object { + fun newContext(): WorkingDirectoryContext = WorkingDirectoryContext( + Files.createTempDirectory("working")) + } + + override fun close() { + Files.walk(dir).sorted(Comparator.reverseOrder()).forEach(Files::delete) + } +} diff --git a/src/main/protobuf/kotlin_model.proto b/src/main/protobuf/kotlin_model.proto index 5fcacf770..0615875ec 100644 --- a/src/main/protobuf/kotlin_model.proto +++ b/src/main/protobuf/kotlin_model.proto @@ -131,6 +131,13 @@ message JvmCompilationTask { } message JsCompilationTask { + + // Directories used by the builder. + message Directories { + // A temp directory that the compiler may use. + string temp = 4; + } + message Outputs { // The primary output string js = 1; @@ -150,4 +157,6 @@ message JsCompilationTask { // flags that should be passed through straight to the kotlinc-js compiler. repeated string pass_through_flags = 5; + + Directories directories = 6; } diff --git a/src/test/kotlin/io/bazel/kotlin/builder/BUILD b/src/test/kotlin/io/bazel/kotlin/builder/BUILD index 6ae01a275..1a4b49266 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/BUILD +++ b/src/test/kotlin/io/bazel/kotlin/builder/BUILD @@ -14,7 +14,6 @@ package(default_visibility = ["//src:__subpackages__"]) load("@rules_java//java:defs.bzl", "java_library") -load("//src/test/kotlin/io/bazel/kotlin:defs.bzl", "kt_rules_test") _COMMON_DEPS = [ "//src/main/kotlin/io/bazel/kotlin/builder", @@ -37,6 +36,7 @@ java_library( "KotlinAbstractTestBuilder.java", "KotlinJsTestBuilder.java", "KotlinJvmTestBuilder.java", + "KotlinBuilderTestComponent.java" ], data = [ "//src/main/kotlin/io/bazel/kotlin/compiler", @@ -51,6 +51,8 @@ java_library( ], deps = _COMMON_DEPS + [ "//third_party:autovalue", + "//third_party:dagger", + "//src/main/kotlin/io/bazel/kotlin/builder/tasks" ], ) diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java index f89145d7b..20857e3a9 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java @@ -5,13 +5,14 @@ * 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 + * 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. * - * 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. */ package io.bazel.kotlin.builder; @@ -141,15 +142,18 @@ public final Path writeGeneratedSourceFile(String filename, String[] lines) { return writeFile(DirectoryType.SOURCE_GEN, filename, lines); } + final R runCompileTask(BiFunction operation) { + T task = buildTask(); + return runCompileTask(infoBuilder.build(), task, (ctx, t) -> operation.apply(ctx, task)); + } + private R runCompileTask( CompilationTaskInfo info, T task, BiFunction operation) { - String curDir = System.getProperty("user.dir"); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); try (PrintStream outputStream = new PrintStream(byteArrayOutputStream)) { - System.setProperty("user.dir", instanceRoot().toAbsolutePath().toString()); - return operation.apply(new CompilationTaskContext(info, outputStream), task); + return operation.apply(new CompilationTaskContext(info, outputStream, + instanceRoot().toAbsolutePath().toString() + File.separator), task); } finally { - System.setProperty("user.dir", curDir); outLines = Collections.unmodifiableList( new BufferedReader( @@ -161,9 +165,17 @@ private R runCompileTask( } } - final R runCompileTask(BiFunction operation) { - T task = buildTask(); - return runCompileTask(infoBuilder.build(), task, (ctx, t) -> operation.apply(ctx, task)); + public final void assertFilesExist(DirectoryType dir, String... paths) { + assertFileExistence(resolved(dir, paths), true); + } + + final void assertFilesExist(String... paths) { + assertFileExistence(Stream.of(paths).map(Paths::get), true); + } + + @SuppressWarnings("unused") + public final void assertFilesDoNotExist(DirectoryType dir, String... filePath) { + assertFileExistence(resolved(dir, filePath), false); } /** @@ -183,19 +195,6 @@ public final void runFailingCompileTaskAndValidateOutput( throw new RuntimeException("compilation task should have failed."); } - public final void assertFilesExist(DirectoryType dir, String... paths) { - assertFileExistence(resolved(dir, paths), true); - } - - final void assertFilesExist(String... paths) { - assertFileExistence(Stream.of(paths).map(Paths::get), true); - } - - @SuppressWarnings("unused") - public final void assertFilesDoNotExist(DirectoryType dir, String... filePath) { - assertFileExistence(resolved(dir, filePath), false); - } - private Stream resolved(DirectoryType dir, String... filePath) { Path directory = directory(dir); return Stream.of(filePath).map(f -> directory.resolve(toPlatformPath(f))); diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinBuilderTestComponent.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinBuilderTestComponent.java new file mode 100644 index 000000000..813e8cf9b --- /dev/null +++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinBuilderTestComponent.java @@ -0,0 +1,50 @@ +/* + * Copyright 2020 The Bazel Authors. All rights reserved. + * + * Licensed 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. + * + */ + +package io.bazel.kotlin.builder; + +import dagger.BindsInstance; +import dagger.Component; +import io.bazel.kotlin.builder.tasks.BazelWorker; +import io.bazel.kotlin.builder.tasks.KotlinBuilder; +import io.bazel.kotlin.builder.tasks.js.Kotlin2JsTaskExecutor; +import io.bazel.kotlin.builder.tasks.jvm.KotlinJvmTaskExecutor; +import io.bazel.kotlin.builder.toolchain.KotlinToolchain; +import javax.inject.Singleton; + +@Singleton +@dagger.Component(modules = {KotlinBuilderComponent.Module.class}) +public interface KotlinBuilderTestComponent { + + KotlinBuilder kotlinBuilder(); + + KotlinToolchain toolchain(); + + KotlinJvmTaskExecutor jvmTaskExecutor(); + + Kotlin2JsTaskExecutor jsTaskExecutor(); + + BazelWorker worker(); + + @Component.Builder + interface Builder { + @BindsInstance + Builder toolchain(KotlinToolchain toolchain); + + KotlinBuilderTestComponent build(); + } +} diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java index 598bd14ff..d82ce67c3 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java @@ -5,13 +5,14 @@ * 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 + * 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. * - * 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. */ package io.bazel.kotlin.builder; @@ -74,8 +75,8 @@ public final Dep runCompileTask(Consumer... setup) { return executeTask(component().jvmTaskExecutor()::execute, setup); } - private KotlinBuilderComponent component() { - return DaggerKotlinBuilderComponent.builder() + public static KotlinBuilderTestComponent component() { + return DaggerKotlinBuilderTestComponent.builder() .toolchain(KotlinToolchain.createToolchain()) .build(); } diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel b/src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel index 567921052..33e9600dc 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel +++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel @@ -22,11 +22,17 @@ kt_rules_test( ], ) +kt_rules_test( + name = "KotlinWorkerTest", + srcs = ["jvm/KotlinWorkerTest.kt"], +) + kt_rules_test( name = "KotlinBuilderJvmBasicTest", srcs = ["jvm/KotlinBuilderJvmBasicTest.java"], ) + # TODO(bazelbuild/rules_kotlin/issues/275): Remove full jar reference when the kt_rules_test handles jvm_import data better. _MAVEN_CENTRAL_PREFIX = "@kotlin_rules_maven//:v1/https/maven-central.storage.googleapis.com/repos/central/data" diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinWorkerTest.kt b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinWorkerTest.kt new file mode 100644 index 000000000..b4e725147 --- /dev/null +++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinWorkerTest.kt @@ -0,0 +1,180 @@ +/* + * Copyright 2020 The Bazel Authors. All rights reserved. + * + * Licensed 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. + * + */ + +package io.bazel.kotlin.builder.tasks.jvm + +import com.google.common.truth.Truth.assertThat +import io.bazel.kotlin.builder.KotlinJvmTestBuilder +import io.bazel.kotlin.builder.tasks.BazelWorker.Companion.OK +import io.bazel.kotlin.builder.tasks.InvocationWorker +import io.bazel.kotlin.builder.tasks.KotlinBuilder.Companion.JavaBuilderFlags +import io.bazel.kotlin.builder.tasks.KotlinBuilder.Companion.KotlinBuilderFlags +import io.bazel.kotlin.model.CompilationTaskInfo +import io.bazel.kotlin.model.Platform +import io.bazel.kotlin.model.RuleKind +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import java.io.ByteArrayOutputStream +import java.io.IOException +import java.io.OutputStream +import java.io.PrintStream +import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.nio.file.Path +import java.util.zip.ZipEntry +import java.util.zip.ZipFile +import kotlin.streams.toList + +@RunWith(JUnit4::class) +class KotlinWorkerTest { + + private val wrkDir = Files.createTempDirectory("KotlinBuilderEnvironmentTest") + + class SourceBuilder(private val out: ByteArrayOutputStream = ByteArrayOutputStream()) { + val ln = "\n".toByteArray(StandardCharsets.UTF_8) + fun l(l: String) { + out.write(l.toByteArray(StandardCharsets.UTF_8)) + out.write(ln) + } + + fun bytes(): ByteArray { + return out.toByteArray() + } + } + + private fun src(path: String, writeLines: (SourceBuilder.() -> Unit)): Path { + val srcPath = Files.createDirectories(wrkDir.resolve("src")).resolve(path) + val b = SourceBuilder() + b.writeLines() + Files.write(srcPath, b.bytes()) + + require(Files.readAllLines(srcPath).isNotEmpty()) { + "failed to write $srcPath" + } + return srcPath + } + + private fun args(src: Path, jar: Path, info: CompilationTaskInfo) = listOf( + JavaBuilderFlags.TARGET_LABEL.flag, info.label, + KotlinBuilderFlags.MODULE_NAME.flag, info.moduleName, + KotlinBuilderFlags.API_VERSION.flag, info.toolchainInfo.common.apiVersion, + KotlinBuilderFlags.LANGUAGE_VERSION.flag, info.toolchainInfo.common.languageVersion, + JavaBuilderFlags.RULE_KIND.flag, "kt_${info.platform.name}_${info.ruleKind.name}", + JavaBuilderFlags.OUTPUT.flag, jar.toString(), + KotlinBuilderFlags.OUTPUT_SRCJAR.flag, "$jar.srcjar", + KotlinBuilderFlags.OUTPUT_JDEPS.flag, "out.jdeps", + JavaBuilderFlags.CLASSDIR.flag, "kt_classes", + KotlinBuilderFlags.GENERATED_CLASSDIR.flag, "generated_classes", + JavaBuilderFlags.TEMPDIR.flag, "tmp", + JavaBuilderFlags.SOURCEGEN_DIR.flag, "generated_sources", + JavaBuilderFlags.CLASSPATH.flag, KotlinJvmTestBuilder.KOTLIN_STDLIB.singleCompileJar(), + JavaBuilderFlags.SOURCES.flag, src.toString(), + KotlinBuilderFlags.PASSTHROUGH_FLAGS.flag, info.passthroughFlags, + KotlinBuilderFlags.DEBUG.flag, info.debugList.joinToString(","), + KotlinBuilderFlags.JVM_TARGET.flag, info.toolchainInfo.jvm.jvmTarget + ) + + @Test + fun `output directories are different for invocations`() { + + val builder = KotlinJvmTestBuilder.component().kotlinBuilder() + + val one = src("One.kt") { + l("package harry.nilsson") + l("") + l("class One {") + l(" fun isTheLoneliestNumber():String {") + l(" return \"that you'll ever do\"") + l(" }") + l("}") + } + + val two = src("Two.kt") { + l("package harry.nilsson") + l("class Two {") + l(" fun canBeAsBadAsOne():String {") + l(" return \"it is the loneliest number since the number one\"") + l(" }") + l("}") + } + + // output buffer for compiler logs. + val outputStream = ByteArrayOutputStream() + val stdOut = System.out + + // tee the stdout -- useful for debugging, but also used as + // part of the compilation task output. + System.setOut(PrintStream(object : OutputStream() { + @Throws(IOException::class) override fun write(b: Int) { + outputStream.write(b) + stdOut.write(b) + } + })) + + val worker = InvocationWorker(delegate = builder, buffer = outputStream) + + val jarOne = out("one.jar") + + assertThat(worker.invoke(args(one, jarOne, compilationTaskInfo))).isEqualTo(OK to "") + + System.err.println(ZipFile(jarOne.toFile()) + .stream() + .map(ZipEntry::getName) + .toList()) + + assertThat( + ZipFile(jarOne.toFile()) + .stream() + .map(ZipEntry::getName) + .filter { it.endsWith(".class") } + .toList() + ).containsExactly("harry/nilsson/One.class") + + val jarTwo = out("two.jar") + assertThat(worker.invoke(args(two, jarTwo, compilationTaskInfo))).isEqualTo(OK to "") + assertThat( + ZipFile(jarTwo.toFile()) + .stream() + .map(ZipEntry::getName) + .filter { it.endsWith(".class") } + .toList() + ).containsExactly("harry/nilsson/Two.class") + } + + private fun out(name: String): Path { + return Files.createDirectories(wrkDir.resolve("out")).resolve(name) + } + + private val compilationTaskInfo: CompilationTaskInfo + get() { + return with(CompilationTaskInfo.newBuilder()) { + label = "//singing/nilsson:one" + moduleName = "harry.nilsson" + platform = Platform.JVM + ruleKind = RuleKind.LIBRARY + toolchainInfo = with(toolchainInfoBuilder) { + common = + commonBuilder.setApiVersion("1.3").setCoroutines("enabled").setLanguageVersion("1.3") + .build() + jvm = jvmBuilder.setJvmTarget("1.8").build() + build() + } + build() + } + } +} From 484f116c1949984697556bcd371ef8eecacc08cb Mon Sep 17 00:00:00 2001 From: Ilja Kroonen Date: Mon, 6 Apr 2020 23:02:30 +0200 Subject: [PATCH 15/16] Adds a kt_plugin rule (#308) Creates a `kt_compiler_plugin` rule to allow kotlin compiler plugins to be specified, and then included with a `plugins=` attribute on kt_jvm_* jobs. This should support arbitrary kotlin compiler plugins, such as the android extensions, open-for-testing, and others. This does _not_ add an exported_plugins infrastructure (such as you get with java_plugins), and it does not change the special-case handling of kapt. It also doesn't do anything to resolve plugin inter-0compatibilities (e.g. the ABI plugin possibly needing information from the parcelizable, or other such interactions) The latter are issues yet to be figured out int he kotlinc plugin infrastructure, and we'll adapt this rule as appropriate. Also adds docs and examples. --- README.md | 35 ++++++++++++- examples/plugin/src/allopen/BUILD | 36 +++++++++++++ examples/plugin/src/allopen/OpenForTesting.kt | 3 ++ examples/plugin/src/allopen/User.kt | 9 ++++ examples/plugin/src/allopen/UserIsOpenTest.kt | 5 ++ examples/plugin/src/noarg/BUILD | 38 ++++++++++++++ examples/plugin/src/noarg/NoArgConstructor.kt | 3 ++ examples/plugin/src/noarg/User.kt | 9 ++++ .../src/noarg/UserHasNoargConstructorTest.kt | 13 +++++ examples/plugin/src/sam_with_receiver/BUILD | 31 +++++++++++ .../plugin/src/sam_with_receiver/Runner.java | 6 +++ .../src/sam_with_receiver/RunnerTest.kt | 5 ++ .../src/sam_with_receiver/SamWithReceiver.kt | 3 ++ kotlin/internal/compiler_plugins.bzl | 21 ++++++++ kotlin/internal/defs.bzl | 7 +++ kotlin/internal/jvm/compile.bzl | 29 +++++++++-- kotlin/internal/jvm/impl.bzl | 19 +++++++ kotlin/internal/jvm/jvm.bzl | 52 +++++++++++++++++++ kotlin/internal/jvm/plugins.bzl | 9 ++-- .../BUILD.com_github_jetbrains_kotlin | 15 ++++++ kotlin/kotlin.bzl | 2 + .../builder/KotlinBuilderComponent.java | 6 +-- .../kotlin/builder/tasks/KotlinBuilder.kt | 5 ++ .../tasks/jvm/KotlinJvmTaskExecutor.kt | 6 +-- .../builder/tasks/jvm/compilation_task.kt | 25 ++++++--- ...er.kt => KaptCompilerPluginArgsEncoder.kt} | 2 +- src/main/protobuf/kotlin_model.proto | 4 ++ 27 files changed, 376 insertions(+), 22 deletions(-) create mode 100644 examples/plugin/src/allopen/BUILD create mode 100644 examples/plugin/src/allopen/OpenForTesting.kt create mode 100644 examples/plugin/src/allopen/User.kt create mode 100644 examples/plugin/src/allopen/UserIsOpenTest.kt create mode 100644 examples/plugin/src/noarg/BUILD create mode 100644 examples/plugin/src/noarg/NoArgConstructor.kt create mode 100644 examples/plugin/src/noarg/User.kt create mode 100644 examples/plugin/src/noarg/UserHasNoargConstructorTest.kt create mode 100644 examples/plugin/src/sam_with_receiver/BUILD create mode 100644 examples/plugin/src/sam_with_receiver/Runner.java create mode 100644 examples/plugin/src/sam_with_receiver/RunnerTest.kt create mode 100644 examples/plugin/src/sam_with_receiver/SamWithReceiver.kt create mode 100644 kotlin/internal/compiler_plugins.bzl rename src/main/kotlin/io/bazel/kotlin/builder/toolchain/{KotlinCompilerPluginArgsEncoder.kt => KaptCompilerPluginArgsEncoder.kt} (98%) diff --git a/README.md b/README.md index 3b23dcc5f..c114caffa 100644 --- a/README.md +++ b/README.md @@ -161,9 +161,42 @@ kotlin_repositories() # if you want the default. Otherwise see custom kotlinc di kt_register_toolchains() # to use the default toolchain, otherwise see toolchains below ``` +# Kotlin compiler plugins + +The `kt_compiler_plugin` rule allows running Kotlin compiler plugins, such as no-arg, sam-with-receiver and allopen. + +For example, you can add allopen to your project like this: +```python +load("//kotlin:kotlin.bzl", "kt_compiler_plugin", "kt_jvm_library") + +kt_compiler_plugin( + name = "open_for_testing_plugin", + id = "org.jetbrains.kotlin.allopen", + options = { + "annotation": "plugin.allopen.OpenForTesting", + }, + deps = [ + "@com_github_jetbrains_kotlin//:allopen-compiler-plugin", + ], +) + +kt_jvm_library( + name = "user", + srcs = ["User.kt"], # The User class is annotated with OpenForTesting + plugins = [ + ":open_for_testing_plugin", + ], + deps = [ + ":open_for_testing", # This contains the annotation (plugin.allopen.OpenForTesting) + ], +) +``` + +Full examples of using compiler plugins can be found [here](examples/plugin). + ## Examples -Examples can be found in the [examples directory](https://github.com/bazelbuild/rules_kotlin/tree/master/examples), including usage with Android, Dagger, Node-JS, etc. +Examples can be found in the [examples directory](https://github.com/bazelbuild/rules_kotlin/tree/master/examples), including usage with Android, Dagger, Node-JS, Kotlin compiler plugins, etc. # History diff --git a/examples/plugin/src/allopen/BUILD b/examples/plugin/src/allopen/BUILD new file mode 100644 index 000000000..b33ada58f --- /dev/null +++ b/examples/plugin/src/allopen/BUILD @@ -0,0 +1,36 @@ +load("//kotlin:kotlin.bzl", "kt_compiler_plugin", "kt_jvm_library") + +kt_compiler_plugin( + name = "open_for_testing_plugin", + id = "org.jetbrains.kotlin.allopen", + options = { + "annotation": "plugin.allopen.OpenForTesting", + }, + deps = [ + "@com_github_jetbrains_kotlin//:allopen-compiler-plugin", + ], +) + +kt_jvm_library( + name = "open_for_testing", + srcs = ["OpenForTesting.kt"], +) + +kt_jvm_library( + name = "user", + srcs = ["User.kt"], + plugins = [ + ":open_for_testing_plugin", + ], + deps = [ + ":open_for_testing", + ], +) + +kt_jvm_library( + name = "user_is_open_test", + srcs = ["UserIsOpenTest.kt"], + deps = [ + ":user", + ], +) diff --git a/examples/plugin/src/allopen/OpenForTesting.kt b/examples/plugin/src/allopen/OpenForTesting.kt new file mode 100644 index 000000000..551688f67 --- /dev/null +++ b/examples/plugin/src/allopen/OpenForTesting.kt @@ -0,0 +1,3 @@ +package plugin.allopen + +annotation class OpenForTesting diff --git a/examples/plugin/src/allopen/User.kt b/examples/plugin/src/allopen/User.kt new file mode 100644 index 000000000..87cf6de32 --- /dev/null +++ b/examples/plugin/src/allopen/User.kt @@ -0,0 +1,9 @@ +package plugin.allopen; + +import java.util.* + +@OpenForTesting +data class User( + val userId: UUID, + val emails: String +) diff --git a/examples/plugin/src/allopen/UserIsOpenTest.kt b/examples/plugin/src/allopen/UserIsOpenTest.kt new file mode 100644 index 000000000..575b003fa --- /dev/null +++ b/examples/plugin/src/allopen/UserIsOpenTest.kt @@ -0,0 +1,5 @@ +package plugin.allopen + +import java.util.* + +class Subclass : User(UUID.randomUUID(), "test@example.org") diff --git a/examples/plugin/src/noarg/BUILD b/examples/plugin/src/noarg/BUILD new file mode 100644 index 000000000..5de0d4fc5 --- /dev/null +++ b/examples/plugin/src/noarg/BUILD @@ -0,0 +1,38 @@ +load("//kotlin:kotlin.bzl", "kt_compiler_plugin", "kt_jvm_library", "kt_jvm_test") + +kt_compiler_plugin( + name = "no_arg_plugin", + id = "org.jetbrains.kotlin.noarg", + options = { + "annotation": "plugin.noarg.NoArgConstructor", + }, + deps = [ + "@com_github_jetbrains_kotlin//:noarg-compiler-plugin", + ], +) + +kt_jvm_library( + name = "no_arg_constructor", + srcs = ["NoArgConstructor.kt"], +) + +kt_jvm_library( + name = "user", + srcs = ["User.kt"], + plugins = [":no_arg_plugin"], + deps = [ + ":no_arg_constructor", + ], +) + +# The no-arg constructor that is generated cannot be compiled against, but should be discoverable at runtime. +kt_jvm_test( + name = "user_has_noarg_constructor_test", + srcs = ["UserHasNoargConstructorTest.kt"], + test_class = "plugin.noarg.UserHasNoargConstructorTest", + deps = [ + ":user", + "@com_github_jetbrains_kotlin//:kotlin-reflect", + "@kotlin_rules_maven//:junit_junit", + ], +) diff --git a/examples/plugin/src/noarg/NoArgConstructor.kt b/examples/plugin/src/noarg/NoArgConstructor.kt new file mode 100644 index 000000000..8ab9276cc --- /dev/null +++ b/examples/plugin/src/noarg/NoArgConstructor.kt @@ -0,0 +1,3 @@ +package plugin.noarg + +annotation class NoArgConstructor diff --git a/examples/plugin/src/noarg/User.kt b/examples/plugin/src/noarg/User.kt new file mode 100644 index 000000000..19939da9f --- /dev/null +++ b/examples/plugin/src/noarg/User.kt @@ -0,0 +1,9 @@ +package plugin.noarg; + +import java.util.* + +@NoArgConstructor +data class User( + val userId: UUID, + val emails: String +) diff --git a/examples/plugin/src/noarg/UserHasNoargConstructorTest.kt b/examples/plugin/src/noarg/UserHasNoargConstructorTest.kt new file mode 100644 index 000000000..292cbb283 --- /dev/null +++ b/examples/plugin/src/noarg/UserHasNoargConstructorTest.kt @@ -0,0 +1,13 @@ +package plugin.noarg + +import org.junit.* +import java.lang.Exception + +class UserHasNoargConstructorTest { + @Test + fun userShouldHaveNoargConstructor() { + if (User::class.java.constructors.none { it.parameters.isEmpty() }) { + throw Exception("Expected an empty constructor to exist") + } + } +} diff --git a/examples/plugin/src/sam_with_receiver/BUILD b/examples/plugin/src/sam_with_receiver/BUILD new file mode 100644 index 000000000..03b90e60e --- /dev/null +++ b/examples/plugin/src/sam_with_receiver/BUILD @@ -0,0 +1,31 @@ +load("//kotlin:kotlin.bzl", "kt_compiler_plugin", "kt_jvm_library") +load("@rules_java//java:defs.bzl", "java_library") + +kt_compiler_plugin( + name = "sam_with_receiver_plugin", + id = "org.jetbrains.kotlin.samWithReceiver", + options = { + "annotation": "plugin.sam_with_receiver.SamWithReceiver", + }, + deps = [ + "@com_github_jetbrains_kotlin//:sam-with-receiver-compiler-plugin", + ], +) + +kt_jvm_library( + name = "sam_with_receiver", + srcs = ["SamWithReceiver.kt"], +) + +java_library( + name = "runner", + srcs = ["Runner.java"], + deps = [":sam_with_receiver"], +) + +kt_jvm_library( + name = "runner_test", + srcs = ["RunnerTest.kt"], + plugins = [":sam_with_receiver_plugin"], + deps = [":runner"], +) diff --git a/examples/plugin/src/sam_with_receiver/Runner.java b/examples/plugin/src/sam_with_receiver/Runner.java new file mode 100644 index 000000000..ce5f11e3f --- /dev/null +++ b/examples/plugin/src/sam_with_receiver/Runner.java @@ -0,0 +1,6 @@ +package plugin.sam_with_receiver; + +@SamWithReceiver +public interface Runner { + void run(Double shouldBecomeThis); +} diff --git a/examples/plugin/src/sam_with_receiver/RunnerTest.kt b/examples/plugin/src/sam_with_receiver/RunnerTest.kt new file mode 100644 index 000000000..122192aaf --- /dev/null +++ b/examples/plugin/src/sam_with_receiver/RunnerTest.kt @@ -0,0 +1,5 @@ +package plugin.sam_with_receiver + +val thisShouldWork = Runner { + println(this.isFinite()) +} diff --git a/examples/plugin/src/sam_with_receiver/SamWithReceiver.kt b/examples/plugin/src/sam_with_receiver/SamWithReceiver.kt new file mode 100644 index 000000000..907de9896 --- /dev/null +++ b/examples/plugin/src/sam_with_receiver/SamWithReceiver.kt @@ -0,0 +1,3 @@ +package plugin.sam_with_receiver + +annotation class SamWithReceiver diff --git a/kotlin/internal/compiler_plugins.bzl b/kotlin/internal/compiler_plugins.bzl new file mode 100644 index 000000000..4306a0d40 --- /dev/null +++ b/kotlin/internal/compiler_plugins.bzl @@ -0,0 +1,21 @@ +load( + "//kotlin/internal:defs.bzl", + _KtCompilerPluginInfo = "KtCompilerPluginInfo", +) + +def plugins_to_classpaths(providers_list): + flattened_files = [] + for providers in providers_list: + if _KtCompilerPluginInfo in providers: + provider = providers[_KtCompilerPluginInfo] + for e in provider.classpath: + flattened_files.append(e) + return flattened_files + +def plugins_to_options(providers_list): + kt_compiler_plugin_providers = [providers[_KtCompilerPluginInfo] for providers in providers_list if _KtCompilerPluginInfo in providers] + flattened_options = [] + for provider in kt_compiler_plugin_providers: + for option in provider.options: + flattened_options.append("%s:%s" % (option.id, option.value)) + return flattened_options diff --git a/kotlin/internal/defs.bzl b/kotlin/internal/defs.bzl index fddc2ce6f..2fe00b70d 100644 --- a/kotlin/internal/defs.bzl +++ b/kotlin/internal/defs.bzl @@ -35,3 +35,10 @@ KtJsInfo = provider( "srcjar": "The jar containing the sources of the library", }, ) + +KtCompilerPluginInfo = provider( + fields = { + "classpath": "The kotlin compiler plugin classpath", + "options": "List of plugin options, represented as structs with an id and a value field, to be passed to the compiler", + }, +) diff --git a/kotlin/internal/jvm/compile.bzl b/kotlin/internal/jvm/compile.bzl index 76c14f040..698369305 100644 --- a/kotlin/internal/jvm/compile.bzl +++ b/kotlin/internal/jvm/compile.bzl @@ -21,6 +21,11 @@ load( _merge_plugin_infos = "merge_plugin_infos", _plugin_mappers = "mappers", ) +load( + "//kotlin/internal:compiler_plugins.bzl", + _plugins_to_classpaths = "plugins_to_classpaths", + _plugins_to_options = "plugins_to_options", +) load( "//kotlin/internal/utils:utils.bzl", _utils = "utils", @@ -218,8 +223,10 @@ def kt_jvm_compile_action(ctx, rule_kind, output_jar): dirs = _compiler_directories(ctx) srcs = _partitioned_srcs(ctx.files.srcs) friend = _compiler_friends(ctx, friends = getattr(ctx.attr, "friends", [])) - compile_deps = _compiler_deps(toolchains, friend, deps = ctx.attr.deps) - plugins = _plugin_mappers.targets_to_kt_plugins(ctx.attr.plugins + ctx.attr.deps) + compile_deps = _compiler_deps(toolchains, friend, deps = ctx.attr.deps + ctx.attr.plugins) + annotation_processors = _plugin_mappers.targets_to_annotation_processors(ctx.attr.plugins + ctx.attr.deps) + plugins = ctx.attr.plugins + _run_kt_builder_action( ctx = ctx, rule_kind = rule_kind, @@ -228,6 +235,7 @@ def kt_jvm_compile_action(ctx, rule_kind, output_jar): srcs = srcs, friend = friend, compile_deps = compile_deps, + annotation_processors = annotation_processors, plugins = plugins, outputs = { "output": output_jar, @@ -263,7 +271,7 @@ def kt_jvm_compile_action(ctx, rule_kind, output_jar): ), ) -def _run_kt_builder_action(ctx, rule_kind, toolchains, dirs, srcs, friend, compile_deps, plugins, outputs): +def _run_kt_builder_action(ctx, rule_kind, toolchains, dirs, srcs, friend, compile_deps, annotation_processors, plugins, outputs): """Creates a KotlinBuilder action invocation.""" args = _utils.init_args(ctx, rule_kind, friend.module_name) @@ -279,17 +287,28 @@ def _run_kt_builder_action(ctx, rule_kind, toolchains, dirs, srcs, friend, compi # Collect and prepare plugin descriptor for the worker. args.add_all( "--processors", - plugins, + annotation_processors, map_each = _plugin_mappers.kt_plugin_to_processor, omit_if_empty = True, ) args.add_all( "--processorpath", - plugins, + annotation_processors, map_each = _plugin_mappers.kt_plugin_to_processorpath, omit_if_empty = True, ) + args.add_all( + "--pluginpath", + _plugins_to_classpaths(plugins), + omit_if_empty = True, + ) + args.add_all( + "--plugin_options", + _plugins_to_options(plugins), + omit_if_empty = True, + ) + progress_message = "Compiling Kotlin to JVM %s { kt: %d, java: %d, srcjars: %d }" % ( ctx.label, len(srcs.kt), diff --git a/kotlin/internal/jvm/impl.bzl b/kotlin/internal/jvm/impl.bzl index c188812c4..1a19d632f 100644 --- a/kotlin/internal/jvm/impl.bzl +++ b/kotlin/internal/jvm/impl.bzl @@ -17,6 +17,7 @@ load( ) load( "//kotlin/internal:defs.bzl", + _KtCompilerPluginInfo = "KtCompilerPluginInfo", _KtJvmInfo = "KtJvmInfo", ) load( @@ -192,6 +193,7 @@ def kt_jvm_junit_test_impl(ctx): main_class = ctx.attr.main_class, jvm_flags = ["-ea", "-Dbazel.test_suite=%s" % test_class] + ctx.attr.jvm_flags, ) + return _make_providers( ctx, providers, @@ -201,3 +203,20 @@ def kt_jvm_junit_test_impl(ctx): direct = ctx.files._java_runtime, ), ) + +def kt_compiler_plugin_impl(ctx): + merged_deps = java_common.merge([j[JavaInfo] for j in ctx.attr.deps]) + plugin_id = ctx.attr.id + options = [] + for (k, v) in ctx.attr.options.items(): + if "=" in k: + fail("kt_compiler_plugin options keys cannot contain the = symbol") + options.append(struct(id = plugin_id, value = "%s=%s" % (k, v))) + + return [ + merged_deps, + _KtCompilerPluginInfo( + classpath = merged_deps.transitive_runtime_jars.to_list(), + options = options, + ), + ] diff --git a/kotlin/internal/jvm/jvm.bzl b/kotlin/internal/jvm/jvm.bzl index ea95acf0c..e669051ba 100644 --- a/kotlin/internal/jvm/jvm.bzl +++ b/kotlin/internal/jvm/jvm.bzl @@ -93,6 +93,7 @@ kt_jvm_binary( load( "//kotlin/internal:defs.bzl", _KT_COMPILER_REPO = "KT_COMPILER_REPO", + _KtCompilerPluginInfo = "KtCompilerPluginInfo", _KtJvmInfo = "KtJvmInfo", _TOOLCHAIN_TYPE = "TOOLCHAIN_TYPE", ) @@ -102,6 +103,7 @@ load( ) load( "//kotlin/internal/jvm:impl.bzl", + _kt_compiler_plugin_impl = "kt_compiler_plugin_impl", _kt_jvm_binary_impl = "kt_jvm_binary_impl", _kt_jvm_import_impl = "kt_jvm_import_impl", _kt_jvm_junit_test_impl = "kt_jvm_junit_test_impl", @@ -184,6 +186,7 @@ _common_attr = utils.add_dicts( "plugins": attr.label_list( default = [], aspects = [_kt_jvm_plugin_aspect], + providers = [JavaInfo], ), "module_name": attr.string( doc = """The name of the module, if not provided the module name is derived from the label. --e.g., @@ -362,3 +365,52 @@ kt_jvm_import = rule( implementation = _kt_jvm_import_impl, provides = [JavaInfo, _KtJvmInfo], ) + +kt_compiler_plugin = rule( + doc = """Define a plugin for the Kotlin compiler to run. The plugin can then be referenced in the `plugins` attribute + of the `kt_jvm_*` rules. + + An example can be found under `//examples/plugin`: + + ```bzl + kt_compiler_plugin( + name = "open_for_testing_plugin", + id = "org.jetbrains.kotlin.allopen", + options = { + "annotation": "plugin.OpenForTesting", + }, + deps = [ + "@com_github_jetbrains_kotlin//:allopen-compiler-plugin", + ], + ) + + kt_jvm_library( + name = "open_for_testing", + srcs = ["OpenForTesting.kt"], + ) + + kt_jvm_library( + name = "user", + srcs = ["User.kt"], + plugins = [":open_for_testing_plugin"], + deps = [ + ":open_for_testing", + ], + ) + ``` + """, + attrs = { + "deps": attr.label_list( + doc = "The list of libraries to be added to the compiler's plugin classpath", + ), + "id": attr.string( + doc = """The ID of the plugin""", + ), + "options": attr.string_dict( + doc = """Dictionary of options to be passed to the plugin""", + default = {}, + ), + }, + implementation = _kt_compiler_plugin_impl, + provides = [JavaInfo, _KtCompilerPluginInfo], +) diff --git a/kotlin/internal/jvm/plugins.bzl b/kotlin/internal/jvm/plugins.bzl index beaa4fe67..99f883866 100644 --- a/kotlin/internal/jvm/plugins.bzl +++ b/kotlin/internal/jvm/plugins.bzl @@ -33,11 +33,14 @@ def _kt_plugin_to_processor(processor): def _kt_plugin_to_processorpath(processor): return [j.path for j in processor.classpath.to_list()] -def _targets_to_kt_plugins(targets): +def _targets_to_annotation_processors(targets): return depset(transitive = [t[KtJvmPluginInfo].annotation_processors for t in targets if t[KtJvmPluginInfo]]) +def _targets_to_plugins(targets): + return depset(transitive = [t[KtJvmPluginInfo].plugins for t in targets if t[KtJvmPluginInfo]]) + mappers = struct( - targets_to_kt_plugins = _targets_to_kt_plugins, + targets_to_annotation_processors = _targets_to_annotation_processors, kt_plugin_to_processor = _kt_plugin_to_processor, kt_plugin_to_processorpath = _kt_plugin_to_processorpath, ) @@ -47,7 +50,7 @@ def merge_plugin_infos(attrs): Returns: A KtJvmPluginInfo provider, Each of the entries is serializable.""" return KtJvmPluginInfo( - annotation_processors = _targets_to_kt_plugins(attrs), + annotation_processors = _targets_to_annotation_processors(attrs), ) def _kt_jvm_plugin_aspect_impl(target, ctx): diff --git a/kotlin/internal/repositories/BUILD.com_github_jetbrains_kotlin b/kotlin/internal/repositories/BUILD.com_github_jetbrains_kotlin index 31ca05885..b49368f18 100644 --- a/kotlin/internal/repositories/BUILD.com_github_jetbrains_kotlin +++ b/kotlin/internal/repositories/BUILD.com_github_jetbrains_kotlin @@ -42,6 +42,21 @@ kt_jvm_import( ] ] +kt_jvm_import( + name = "allopen-compiler-plugin", + jar = "lib/allopen-compiler-plugin.jar", +) + +kt_jvm_import( + name = "noarg-compiler-plugin", + jar = "lib/noarg-compiler-plugin.jar", +) + +kt_jvm_import( + name = "sam-with-receiver-compiler-plugin", + jar = "lib/sam-with-receiver-compiler-plugin.jar", +) + # Kotlin dependencies that are internal to this repo and may be linked. [ java_import( diff --git a/kotlin/kotlin.bzl b/kotlin/kotlin.bzl index 344bf7652..db7cd0f89 100644 --- a/kotlin/kotlin.bzl +++ b/kotlin/kotlin.bzl @@ -23,6 +23,7 @@ load( ) load( "//kotlin/internal/jvm:jvm.bzl", + _kt_compiler_plugin = "kt_compiler_plugin", _kt_jvm_binary = "kt_jvm_binary", _kt_jvm_import = "kt_jvm_import", _kt_jvm_library = "kt_jvm_library", @@ -48,3 +49,4 @@ kt_jvm_import = _kt_jvm_import kt_jvm_library = _kt_jvm_library kt_jvm_test = _kt_jvm_test kt_android_library = _kt_android_library +kt_compiler_plugin = _kt_compiler_plugin diff --git a/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java b/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java index 5c0018ea4..a5752864e 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java +++ b/src/main/kotlin/io/bazel/kotlin/builder/KotlinBuilderComponent.java @@ -23,7 +23,7 @@ import io.bazel.kotlin.builder.tasks.KotlinBuilder; import io.bazel.kotlin.builder.tasks.js.Kotlin2JsTaskExecutor; import io.bazel.kotlin.builder.tasks.jvm.KotlinJvmTaskExecutor; -import io.bazel.kotlin.builder.toolchain.KotlinCompilerPluginArgsEncoder; +import io.bazel.kotlin.builder.toolchain.KaptCompilerPluginArgsEncoder; import io.bazel.kotlin.builder.toolchain.KotlinToolchain; import javax.inject.Singleton; @@ -51,8 +51,8 @@ public interface Builder { @dagger.Module public class Module { @Provides - public KotlinCompilerPluginArgsEncoder providePluginArgEncoder(KotlinToolchain toolchain) { - return new KotlinCompilerPluginArgsEncoder( + public KaptCompilerPluginArgsEncoder providePluginArgEncoder(KotlinToolchain toolchain) { + return new KaptCompilerPluginArgsEncoder( toolchain.getKapt3Plugin().getJarPath(), toolchain.getKapt3Plugin().getId()); } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt index d2e8ba8a5..dd393b55f 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt @@ -76,6 +76,8 @@ class KotlinBuilder @Inject internal constructor( BOOT_CLASSPATH("--bootclasspath"), PROCESSOR_PATH("--processorpath"), PROCESSORS("--processors"), + PLUGIN_PATH("--pluginpath"), + PLUGIN_OPTION("--plugin_options"), EXT_CLASSPATH("--extclasspath"), EXT_DIR("--extdir"), OUTPUT("--output"), @@ -250,6 +252,9 @@ class KotlinBuilder @Inject internal constructor( addAllProcessors(argMap.optional(JavaBuilderFlags.PROCESSORS) ?: emptyList()) addAllProcessorpaths(argMap.optional(JavaBuilderFlags.PROCESSOR_PATH) ?: emptyList()) + addAllPluginpaths(argMap.optional(JavaBuilderFlags.PLUGIN_PATH) ?: emptyList()) + addAllPluginOptions(argMap.optional(JavaBuilderFlags.PLUGIN_OPTION) ?: emptyList()) + argMap.optional(JavaBuilderFlags.SOURCES)?.iterator()?.partitionJvmSources( { addKotlinSources(it) }, { addJavaSources(it) } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt index 830ab0eca..6821f4af3 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt @@ -17,7 +17,7 @@ package io.bazel.kotlin.builder.tasks.jvm import io.bazel.kotlin.builder.toolchain.CompilationStatusException import io.bazel.kotlin.builder.toolchain.CompilationTaskContext -import io.bazel.kotlin.builder.toolchain.KotlinCompilerPluginArgsEncoder +import io.bazel.kotlin.builder.toolchain.KaptCompilerPluginArgsEncoder import io.bazel.kotlin.builder.toolchain.KotlinToolchain import io.bazel.kotlin.model.JvmCompilationTask import javax.inject.Inject @@ -32,14 +32,14 @@ const val X_FRIENDS_PATH_SEPARATOR = "," @Singleton class KotlinJvmTaskExecutor @Inject internal constructor( private val compiler: KotlinToolchain.KotlincInvoker, - private val pluginArgsEncoder: KotlinCompilerPluginArgsEncoder, + private val pluginArgsEncoderKapt: KaptCompilerPluginArgsEncoder, private val javaCompiler: JavaCompiler, private val jDepsGenerator: JDepsGenerator ) { fun execute(context: CompilationTaskContext, task: JvmCompilationTask) { val preprocessedTask = task .preProcessingSteps(context) - .runAnnotationProcessors(context, pluginArgsEncoder, compiler) + .runPlugins(context, pluginArgsEncoderKapt, compiler) context.execute("compile classes") { preprocessedTask.apply { diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt index 957fc737b..4cceda0dd 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/compilation_task.kt @@ -19,7 +19,7 @@ package io.bazel.kotlin.builder.tasks.jvm import io.bazel.kotlin.builder.toolchain.CompilationTaskContext -import io.bazel.kotlin.builder.toolchain.KotlinCompilerPluginArgsEncoder +import io.bazel.kotlin.builder.toolchain.KaptCompilerPluginArgsEncoder import io.bazel.kotlin.builder.toolchain.KotlinToolchain import io.bazel.kotlin.builder.utils.IS_JVM_SOURCE_FILE import io.bazel.kotlin.builder.utils.bazelRuleKind @@ -52,6 +52,19 @@ internal fun JvmCompilationTask.baseArgs(): CompilationArgs = CompilationArgs() .flag("-jvm-target", info.toolchainInfo.jvm.jvmTarget) .flag("-module-name", info.moduleName) +internal fun pluginArgs(context: JvmCompilationTask, args: CompilationArgs): CompilationArgs = args + .let { + val pluginsPath = context.inputs.pluginpathsList.joinToString(":") + it.value("-Xplugin=${pluginsPath}") + } + .let { + var r = it + context.inputs.pluginOptionsList.forEach { opt -> + r = r.flag("-P", "plugin:$opt") + } + r + } + internal fun JvmCompilationTask.preProcessingSteps(context: CompilationTaskContext): JvmCompilationTask { return context.execute("expand sources") { expandWithSourceJarSources() } } @@ -79,17 +92,17 @@ internal fun JvmCompilationTask.produceSourceJar() { } } -internal fun JvmCompilationTask.runAnnotationProcessors( +internal fun JvmCompilationTask.runPlugins( context: CompilationTaskContext, - pluginArgsEncoder: KotlinCompilerPluginArgsEncoder, + kaptPluginArgsEncoder: KaptCompilerPluginArgsEncoder, compiler: KotlinToolchain.KotlincInvoker ): JvmCompilationTask { if (inputs.processorsList.isEmpty()) { return this } else { return context.execute("kapt (${inputs.processorsList.joinToString(", ")})") { - commonArgs() - .values(pluginArgsEncoder.encode(context, this)) + pluginArgs(this, commonArgs()) + .values(kaptPluginArgsEncoder.encode(context, this)) .values(inputs.kotlinSourcesList) .values(inputs.javaSourcesList).list().let { args -> context.executeCompilerTask( @@ -131,7 +144,7 @@ internal fun JvmCompilationTask.compileKotlin( compiler: KotlinToolchain.KotlincInvoker, printOnFail: Boolean = true ) = - commonArgs() + pluginArgs(this, commonArgs()) .values(inputs.javaSourcesList) .values(inputs.kotlinSourcesList) .list().let { args -> diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinCompilerPluginArgsEncoder.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KaptCompilerPluginArgsEncoder.kt similarity index 98% rename from src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinCompilerPluginArgsEncoder.kt rename to src/main/kotlin/io/bazel/kotlin/builder/toolchain/KaptCompilerPluginArgsEncoder.kt index 770f07ac0..9024c145e 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinCompilerPluginArgsEncoder.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KaptCompilerPluginArgsEncoder.kt @@ -21,7 +21,7 @@ import java.io.ObjectOutputStream import java.util.Base64 // TODO(hs) move the kapt specific stuff to the JVM package. -class KotlinCompilerPluginArgsEncoder( +class KaptCompilerPluginArgsEncoder( private val jarPath: String, private val pluginId: String ) { diff --git a/src/main/protobuf/kotlin_model.proto b/src/main/protobuf/kotlin_model.proto index 0615875ec..171ff1630 100644 --- a/src/main/protobuf/kotlin_model.proto +++ b/src/main/protobuf/kotlin_model.proto @@ -122,6 +122,10 @@ message JvmCompilationTask { repeated string processors = 7; // Annotation processor classpath. repeated string processorpaths = 8; + // Kotlin compiler plugin options + repeated string plugin_options = 9; + // Kotlin compiler plugin classpath + repeated string pluginpaths = 10; } CompilationTaskInfo info = 1; From 5efac99b66d48992cded75646e0b00778cb8b38d Mon Sep 17 00:00:00 2001 From: Benjamin Romano Date: Tue, 7 Apr 2020 12:20:29 -0700 Subject: [PATCH 16/16] Fix non-reproducible archives (#304) Fix non-reproducible archives by creating a fixed GregorianCalendar on a given date (slightly later than Jan 1 1980, since Java 7 and 8 have different special casing there). --- .../io/bazel/kotlin/builder/utils/jars/JarHelper.kt | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarHelper.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarHelper.kt index 8af6836fa..5ab0dd29a 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarHelper.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarHelper.kt @@ -22,8 +22,8 @@ import java.io.FileNotFoundException import java.io.IOException import java.nio.file.Files import java.nio.file.Path -import java.time.LocalDateTime -import java.time.ZoneId +import java.util.Calendar +import java.util.GregorianCalendar import java.util.HashSet import java.util.jar.Attributes import java.util.jar.JarEntry @@ -245,11 +245,10 @@ open class JarHelper internal constructor( const val SERVICES_DIR = "META-INF/services/" internal val EMPTY_BYTEARRAY = ByteArray(0) - /** Normalize timestamps. */ - val DEFAULT_TIMESTAMP = LocalDateTime.of(1980, 1, 1, 0, 0, 0) - .atZone(ZoneId.systemDefault()) - .toInstant() - .toEpochMilli() + // Normalized timestamp for zip entries + // We do not include the system's default timezone and locale and additionally avoid the unix epoch + // to ensure Java's zip implementation does not add the System's timezone into the extra field of the zip entry + val DEFAULT_TIMESTAMP = GregorianCalendar(1980, Calendar.FEBRUARY, 1, 0, 0, 0).getTimeInMillis() // These attributes are used by JavaBuilder, Turbine, and ijar. // They must all be kept in sync.