Support Starlark rules_android (#1333)
* Support Starlark rules_android
* Revert
* Formatting
* Add missing _lcov_merger attr
* More clean up
* More clean up and fixes
* More cleanup
* More cleanup
* More cleanup
* More cleanup and fixes
* More
* Fixes
* More fixes
* More fixes
* Fixes
diff --git a/examples/android/MODULE.bazel b/examples/android/MODULE.bazel
index b024c23..91f7dc8 100644
--- a/examples/android/MODULE.bazel
+++ b/examples/android/MODULE.bazel
@@ -7,6 +7,11 @@
bazel_dep(name = "rules_kotlin", version = "1.9.5")
bazel_dep(name = "rules_jvm_external", version = "6.6")
+android_sdk_repository_extension = use_extension("@rules_android//rules/android_sdk_repository:rule.bzl", "android_sdk_repository_extension")
+use_repo(android_sdk_repository_extension, "androidsdk")
+
+register_toolchains("@androidsdk//:sdk-toolchain", "@androidsdk//:all")
+
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
maven.install(
name = "maven_rules_kotlin_example",
diff --git a/examples/android/libKtAndroid/src/test/java/examples/android/lib/BUILD.bazel b/examples/android/libKtAndroid/src/test/java/examples/android/lib/BUILD.bazel
index b4d9843..c26317f 100644
--- a/examples/android/libKtAndroid/src/test/java/examples/android/lib/BUILD.bazel
+++ b/examples/android/libKtAndroid/src/test/java/examples/android/lib/BUILD.bazel
@@ -3,7 +3,7 @@
kt_android_local_test(
name = "SomeTest",
srcs = ["SomeTest.kt"],
- associates = ["//libKtAndroid:my_kt_kt"],
+ associates = ["//libKtAndroid:my_kt"],
custom_package = "examples.android.lib",
jvm_flags = [
"-Djava.security.manager=allow",
diff --git a/kotlin/android.bzl b/kotlin/android.bzl
index 6095ad6..f9c2443 100644
--- a/kotlin/android.bzl
+++ b/kotlin/android.bzl
@@ -1,6 +1,9 @@
load(
- "//kotlin/internal/jvm:android.bzl",
+ "//kotlin/internal/jvm:kt_android_library.bzl",
_kt_android_library = "kt_android_library",
+)
+load(
+ "//kotlin/internal/jvm:kt_android_local_test.bzl",
_kt_android_local_test = "kt_android_local_test",
)
diff --git a/kotlin/internal/jvm/android.bzl b/kotlin/internal/jvm/android.bzl
index 53eafe4..80a7d15 100644
--- a/kotlin/internal/jvm/android.bzl
+++ b/kotlin/internal/jvm/android.bzl
@@ -11,123 +11,8 @@
# 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_android//android:rules.bzl",
- _android_library = "android_library",
- _android_local_test = "android_local_test",
-)
-load(
- "//kotlin/internal/jvm:jvm.bzl",
- _kt_jvm_library = "kt_jvm_library",
-)
+load(":kt_android_library.bzl", _kt_android_library = "kt_android_library")
+load(":kt_android_local_test_impl.bzl", _kt_android_local_test = "kt_android_local_test")
-_ANDROID_SDK_JAR = "%s" % Label("//third_party:android_sdk")
-
-def _kt_android_artifact(
- name,
- srcs = [],
- deps = [],
- resources = [],
- plugins = [],
- associates = [],
- module_name = "",
- kotlinc_opts = None,
- javac_opts = None,
- enable_data_binding = False,
- tags = [],
- exec_properties = None,
- **kwargs):
- """Delegates Android related build attributes to the native rules but uses the Kotlin builder to compile Java and
- Kotlin srcs. Returns a sequence of labels that a wrapping macro should export.
- """
- base_name = name + "_base"
- kt_name = name + "_kt"
-
- # TODO(bazelbuild/rules_kotlin/issues/273): This should be retrieved from a provider.
- base_deps = [_ANDROID_SDK_JAR] + deps
-
- _android_library(
- name = base_name,
- visibility = ["//visibility:private"],
- exports = base_deps,
- deps = deps if enable_data_binding else [],
- enable_data_binding = enable_data_binding,
- tags = tags,
- exec_properties = exec_properties,
- **kwargs
- )
- _kt_jvm_library(
- name = kt_name,
- srcs = srcs,
- deps = [base_name] + base_deps,
- resources = resources,
- plugins = plugins,
- associates = associates,
- module_name = module_name,
- testonly = kwargs.get("testonly", default = False),
- visibility = ["//visibility:public"],
- kotlinc_opts = kotlinc_opts,
- javac_opts = javac_opts,
- tags = tags,
- exec_properties = exec_properties,
- )
- return [base_name, kt_name]
-
-def kt_android_library(name, exports = [], visibility = None, exec_properties = None, **kwargs):
- """Creates an Android sandwich library.
-
- `srcs`, `deps`, `plugins` are routed to `kt_jvm_library` the other android
- related attributes are handled by the native `android_library` rule.
- """
-
- _android_library(
- name = name,
- exports = exports + _kt_android_artifact(name, exec_properties = exec_properties, **kwargs),
- visibility = visibility,
- tags = kwargs.get("tags", default = None),
- testonly = kwargs.get("testonly", default = 0),
- exec_properties = exec_properties,
- )
-
-def kt_android_local_test(
- name,
- jvm_flags = None,
- manifest = None,
- manifest_values = None,
- test_class = None,
- size = None,
- data = None,
- timeout = None,
- flaky = False,
- shard_count = None,
- visibility = None,
- testonly = True,
- exec_properties = None,
- nocompress_extensions = None,
- **kwargs):
- """Creates a testable Android sandwich library.
-
- `srcs`, `deps`, `plugins`, `associates` are routed to `kt_jvm_library` the other android
- related attributes are handled by the native `android_library` rule while the test attributes
- are picked out and handled by the `android_local_test` rule.
- """
-
- _android_local_test(
- name = name,
- deps = kwargs.get("deps", []) + _kt_android_artifact(name = name, testonly = testonly, exec_properties = exec_properties, **kwargs),
- jvm_flags = jvm_flags,
- test_class = test_class,
- visibility = visibility,
- size = size,
- data = data,
- timeout = timeout,
- flaky = flaky,
- shard_count = shard_count,
- custom_package = kwargs.get("custom_package", default = None),
- manifest = manifest,
- manifest_values = manifest_values,
- tags = kwargs.get("tags", default = None),
- testonly = testonly,
- exec_properties = exec_properties,
- nocompress_extensions = nocompress_extensions,
- )
+kt_android_library = _kt_android_library
+kt_android_local_test = _kt_android_local_test
diff --git a/kotlin/internal/jvm/compile.bzl b/kotlin/internal/jvm/compile.bzl
index b501bbc..2015e3a 100644
--- a/kotlin/internal/jvm/compile.bzl
+++ b/kotlin/internal/jvm/compile.bzl
@@ -272,7 +272,7 @@
toolchain = _TOOLCHAIN_TYPE,
)
-def _resourcejar_args_action(ctx):
+def _resourcejar_args_action(ctx, extra_resources = {}):
res_cmd = []
for f in ctx.files.resources:
target_path = _adjust_resources_path(f.short_path, ctx.attr.resource_strip_prefix)
@@ -283,20 +283,31 @@
f_path = f.path,
)
res_cmd.extend([line])
+
+ for key, value in extra_resources.items():
+ target_path = _adjust_resources_path(value.short_path, ctx.label.package)
+ if target_path[0] == "/":
+ target_path = target_path[1:]
+ line = "{target_path}={res_path}\n".format(
+ res_path = value.path,
+ target_path = key,
+ )
+ res_cmd.extend([line])
+
zipper_args_file = ctx.actions.declare_file("%s_resources_zipper_args" % ctx.label.name)
ctx.actions.write(zipper_args_file, "".join(res_cmd))
return zipper_args_file
-def _build_resourcejar_action(ctx):
+def _build_resourcejar_action(ctx, extra_resources = {}):
"""sets up an action to build a resource jar for the target being compiled.
Returns:
The file resource jar file.
"""
resources_jar_output = ctx.actions.declare_file(ctx.label.name + "-resources.jar")
- zipper_args = _resourcejar_args_action(ctx)
+ zipper_args = _resourcejar_args_action(ctx, extra_resources)
ctx.actions.run_shell(
mnemonic = "KotlinZipResourceJar",
- inputs = ctx.files.resources + [zipper_args],
+ inputs = ctx.files.resources + extra_resources.values() + [zipper_args],
tools = [ctx.executable._zipper],
outputs = [resources_jar_output],
command = "{zipper} c {resources_jar_output} @{path}".format(
@@ -570,27 +581,57 @@
# MAIN ACTIONS #########################################################################################################
-def kt_jvm_produce_jar_actions(ctx, rule_kind):
+def _kt_jvm_produce_jar_actions(ctx, rule_kind, extra_resources = {}):
+ """Setup The actions to compile a jar and if any resources or resource_jars were provided to merge these in with the
+ compilation output.
+
+ Returns:
+ see `kt_jvm_compile_action`.
+ """
+ deps = getattr(ctx.attr, "deps", [])
+ associates = getattr(ctx.attr, "associates", [])
+ _fail_if_invalid_associate_deps(associates, deps)
+ compile_deps = _jvm_deps_utils.jvm_deps(
+ ctx,
+ toolchains = _compiler_toolchains(ctx),
+ associate_deps = associates,
+ deps = deps,
+ exports = getattr(ctx.attr, "exports", []),
+ runtime_deps = getattr(ctx.attr, "runtime_deps", []),
+ )
+
+ outputs = struct(
+ jar = ctx.outputs.jar,
+ srcjar = ctx.outputs.srcjar,
+ )
+
+ # Setup the compile action.
+ return _kt_jvm_produce_output_jar_actions(
+ ctx,
+ rule_kind = rule_kind,
+ compile_deps = compile_deps,
+ outputs = outputs,
+ extra_resources = extra_resources,
+ )
+
+def _kt_jvm_produce_output_jar_actions(
+ ctx,
+ rule_kind,
+ compile_deps,
+ outputs,
+ extra_resources = {}):
"""This macro sets up a compile action for a Kotlin jar.
Args:
ctx: Invoking rule ctx, used for attr, actions, and label.
rule_kind: The rule kind --e.g., `kt_jvm_library`.
+ compile_deps: The rule kind --e.g., `kt_jvm_library`.
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)
srcs = _partitioned_srcs(ctx.files.srcs)
- _fail_if_invalid_associate_deps(ctx.attr.associates, ctx.attr.deps)
- compile_deps = _jvm_deps_utils.jvm_deps(
- ctx,
- toolchains = toolchains,
- associate_deps = ctx.attr.associates,
- deps = ctx.attr.deps,
- exports = getattr(ctx.attr, "exports", []),
- runtime_deps = getattr(ctx.attr, "runtime_deps", []),
- )
annotation_processors = _plugin_mappers.targets_to_annotation_processors(ctx.attr.plugins + ctx.attr.deps)
ksp_annotation_processors = _plugin_mappers.targets_to_ksp_annotation_processors(ctx.attr.plugins + ctx.attr.deps)
@@ -627,12 +668,12 @@
annotation_processing = outputs_struct.annotation_processing
# If this rule has any resources declared setup a zipper action to turn them into a jar.
- if len(ctx.files.resources) > 0:
- output_jars.append(_build_resourcejar_action(ctx))
+ if len(ctx.files.resources) + len(extra_resources) > 0:
+ output_jars.append(_build_resourcejar_action(ctx, extra_resources))
output_jars.extend(ctx.files.resource_jars)
# Merge outputs into final runtime jar.
- output_jar = ctx.actions.declare_file(ctx.label.name + ".jar")
+ output_jar = outputs.jar
_fold_jars_action(
ctx,
rule_kind = rule_kind,
@@ -644,7 +685,7 @@
source_jar = java_common.pack_sources(
ctx.actions,
- output_source_jar = ctx.outputs.srcjar,
+ output_source_jar = outputs.srcjar,
sources = srcs.kt + srcs.java,
source_jars = srcs.src_jars + generated_src_jars,
java_toolchain = toolchains.java,
@@ -928,7 +969,7 @@
)
return None
-def export_only_providers(ctx, actions, attr, outputs):
+def _export_only_providers(ctx, actions, attr, outputs):
"""_export_only_providers creates a series of forwarding providers without compilation overhead.
Args:
@@ -936,6 +977,7 @@
actions: invoking rule actions,
attr: kt_compiler_attributes,
outputs: kt_compiler_outputs
+
Returns:
kt_compiler_result
"""
@@ -987,3 +1029,11 @@
extensions = ["kt", "java"],
),
)
+
+compile = struct(
+ compiler_toolchains = _compiler_toolchains,
+ verify_associates_not_duplicated_in_deps = _fail_if_invalid_associate_deps,
+ export_only_providers = _export_only_providers,
+ kt_jvm_produce_output_jar_actions = _kt_jvm_produce_output_jar_actions,
+ kt_jvm_produce_jar_actions = _kt_jvm_produce_jar_actions,
+)
diff --git a/kotlin/internal/jvm/impl.bzl b/kotlin/internal/jvm/impl.bzl
index cb3ba18..2136946 100644
--- a/kotlin/internal/jvm/impl.bzl
+++ b/kotlin/internal/jvm/impl.bzl
@@ -24,8 +24,7 @@
)
load(
"//kotlin/internal/jvm:compile.bzl",
- "export_only_providers",
- _kt_jvm_produce_jar_actions = "kt_jvm_produce_jar_actions",
+ _compile = "compile",
)
load(
"//kotlin/internal/utils:utils.bzl",
@@ -41,6 +40,7 @@
files = [ctx.outputs.jar]
if providers.java.outputs.jdeps:
files.append(providers.java.outputs.jdeps)
+
return [
providers.java,
providers.kt,
@@ -224,7 +224,7 @@
)
return _make_providers(
ctx,
- _kt_jvm_produce_jar_actions(ctx, "kt_jvm_library") if ctx.attr.srcs or ctx.attr.resources else export_only_providers(
+ _compile.kt_jvm_produce_jar_actions(ctx, "kt_jvm_library") if ctx.attr.srcs or ctx.attr.resources else _compile.export_only_providers(
ctx = ctx,
actions = ctx.actions,
outputs = ctx.outputs,
@@ -234,7 +234,7 @@
)
def kt_jvm_binary_impl(ctx):
- providers = _kt_jvm_produce_jar_actions(ctx, "kt_jvm_binary")
+ providers = _compile.kt_jvm_produce_jar_actions(ctx, "kt_jvm_binary")
jvm_flags = []
if hasattr(ctx.fragments.java, "default_jvm_opts"):
jvm_flags = ctx.fragments.java.default_jvm_opts
@@ -269,7 +269,7 @@
]
def kt_jvm_junit_test_impl(ctx):
- providers = _kt_jvm_produce_jar_actions(ctx, "kt_jvm_test")
+ providers = _compile.kt_jvm_produce_jar_actions(ctx, "kt_jvm_test")
runtime_jars = depset(ctx.files._bazel_test_runner, transitive = [providers.java.transitive_runtime_jars])
coverage_runfiles = []
diff --git a/kotlin/internal/jvm/jvm.bzl b/kotlin/internal/jvm/jvm.bzl
index d4a2c15..7ffeb7f 100644
--- a/kotlin/internal/jvm/jvm.bzl
+++ b/kotlin/internal/jvm/jvm.bzl
@@ -249,6 +249,7 @@
providers = [_JavacOptions],
mandatory = False,
),
+ "_use_auto_exec_groups": attr.bool(default = False),
},
)
@@ -659,3 +660,8 @@
),
},
)
+
+attrs = struct(
+ lib_common_attr = _lib_common_attr,
+ runnable_common_attr = _runnable_common_attr,
+)
diff --git a/kotlin/internal/jvm/jvm_deps.bzl b/kotlin/internal/jvm/jvm_deps.bzl
index 6e2957a..9c5637f 100644
--- a/kotlin/internal/jvm/jvm_deps.bzl
+++ b/kotlin/internal/jvm/jvm_deps.bzl
@@ -21,9 +21,9 @@
def _java_info(target):
return target[JavaInfo] if JavaInfo in target else None
-def _jvm_deps(ctx, toolchains, associate_deps, deps, exports = [], runtime_deps = []):
+def _jvm_deps(ctx, toolchains, associate_deps, deps = [], deps_java_infos = [], exports = [], runtime_deps = []):
"""Encapsulates jvm dependency metadata."""
- dep_infos = [_java_info(d) for d in deps] + [toolchains.kt.jvm_stdlibs]
+ dep_infos = deps_java_infos + [_java_info(d) for d in deps] + [toolchains.kt.jvm_stdlibs]
associates = _associate_utils.get_associates(ctx, toolchains = toolchains, associates = associate_deps)
diff --git a/kotlin/internal/jvm/kt_android_library.bzl b/kotlin/internal/jvm/kt_android_library.bzl
new file mode 100644
index 0000000..5f112c2
--- /dev/null
+++ b/kotlin/internal/jvm/kt_android_library.bzl
@@ -0,0 +1,53 @@
+# 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(
+ "@rules_android//rules/android_library:attrs.bzl",
+ _BASE_ATTRS = "ATTRS",
+)
+load(
+ "@rules_android//rules/android_library:rule.bzl",
+ _make_rule = "make_rule",
+)
+load(
+ "//kotlin/internal:defs.bzl",
+ _KtJvmInfo = "KtJvmInfo",
+ _TOOLCHAIN_TYPE = "TOOLCHAIN_TYPE",
+)
+load(
+ "//kotlin/internal/jvm:jvm.bzl",
+ _attrs = "attrs",
+)
+load(
+ "//kotlin/internal/jvm:kt_android_library_impl.bzl",
+ _kt_android_library_impl = "kt_android_library_impl",
+)
+load(
+ "//kotlin/internal/utils:utils.bzl",
+ _utils = "utils",
+)
+
+_ATTRS = _utils.add_dicts(_BASE_ATTRS, _attrs.lib_common_attr, {
+ # Pass or override any attributes needed here
+})
+
+kt_android_library = _make_rule(
+ implementation = _kt_android_library_impl,
+ attrs = _ATTRS,
+ additional_toolchains = [
+ _TOOLCHAIN_TYPE,
+ ],
+ additional_providers = [
+ _KtJvmInfo,
+ ],
+)
diff --git a/kotlin/internal/jvm/kt_android_library_impl.bzl b/kotlin/internal/jvm/kt_android_library_impl.bzl
new file mode 100644
index 0000000..3a22b85
--- /dev/null
+++ b/kotlin/internal/jvm/kt_android_library_impl.bzl
@@ -0,0 +1,155 @@
+# 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(
+ "@rules_android//providers:providers.bzl",
+ _AndroidLibraryResourceClassJarProvider = "AndroidLibraryResourceClassJarProvider",
+)
+load(
+ "@rules_android//rules:java.bzl",
+ _java = "java",
+)
+load(
+ "@rules_android//rules:processing_pipeline.bzl",
+ _ProviderInfo = "ProviderInfo",
+ _processing_pipeline = "processing_pipeline",
+)
+load(
+ "@rules_android//rules:utils.bzl",
+ _get_android_sdk = "get_android_sdk",
+ _utils = "utils",
+)
+load(
+ "@rules_android//rules/android_library:impl.bzl",
+ _BASE_PROCESSORS = "PROCESSORS",
+ _finalize = "finalize",
+)
+load(
+ "@rules_java//java:defs.bzl",
+ "JavaInfo",
+)
+load(
+ "//kotlin/internal/jvm:compile.bzl",
+ _compile = "compile",
+)
+load(
+ "//kotlin/internal/jvm:jvm_deps.bzl",
+ _jvm_deps_utils = "jvm_deps_utils",
+)
+
+def _process_jvm(ctx, resources_ctx, **_unused_sub_ctxs):
+ """Custom JvmProcessor that handles Kotlin compilation
+ """
+ r_java = resources_ctx.r_java
+ outputs = struct(jar = ctx.outputs.lib_jar, srcjar = ctx.outputs.lib_src_jar, deploy_jar = None)
+ providers = _kt_android_produce_jar_actions(ctx, "kt_android_library", outputs, r_java)
+
+ return _ProviderInfo(
+ name = "jvm_ctx",
+ value = struct(
+ java_info = providers.java,
+ kt_info = providers.kt,
+ providers = [
+ providers.kt,
+ providers.java,
+ ],
+ ),
+ )
+
+PROCESSORS = _processing_pipeline.replace(
+ _BASE_PROCESSORS,
+ JvmProcessor = _process_jvm,
+)
+
+_PROCESSING_PIPELINE = _processing_pipeline.make_processing_pipeline(
+ processors = PROCESSORS,
+ finalize = _finalize,
+)
+
+def kt_android_library_impl(ctx):
+ """The rule implementation.
+
+ Args:
+ ctx: The context.
+
+ Returns:
+ A list of providers.
+ """
+ java_package = _java.resolve_package_from_label(ctx.label, ctx.attr.custom_package)
+ return _processing_pipeline.run(ctx, java_package, _PROCESSING_PIPELINE)
+
+def _get_android_resource_class_jars(targets):
+ android_compile_dependencies = []
+
+ # Collect R.class jar files from direct dependencies
+ for d in targets:
+ if _AndroidLibraryResourceClassJarProvider in d:
+ jars = d[_AndroidLibraryResourceClassJarProvider].jars
+ if jars:
+ android_compile_dependencies.extend([
+ JavaInfo(output_jar = jar, compile_jar = jar, neverlink = True)
+ for jar in _utils.list_or_depset_to_list(jars)
+ ])
+
+ return android_compile_dependencies
+
+def _kt_android_produce_jar_actions(
+ ctx,
+ rule_kind,
+ outputs,
+ rClass = None,
+ extra_resources = {}):
+ """Setup The actions to compile a jar and if any resources or resource_jars were provided to merge these in with the
+ compilation output.
+ """
+ deps = getattr(ctx.attr, "deps", [])
+ associates = getattr(ctx.attr, "associates", [])
+ exports = getattr(ctx.attr, "exports", [])
+ runtime_deps = getattr(ctx.attr, "runtime_deps", [])
+ _compile.verify_associates_not_duplicated_in_deps(deps = deps, associate_deps = associates)
+
+ # Collect the android compile dependencies
+ android_java_infos = [
+ JavaInfo(
+ output_jar = _get_android_sdk(ctx).android_jar,
+ compile_jar = _get_android_sdk(ctx).android_jar,
+ neverlink = True,
+ ),
+ ]
+ if rClass:
+ android_java_infos.append(rClass)
+ android_java_infos.extend(_get_android_resource_class_jars(deps + associates + runtime_deps))
+
+ compile_deps = _jvm_deps_utils.jvm_deps(
+ ctx,
+ toolchains = _compile.compiler_toolchains(ctx),
+ associate_deps = associates,
+ deps = deps,
+ deps_java_infos = android_java_infos,
+ exports = exports,
+ runtime_deps = runtime_deps,
+ )
+
+ # Setup the compile action.
+ return _compile.kt_jvm_produce_output_jar_actions(
+ ctx,
+ rule_kind = rule_kind,
+ compile_deps = compile_deps,
+ outputs = outputs,
+ extra_resources = extra_resources,
+ ) if ctx.attr.srcs else _compile.compile.export_only_providers(
+ ctx = ctx,
+ actions = ctx.actions,
+ outputs = outputs,
+ attr = ctx.attr,
+ )
diff --git a/kotlin/internal/jvm/kt_android_local_test.bzl b/kotlin/internal/jvm/kt_android_local_test.bzl
new file mode 100644
index 0000000..0bdaf5a
--- /dev/null
+++ b/kotlin/internal/jvm/kt_android_local_test.bzl
@@ -0,0 +1,63 @@
+# 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(
+ "@rules_android//rules/android_local_test:attrs.bzl",
+ _BASE_ATTRS = "ATTRS",
+)
+load(
+ "@rules_android//rules/android_local_test:rule.bzl",
+ _make_rule = "make_rule",
+)
+load(
+ "//kotlin/internal:defs.bzl",
+ _JAVA_RUNTIME_TOOLCHAIN_TYPE = "JAVA_RUNTIME_TOOLCHAIN_TYPE",
+ _TOOLCHAIN_TYPE = "TOOLCHAIN_TYPE",
+)
+load(
+ "//kotlin/internal/jvm:jvm.bzl",
+ _attrs = "attrs",
+)
+load(
+ "//kotlin/internal/jvm:kt_android_local_test_impl.bzl",
+ _kt_android_local_test_impl = "kt_android_local_test_impl",
+)
+load(
+ "//kotlin/internal/utils:utils.bzl",
+ _utils = "utils",
+)
+
+_ATTRS = _utils.add_dicts(_BASE_ATTRS, _attrs.runnable_common_attr, {
+ "main_class": attr.string(
+ default = "com.google.testing.junit.runner.BazelTestRunner",
+ ),
+ "jacocorunner": attr.label(
+ default = Label("@bazel_tools//tools/jdk:JacocoCoverage"),
+ ),
+ "_lcov_merger": attr.label(
+ cfg = "exec",
+ default = configuration_field(
+ fragment = "coverage",
+ name = "output_generator",
+ ),
+ ),
+})
+
+kt_android_local_test = _make_rule(
+ implementation = _kt_android_local_test_impl,
+ attrs = _ATTRS,
+ additional_toolchains = [
+ _TOOLCHAIN_TYPE,
+ _JAVA_RUNTIME_TOOLCHAIN_TYPE,
+ ],
+)
diff --git a/kotlin/internal/jvm/kt_android_local_test_impl.bzl b/kotlin/internal/jvm/kt_android_local_test_impl.bzl
new file mode 100644
index 0000000..46d163c
--- /dev/null
+++ b/kotlin/internal/jvm/kt_android_local_test_impl.bzl
@@ -0,0 +1,214 @@
+# 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(
+ "@bazel_skylib//rules:common_settings.bzl",
+ _BuildSettingInfo = "BuildSettingInfo",
+)
+load(
+ "@rules_android//providers:providers.bzl",
+ _AndroidFilteredJdepsInfo = "AndroidFilteredJdepsInfo",
+)
+load(
+ "@rules_android//rules:attrs.bzl",
+ _attrs = "attrs",
+)
+load(
+ "@rules_android//rules:java.bzl",
+ _java = "java",
+)
+load(
+ "@rules_android//rules:processing_pipeline.bzl",
+ _ProviderInfo = "ProviderInfo",
+ _processing_pipeline = "processing_pipeline",
+)
+load(
+ "@rules_android//rules:resources.bzl",
+ _resources = "resources",
+)
+load(
+ "@rules_android//rules:utils.bzl",
+ _compilation_mode = "compilation_mode",
+ _get_android_sdk = "get_android_sdk",
+ _get_android_toolchain = "get_android_toolchain",
+ _utils = "utils",
+)
+load(
+ "@rules_android//rules/android_local_test:impl.bzl",
+ _BASE_PROCESSORS = "PROCESSORS",
+ _filter_jdeps = "filter_jdeps",
+ _finalize = "finalize",
+)
+load(
+ "@rules_java//java:defs.bzl",
+ "JavaInfo",
+ "java_common",
+)
+load(
+ "//kotlin/internal:defs.bzl",
+ _JAVA_RUNTIME_TOOLCHAIN_TYPE = "JAVA_RUNTIME_TOOLCHAIN_TYPE",
+ _TOOLCHAIN_TYPE = "TOOLCHAIN_TYPE",
+)
+load(
+ "//kotlin/internal/jvm:compile.bzl",
+ _compile = "compile",
+)
+load(
+ "//kotlin/internal/jvm:jvm_deps.bzl",
+ _jvm_deps_utils = "jvm_deps_utils",
+)
+
+_JACOCOCO_CLASS = "com.google.testing.coverage.JacocoCoverageRunner"
+
+def _process_resources(ctx, java_package, manifest_ctx, **_unused_sub_ctxs):
+ # Note: This needs to be kept in sync with.
+ # The main difference between this and the upstream macro is that both ctx.attr.associates and ctx.attr.deps needs to
+ # be passed to `_resources.package(` in order for ALL of the resource references to get merged into a single R
+ # class file.
+ # https://github.com/bazelbuild/rules_android/blob/e98ee9eb79c9398a9866d073a43ecd5e97aaf896/rules/android_local_test/impl.bzl#L94-L122
+ resources_ctx = _resources.package(
+ ctx,
+ # This entire section is being overridden so that we can pass the associates into the deps section.
+ # Without this tests won't be able to reference resources of the associate targets
+ deps = ctx.attr.associates + ctx.attr.deps,
+ manifest = manifest_ctx.processed_manifest,
+ manifest_values = manifest_ctx.processed_manifest_values,
+ manifest_merge_order = ctx.attr._manifest_merge_order[_BuildSettingInfo].value,
+ resource_files = ctx.files.resource_files,
+ assets = ctx.files.assets,
+ assets_dir = ctx.attr.assets_dir,
+ resource_configs = ctx.attr.resource_configuration_filters,
+ densities = ctx.attr.densities,
+ nocompress_extensions = ctx.attr.nocompress_extensions,
+ compilation_mode = _compilation_mode.get(ctx),
+ java_package = java_package,
+ shrink_resources = _attrs.tristate.no,
+ build_java_with_final_resources = True,
+ aapt = _get_android_toolchain(ctx).aapt2.files_to_run,
+ android_jar = _get_android_sdk(ctx).android_jar,
+ busybox = _get_android_toolchain(ctx).android_resources_busybox.files_to_run,
+ host_javabase = ctx.attr._host_javabase,
+ # TODO(b/140582167): Throwing on resource conflict need to be rolled
+ # out to android_local_test.
+ should_throw_on_conflict = False,
+ )
+
+ return _ProviderInfo(
+ name = "resources_ctx",
+ value = resources_ctx,
+ )
+
+def _process_jvm(ctx, resources_ctx, **_unused_sub_ctxs):
+ """Custom JvmProcessor that handles Kotlin compilation
+ """
+ _compile.verify_associates_not_duplicated_in_deps(deps = getattr(ctx.attr, "deps", []), associate_deps = getattr(ctx.attr, "associates", []))
+
+ outputs = struct(jar = ctx.outputs.jar, srcjar = ctx.actions.declare_file(ctx.label.name + "-src.jar"))
+
+ deps = (
+ [_get_android_toolchain(ctx).testsupport] +
+ getattr(ctx.attr, "associates", []) +
+ getattr(ctx.attr, "deps", [])
+ )
+
+ if ctx.configuration.coverage_enabled:
+ deps.append(ctx.toolchains[_TOOLCHAIN_TYPE].jacocorunner)
+ java_start_class = _JACOCOCO_CLASS
+ coverage_start_class = ctx.attr.main_class
+ else:
+ java_start_class = ctx.attr.main_class
+ coverage_start_class = None
+
+ # Setup the compile action.
+ providers = _compile.kt_jvm_produce_output_jar_actions(
+ ctx,
+ rule_kind = "kt_android_local_test",
+ compile_deps = _jvm_deps_utils.jvm_deps(
+ ctx,
+ toolchains = _compile.compiler_toolchains(ctx),
+ deps = deps,
+ deps_java_infos = (
+ ([resources_ctx.r_java] if resources_ctx.r_java else []) +
+ [
+ JavaInfo(
+ output_jar = _get_android_sdk(ctx).android_jar,
+ compile_jar = _get_android_sdk(ctx).android_jar,
+ # The android_jar must not be compiled into the test, it
+ # will bloat the Jar with no benefit.
+ neverlink = True,
+ ),
+ ]
+ ),
+ associate_deps = getattr(ctx.attr, "associates", []),
+ runtime_deps = getattr(ctx.attr, "runtime_deps", []),
+ ),
+ outputs = outputs,
+ )
+
+ java_info = providers.java
+ if getattr(java_common, "add_constraints", None):
+ java_info = java_common.add_constraints(java_info, constraints = ["android"])
+
+ # Create test run action
+ providers = [providers.kt, java_info]
+ runfiles = []
+
+ # Create a filtered jdeps with no resources jar. See b/129011477 for more context.
+ if java_info.outputs.jdeps != None:
+ filtered_jdeps = ctx.actions.declare_file(ctx.label.name + ".filtered.jdeps")
+ _filter_jdeps(ctx, java_info.outputs.jdeps, filtered_jdeps, _utils.only(resources_ctx.r_java.compile_jars.to_list()))
+ providers.append(_AndroidFilteredJdepsInfo(jdeps = filtered_jdeps))
+ runfiles.append(filtered_jdeps)
+
+ # Append the security manager override
+ jvm_flags = []
+ java_runtime = ctx.toolchains[_JAVA_RUNTIME_TOOLCHAIN_TYPE].java_runtime
+ if java_runtime.version >= 17:
+ jvm_flags.append("-Djava.security.manager=allow")
+
+ return _ProviderInfo(
+ name = "jvm_ctx",
+ value = struct(
+ java_info = java_info,
+ providers = providers,
+ deps = deps,
+ java_start_class = java_start_class,
+ coverage_start_class = coverage_start_class,
+ android_properties_file = ctx.file.robolectric_properties_file.short_path,
+ additional_jvm_flags = jvm_flags,
+ ),
+ runfiles = ctx.runfiles(files = runfiles),
+ )
+
+PROCESSORS = _processing_pipeline.replace(
+ _BASE_PROCESSORS,
+ ResourceProcessor = _process_resources,
+ JvmProcessor = _process_jvm,
+)
+
+_PROCESSING_PIPELINE = _processing_pipeline.make_processing_pipeline(
+ processors = PROCESSORS,
+ finalize = _finalize,
+)
+
+def kt_android_local_test_impl(ctx):
+ """The rule implementation.
+
+ Args:
+ ctx: The context.
+
+ Returns:
+ A list of providers.
+ """
+ java_package = _java.resolve_package_from_label(ctx.label, ctx.attr.custom_package)
+ return _processing_pipeline.run(ctx, java_package, _PROCESSING_PIPELINE)
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 e8bb033..305172b 100644
--- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt
+++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt
@@ -101,7 +101,9 @@
try {
@Suppress("WHEN_ENUM_CAN_BE_NULL_IN_JAVA")
when (compileContext.info.platform) {
- Platform.JVM -> executeJvmTask(compileContext, taskContext.directory, argMap)
+ Platform.JVM,
+ Platform.ANDROID,
+ -> executeJvmTask(compileContext, taskContext.directory, argMap)
Platform.UNRECOGNIZED -> throw IllegalStateException(
"unrecognized platform: ${compileContext.info}",
)
@@ -140,16 +142,11 @@
addAllDebug(argMap.mandatory(KotlinBuilderFlags.DEBUG))
label = argMap.mandatorySingle(KotlinBuilderFlags.TARGET_LABEL)
- argMap.mandatorySingle(KotlinBuilderFlags.RULE_KIND).split("_").also {
- check(it.size == 3 && it[0] == "kt") { "invalid rule kind $it" }
- platform =
- checkNotNull(Platform.valueOf(it[1].uppercase())) {
- "unrecognized platform ${it[1]}"
- }
- ruleKind =
- checkNotNull(RuleKind.valueOf(it[2].uppercase())) {
- "unrecognized rule kind ${it[2]}"
- }
+ argMap.mandatorySingle(KotlinBuilderFlags.RULE_KIND).also {
+ val splitRuleKind = it.split("_")
+ require(splitRuleKind[0] == "kt") { "Invalid rule kind $it" }
+ platform = Platform.valueOf(splitRuleKind[1].uppercase())
+ ruleKind = RuleKind.valueOf(splitRuleKind.last().uppercase())
}
moduleName =
argMap.mandatorySingle(KotlinBuilderFlags.MODULE_NAME).also {
diff --git a/src/main/protobuf/kotlin_model.proto b/src/main/protobuf/kotlin_model.proto
index 60399bf..183c573 100644
--- a/src/main/protobuf/kotlin_model.proto
+++ b/src/main/protobuf/kotlin_model.proto
@@ -54,6 +54,7 @@
enum Platform {
JVM = 0;
+ ANDROID = 1;
}
// Common info about a Kotlin compilation task, this message is shared by all compilation tasks.
diff --git a/third_party/BUILD b/third_party/BUILD
index 53b1494..6517349 100644
--- a/third_party/BUILD
+++ b/third_party/BUILD
@@ -1,5 +1,5 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
-load("@rules_java//java:defs.bzl", "java_binary", "java_import", "java_library", "java_plugin")
+load("@rules_java//java:defs.bzl", "java_binary", "java_library", "java_plugin")
load("//src/main/starlark/release:packager.bzl", "release_archive")
# Copyright 2018 The Bazel Authors. All rights reserved.
@@ -74,14 +74,6 @@
runtime_deps = ["@kotlin_rules_maven//:org_pantsbuild_jarjar"],
)
-# TODO(bazelbuild/rules_kotlin/issues/273): Remove android_sdk import.
-java_import(
- name = "android_sdk",
- jars = ["@rules_android//tools/android:android_jar"],
- neverlink = 1,
- visibility = ["//visibility:public"],
-)
-
bzl_library(
name = "bzl",
srcs = [
diff --git a/third_party/BUILD.release.bazel b/third_party/BUILD.release.bazel
index fb1536f..ba19780 100644
--- a/third_party/BUILD.release.bazel
+++ b/third_party/BUILD.release.bazel
@@ -13,7 +13,7 @@
# limitations under the License.
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
-load("@rules_java//java:defs.bzl", "java_binary", "java_import")
+load("@rules_java//java:defs.bzl", "java_binary")
exports_files([
"empty.jar",
@@ -28,13 +28,6 @@
runtime_deps = [":jarjar.jar"],
)
-java_import(
- name = "android_sdk",
- jars = ["@rules_android//tools/android:android_jar"],
- neverlink = True,
- visibility = ["//visibility:public"],
-)
-
bzl_library(
name = "bzl",
srcs = [