Skip to content

Commit 5ecb3fa

Browse files
authored
[kapt] allow options to be passed to kapt and javac annotation processing. (#1354)
* [kapt] allow options to be passed to kapt and javac annotation processing. java annotatin processing options can be passed like this: ``` kt_plugin_cfg( name = "autovalue_no_identifiers", options = { "com.google.auto.value.OmitIdentifiers": ["true"], }, plugin = "//kotlin/compiler:kapt", deps = [ ":autovalue", ], ) ``` * Fix lint errors
1 parent 17862f9 commit 5ecb3fa

File tree

22 files changed

+499
-66
lines changed

22 files changed

+499
-66
lines changed

kotlin/compiler/BUILD

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ load("//src/main/starlark/release:packager.bzl", "release_archive")
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616
load(":compiler.bzl", "kt_configure_compiler")
17+
load(":kapt.bzl", "kapt_compiler_plugin")
1718
load(":ksp.bzl", "kt_configure_ksp")
1819

1920
package(default_visibility = ["//visibility:public"])
@@ -31,3 +32,8 @@ release_archive(
3132
"BUILD.release.bazel": "BUILD.bazel",
3233
},
3334
)
35+
36+
kapt_compiler_plugin(
37+
name = "kapt",
38+
id = "org.jetbrains.kotlin.kapt3",
39+
)

kotlin/compiler/BUILD.release.bazel

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
1616
load(":compiler.bzl", "kt_configure_compiler")
17+
load(":kapt.bzl", "kapt_compiler_plugin")
1718
load(":ksp.bzl", "kt_configure_ksp")
1819

1920
package(default_visibility = ["//visibility:public"])
@@ -28,3 +29,8 @@ bzl_library(
2829
name = "compiler",
2930
srcs = glob(["*.bzl"]),
3031
)
32+
33+
kapt_compiler_plugin(
34+
name = "kapt",
35+
id = "org.jetbrains.kotlin.kapt3",
36+
)

kotlin/compiler/kapt.bzl

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
load("@rules_java//java/common:java_common.bzl", "java_common")
2+
load("@rules_java//java/common:java_info.bzl", "JavaInfo")
3+
load("@rules_java//java/common:java_plugin_info.bzl", "JavaPluginInfo")
4+
load("//src/main/starlark/core/options:opts.javac.bzl", "JavacOptions")
5+
load("//src/main/starlark/core/plugin:common.bzl", "plugin_common")
6+
load(
7+
"//src/main/starlark/core/plugin:providers.bzl",
8+
"KtCompilerPluginInfo",
9+
"KtCompilerPluginOption",
10+
"KtPluginConfiguration",
11+
)
12+
13+
def _resolve_kapt_cfg(
14+
info,
15+
option_string_list_dict,
16+
deps,
17+
expand_location): # @unused Needed for lambda contract.
18+
infos = []
19+
plugins = []
20+
for d in deps:
21+
if JavaInfo in d:
22+
infos.append(d[JavaInfo])
23+
if JavaPluginInfo in d:
24+
# mild chicanary to turn a JavaPluginInfo in to a JavaInfo.
25+
# This is necessary to merge all the java related things into a single JavaInfo
26+
# that exports all plugins. It would be easier if there was a way to
27+
# generate JavaInfo without an output_jar.
28+
jpi = d[JavaPluginInfo]
29+
for o in jpi.java_outputs:
30+
infos.append(
31+
JavaInfo(
32+
output_jar = o.class_jar,
33+
compile_jar = o.compile_jar,
34+
exported_plugins = [jpi],
35+
),
36+
)
37+
38+
ji = java_common.merge(infos)
39+
classpath = depset(ji.runtime_output_jars, transitive = [ji.transitive_runtime_jars])
40+
data = None
41+
data_runfiles = [d[DefaultInfo].default_runfiles for d in deps if d[DefaultInfo]]
42+
if data_runfiles:
43+
data = data_runfiles[0].merge_all(data_runfiles[1:])
44+
return [
45+
ji, # allows java compilation to pick up the annotation processor.
46+
JavacOptions(
47+
annotation_processor_options = {
48+
k: v
49+
for (k, vs) in option_string_list_dict.items()
50+
for v in vs
51+
},
52+
),
53+
KtPluginConfiguration(
54+
id = info.id,
55+
options = [
56+
KtCompilerPluginOption(
57+
id = info.id,
58+
value = "apoption=%s:%s" % (k, v),
59+
)
60+
for (k, vs) in option_string_list_dict.items()
61+
for v in vs
62+
],
63+
classpath = classpath,
64+
data = data,
65+
),
66+
] + plugins
67+
68+
def _kapt_compiler_plugin_impl(ctx):
69+
plugin_id = ctx.attr.id
70+
return [
71+
KtCompilerPluginInfo(
72+
id = plugin_id,
73+
classpath = depset(),
74+
options = [],
75+
stubs = True,
76+
compile = False,
77+
resolve_cfg = _resolve_kapt_cfg,
78+
merge_cfgs = plugin_common.merge_cfgs,
79+
),
80+
]
81+
82+
kapt_compiler_plugin = rule(
83+
implementation = _kapt_compiler_plugin_impl,
84+
attrs = {
85+
"id": attr.string(default = "org.jetbrains.kotlin.kapt3"),
86+
},
87+
)

kotlin/internal/jvm/compile.bzl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ def _new_plugins_from(targets):
197197
plugin = t[_KtCompilerPluginInfo]
198198
if not (plugin.stubs or plugin.compile):
199199
plugins_without_phase.append("%s: %s" % (t.label, plugin.id))
200-
if plugin.id in all_plugins:
200+
if plugin.id in all_plugins and all_plugins[plugin.id] != plugin:
201201
# This need a more robust error messaging.
202202
fail("has multiple plugins with the same id: %s." % plugin.id)
203203
all_plugins[plugin.id] = plugin
@@ -884,6 +884,12 @@ def _run_kt_java_builder_actions(
884884
ksp_generated_java_src_jars = generated_ksp_src_jars and is_ksp_processor_generating_java(ctx.attr.plugins)
885885
if srcs.java or generated_kapt_src_jars or srcs.src_jars or ksp_generated_java_src_jars:
886886
javac_opts = javac_options_to_flags(ctx.attr.javac_opts[JavacOptions] if ctx.attr.javac_opts else toolchains.kt.javac_options)
887+
javac_opts.extend([
888+
flag
889+
for plugin in ctx.attr.plugins
890+
if JavacOptions in plugin
891+
for flag in javac_options_to_flags(plugin[JavacOptions])
892+
])
887893

888894
# Kotlin takes care of annotation processing. Note that JavaBuilder "discovers"
889895
# annotation processors in `deps` also.
@@ -894,7 +900,7 @@ def _run_kt_java_builder_actions(
894900
source_files = srcs.java,
895901
source_jars = generated_kapt_src_jars + srcs.src_jars + generated_ksp_src_jars,
896902
output = ctx.actions.declare_file(ctx.label.name + "-java.jar"),
897-
deps = compile_deps.deps + kt_stubs_for_java,
903+
deps = compile_deps.deps + kt_stubs_for_java + [p[JavaInfo] for p in ctx.attr.plugins if JavaInfo in p],
898904
java_toolchain = toolchains.java,
899905
plugins = _plugin_mappers.targets_to_annotation_processors_java_plugin_info(ctx.attr.plugins),
900906
javac_opts = javac_opts,

kotlin/internal/jvm/impl.bzl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,9 @@ def kt_compiler_plugin_impl(ctx):
429429

430430
def kt_plugin_cfg_impl(ctx):
431431
plugin = ctx.attr.plugin[_KtCompilerPluginInfo]
432-
return plugin.resolve_cfg(plugin, ctx.attr.options, ctx.attr.deps, ctx.expand_location)
432+
return [
433+
plugin,
434+
] + plugin.resolve_cfg(plugin, ctx.attr.options, ctx.attr.deps, ctx.expand_location)
433435

434436
def kt_ksp_plugin_impl(ctx):
435437
deps = ctx.attr.deps

kotlin/internal/jvm/jvm.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,7 @@ kt_plugin_cfg = rule(
661661
[JavaInfo],
662662
[JavaPluginInfo],
663663
],
664+
cfg = "exec",
664665
),
665666
},
666667
)

kotlin/internal/jvm/plugins.bzl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ def _targets_to_annotation_processors(targets):
4646
p = t[JavaInfo].plugins
4747
if p.processor_jars:
4848
plugins.append(p)
49-
return depset(plugins)
49+
50+
return plugins
5051

5152
def _targets_to_ksp_annotation_processors(targets):
5253
plugins = []

src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationArgs.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,13 @@ class CompilationArgs(
201201
for ((k, vs) in values) {
202202
oos.writeUTF(k)
203203

204-
oos.writeInt(vs.size)
205-
for (v in vs) {
206-
oos.writeUTF(v)
204+
if (vs.size == 1) {
205+
oos.writeUTF(vs[0])
206+
} else {
207+
oos.writeInt(vs.size)
208+
for (v in vs) {
209+
oos.writeUTF(v)
210+
}
207211
}
208212
}
209213

src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationTask.kt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ internal fun JvmCompilationTask.kaptArgs(
167167
val version =
168168
info.toolchainInfo.common.apiVersion
169169
.toFloat()
170+
170171
when {
171172
version < 1.5 ->
172173
base64Encode(
@@ -181,6 +182,20 @@ internal fun JvmCompilationTask.kaptArgs(
181182
"plugin:${plugins.kapt.id}:$option=$value"
182183
}
183184
}
185+
// Read kapt options from the plugin options
186+
val optionPrefix = plugins.kapt.id + ":apoption="
187+
val options =
188+
(inputs.compilerPluginOptionsList + inputs.stubsPluginOptionsList)
189+
.filter { o -> o.startsWith(optionPrefix) }
190+
.map { o -> o.substring(optionPrefix.length).split(":", limit = 2) }
191+
.map { kv -> kv[0] to listOf(kv[1]) }
192+
.toTypedArray()
193+
194+
if (options.isNotEmpty()) {
195+
base64Encode("-P", *options) { enc ->
196+
"plugin:${plugins.kapt.id}:apoptions=$enc"
197+
}
198+
}
184199
}
185200
}
186201

@@ -265,7 +280,7 @@ private fun JvmCompilationTask.runKaptPlugin(
265280
baseArgs()
266281
.plus(
267282
plugins(
268-
options = inputs.stubsPluginOptionsList,
283+
options = inputs.stubsPluginOptionsList.filterNot { o -> o.startsWith(plugins.kapt.id) },
269284
classpath = inputs.stubsPluginClasspathList,
270285
),
271286
).plus(
@@ -278,7 +293,7 @@ private fun JvmCompilationTask.runKaptPlugin(
278293
context.executeCompilerTask(
279294
args,
280295
compiler::compile,
281-
printOnSuccess = context.whenTracing { true } ?: false,
296+
printOnSuccess = context.whenTracing { true } == true,
282297
)
283298
}.let { outputLines ->
284299
// if tracing is enabled the output should be formatted in a special way, if we aren't

src/main/starlark/core/options/convert.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def _to_flags(opts, attr_provider):
1717
value = getattr(attr_provider, n, None)
1818
if o.value_to_flag and o.value_to_flag.get(derive.info, None):
1919
info = o.value_to_flag[derive.info]
20-
flag = info.derive(info.ctx, value)
20+
flag = info.derive(info.ctx, value or o.args.get("default", None))
2121
elif o.value_to_flag:
2222
flag = o.value_to_flag.get(value, None)
2323
else:

0 commit comments

Comments
 (0)