blob: 59348bb6599b3bc5f86b1be81d032f7bdadfed6c [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/rules:defs.bzl",
_KotlinInfo = "KotlinInfo",
)
load(
"//kotlin/rules:plugins.bzl",
_merge_plugin_infos = "merge_plugin_infos",
)
load(
"//kotlin/rules:util.bzl",
_collect_all_jars = "collect_all_jars",
_collect_jars_for_compile = "collect_jars_for_compile",
_kotlin_build_resourcejar_action = "kotlin_build_resourcejar_action",
_kotlin_fold_jars_action = "kotlin_fold_jars_action",
_kotlin_maybe_make_srcs_action = "kotlin_maybe_make_srcs_action",
)
def _kotlin_do_compile_action(ctx, output_jar, compile_jars, opts):
"""Internal macro that sets up a Kotlin compile action.
This macro only supports a single Kotlin compile operation for a rule.
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 `srcs` to compile.
output_jar: The jar file that this macro will use as the output of the action -- a hardcoded default output is not
setup by this rule as this would close the door to optimizations for simple compile operations.
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.
opts: struct containing Kotlin compilation options.
"""
compiler_output_base=ctx.actions.declare_directory(ctx.label.name + "." + "kotlinc")
tc=ctx.toolchains["@io_bazel_rules_kotlin//kotlin:kt_jvm_toolchain_type"]
args = [
"--target_label", ctx.label,
"--compiler_output_base", compiler_output_base.path,
"--output", output_jar.path,
"--output_jdeps", ctx.outputs.jdeps.path,
"--classpath", ":".join([f.path for f in compile_jars.to_list()]),
"--sources", ":".join([f.path for f in ctx.files.srcs]),
"--kotlin_jvm_target", tc.jvm_target,
"--kotlin_api_version", tc.api_version,
"--kotlin_language_version", tc.language_version,
"--kotlin_passthrough_flags", "-Xcoroutines=%s" % tc.coroutines
]
# Collect and prepare plugin descriptor for the worker.
plugin_info=_merge_plugin_infos(ctx.attr.plugins + ctx.attr.deps)
if len(plugin_info.processors) > 0:
args += [ "--kt-plugins", plugin_info.to_json() ]
# Declare and write out argument file.
args_file = ctx.actions.declare_file(ctx.label.name + "-worker.args")
ctx.actions.write(args_file, "\n".join(args))
# When a stratetegy isn't provided for the worker and the workspace is fresh then certain deps are not available under
# external/@com_github_jetbrains_kotlin/... that is why the classpath is added explicetly.
compile_inputs = (
depset([args_file]) +
ctx.files.srcs +
compile_jars +
ctx.files._kotlin_compiler_classpath +
ctx.files._kotlin_home +
ctx.files._jdk)
ctx.action(
mnemonic = "KotlinCompile",
inputs = compile_inputs,
outputs = [output_jar, ctx.outputs.jdeps, compiler_output_base],
executable = ctx.executable._kotlinw,
execution_requirements = {"supports-workers": "1"},
arguments = ["@" + args_file.path],
progress_message="Compiling %d Kotlin source files to %s" % (len(ctx.files.srcs), output_jar.short_path),
)
def _select_compilation_options(ctx):
"""TODO Stub: setup compilation options"""
return struct(
# Basic kotlin compile options.
opts = {},
# Advanced Kotlin compile options.
x_opts ={},
# Kotlin compiler plugin options.
plugin_opts = {}
)
def _select_std_libs(ctx):
return ctx.files._kotlin_std
def _make_java_provider(ctx, 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.
"""
deps=_collect_all_jars(ctx.attr.deps)
exported_deps=_collect_all_jars(getattr(ctx.attr, "exports", []))
my_compile_jars = exported_deps.compile_jars + [ctx.outputs.jar]
my_runtime_jars = exported_deps.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 + [ctx.file._kotlin_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=_kotlin_maybe_make_srcs_action(ctx),
# 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 kotlin_make_providers(ctx, java_info, transitive_files=depset(order="default")):
kotlin_info=_KotlinInfo(
src=ctx.attr.srcs,
outputs = struct(
jdeps = ctx.outputs.jdeps,
jars = [struct(
class_jar = ctx.outputs.jar,
ijar = None,
)]
), # intelij aspect needs this.
)
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 kotlin_compile_action(ctx):
"""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 + [_kotlin_build_resourcejar_action(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)
# setup the compile action.
_kotlin_do_compile_action(
ctx,
kt_compile_output_jar,
_collect_jars_for_compile(ctx.attr.deps) + kotlin_auto_deps,
_select_compilation_options(ctx)
)
# setup the merge action if needed.
if len(output_merge_list) > 0:
_kotlin_fold_jars_action(ctx, output_jar, output_merge_list)
# create the java provider but the kotlin and default provider cannot be created here.
return _make_java_provider(ctx, kotlin_auto_deps)