blob: 71f1d48e1529e702caba7141f7a9b223d5ca7667 [file] [log] [blame]
# 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:kt.bzl", "kt")
load("//kotlin/internal:plugins.bzl", "plugins")
load("//kotlin/internal:utils.bzl", "utils")
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 _common_init_args(ctx, rule_kind, module_name):
toolchain=ctx.toolchains[kt.defs.TOOLCHAIN_TYPE]
args = ctx.actions.args()
args.set_param_file_format("multiline")
args.use_param_file("--flagfile=%s", use_always=True)
args.add("--target_label", ctx.label)
args.add("--rule_kind", rule_kind)
args.add("--kotlin_module_name", module_name)
args.add("--kotlin_jvm_target", toolchain.jvm_target)
args.add("--kotlin_api_version", toolchain.api_version)
args.add("--kotlin_language_version", toolchain.language_version)
args.add("--kotlin_passthrough_flags", "-Xcoroutines=%s" % toolchain.coroutines)
return args
def _kotlin_do_compile_action(ctx, rule_kind, output_jar, compile_jars, module_name, friend_paths, srcs):
"""Internal macro that sets up a Kotlin compile action.
This macro only supports a single Kotlin compile operation for a rule.
Args:
rule_kind: The rule kind,
output_jar: The jar file that this macro will use as the output of the action.
compile_jars: The compile time jars provided on the classpath for the compile operations -- callers are
responsible for preparing the classpath. The stdlib (and jdk7 + jdk8) should generally be added to the classpath
by the caller -- kotlin-reflect could be optional.
"""
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")
toolchain=ctx.toolchains[kt.defs.TOOLCHAIN_TYPE]
args = _common_init_args(ctx, rule_kind, module_name)
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("--output_jdeps", ctx.outputs.jdeps)
args.add("--kotlin_output_srcjar", ctx.outputs.srcjar)
args.add("--kotlin_friend_paths", "\n".join(friend_paths.to_list()))
args.add("--classpath", 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)
# Collect and prepare plugin descriptor for the worker.
plugin_info=plugins.merge_plugin_infos(ctx.attr.plugins + ctx.attr.deps)
if len(plugin_info.annotation_processors) > 0:
args.add("--kt-plugins", plugin_info.to_json())
progress_message = "Compiling Kotlin %s { kt: %d, java: %d, srcjars: %d }" % (
ctx.label,
len(srcs.kt),
len(srcs.java),
len(srcs.src_jars)
)
inputs, _, input_manifests = ctx.resolve_command(tools = [toolchain.kotlinbuilder])
ctx.actions.run(
mnemonic = "KotlinCompile",
inputs = depset(inputs) + ctx.files.srcs + compile_jars,
outputs = [
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"},
arguments = [args],
progress_message = progress_message,
input_manifests = input_manifests
)
def _select_std_libs(ctx):
return ctx.toolchains[kt.defs.TOOLCHAIN_TYPE].jvm_stdlibs
def _make_java_provider(ctx, srcs, input_deps=[], auto_deps=[]):
"""Creates the java_provider for a Kotlin target.
This macro is distinct from the kotlin_make_providers as collecting the java_info is useful before the DefaultInfo is
created.
Args:
ctx: The ctx of the rule in scope when this macro is called. The macro will pick up the following entities from
the rule ctx:
* The default output jar.
* The `deps` for this provider.
* Optionally `exports` (see java rules).
* The `_kotlin_runtime` implicit dependency.
Returns:
A JavaInfo provider.
"""
runtime = ctx.toolchains[kt.defs.TOOLCHAIN_TYPE].jvm_runtime
deps=utils.collect_all_jars(input_deps)
exported_deps=utils.collect_all_jars(getattr(ctx.attr, "exports", []))
my_compile_jars = exported_deps.compile_jars + [ctx.outputs.jar]
my_runtime_jars = exported_deps.transitive_runtime_jars + [ctx.outputs.jar]
my_transitive_compile_jars = my_compile_jars + deps.transitive_compile_time_jars + exported_deps.transitive_compile_time_jars + auto_deps
my_transitive_runtime_jars = my_runtime_jars + deps.transitive_runtime_jars + exported_deps.transitive_runtime_jars + runtime + auto_deps
# collect the runtime jars from the runtime_deps attribute.
for jar in ctx.attr.runtime_deps:
my_transitive_runtime_jars += jar[JavaInfo].transitive_runtime_jars
return java_common.create_provider(
use_ijar = False,
# A list or set of output source jars that contain the uncompiled source files including the source files
# generated by annotation processors if the case.
source_jars = [ctx.outputs.srcjar],
# A list or a set of jars that should be used at compilation for a given target.
compile_time_jars = my_compile_jars,
# A list or a set of jars that should be used at runtime for a given target.
runtime_jars = my_runtime_jars,
transitive_compile_time_jars = my_transitive_compile_jars,
transitive_runtime_jars = my_transitive_runtime_jars
)
def _make_providers(ctx, java_info, module_name, transitive_files=depset(order="default")):
kotlin_info=kt.info.KtInfo(
srcs=ctx.files.srcs,
module_name = module_name,
# intelij aspect needs this.
outputs = struct(
jdeps = ctx.outputs.jdeps,
jars = [struct(
class_jar = ctx.outputs.jar,
ijar = None,
source_jars = java_info.source_jars
)]
),
)
default_info = DefaultInfo(
files=depset([ctx.outputs.jar]),
runfiles=ctx.runfiles(
transitive_files=transitive_files,
collect_default=True
),
)
return struct(
kt=kotlin_info,
providers=[java_info,default_info,kotlin_info],
)
def _compile_action(ctx, rule_kind, module_name, friend_paths=depset(), src_jars=[]):
"""Setup a kotlin compile action.
Args:
ctx: The rule context.
Returns:
A JavaInfo struct for the output jar that this macro will build.
"""
# The main output jars
output_jar = ctx.outputs.jar
# The output of the compile step may be combined (folded) with other entities -- e.g., other class files from annotation processing, embedded resources.
kt_compile_output_jar=output_jar
# the list of jars to merge into the final output, start with the resource jars if any were provided.
output_merge_list=ctx.files.resource_jars
# If this rule has any resources declared setup a zipper action to turn them into a jar and then add the declared zipper output to the merge list.
if len(ctx.files.resources) > 0:
output_merge_list = output_merge_list + [utils.actions.build_resourcejar(ctx)]
# If this compile operation requires merging other jars setup the compile operation to go to a intermediate file and add that file to the merge list.
if len(output_merge_list) > 0:
# Intermediate jar containing the Kotlin compile output.
kt_compile_output_jar=ctx.new_file(ctx.label.name + "-ktclass.jar")
# If we setup indirection than the first entry in the merge list is the result of the kotlin compile action.
output_merge_list=[ kt_compile_output_jar ] + output_merge_list
kotlin_auto_deps=_select_std_libs(ctx)
deps = ctx.attr.deps + getattr(ctx.attr, "friends", [])
srcs = utils.partition_srcs(ctx.files.srcs)
if (len(srcs.kt) + len(srcs.java) == 0) and len(srcs.src_jars) == 0:
fail("no sources provided")
# setup the compile action.
_kotlin_do_compile_action(
ctx,
rule_kind = rule_kind,
output_jar = kt_compile_output_jar,
compile_jars = utils.collect_jars_for_compile(deps) + kotlin_auto_deps,
module_name = module_name,
friend_paths = friend_paths,
srcs = srcs
)
# setup the merge action if needed.
if len(output_merge_list) > 0:
utils.actions.fold_jars(ctx, rule_kind, output_jar, output_merge_list)
# create the java provider but the kotlin and default provider cannot be created here.
return _make_java_provider(ctx, srcs, deps, kotlin_auto_deps)
compile = struct(
compile_action = _compile_action,
make_providers = _make_providers,
)