diff --git a/examples/ksp/BUILD b/examples/ksp/BUILD index 0c4a5acdf..6722c96f2 100644 --- a/examples/ksp/BUILD +++ b/examples/ksp/BUILD @@ -14,7 +14,7 @@ load("@rules_java//java:defs.bzl", "java_binary", "java_plugin") # 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_kotlin//kotlin:core.bzl", "define_kt_toolchain", "kt_ksp_plugin") +load("@rules_kotlin//kotlin:core.bzl", "define_kt_toolchain", "kt_compiler_plugin", "kt_ksp_plugin", "kt_plugin_cfg") load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") package(default_visibility = ["//visibility:public"]) @@ -81,3 +81,73 @@ build_test( "//:coffee_app_deploy.jar", ], ) + +kt_compiler_plugin( + name = "ksp", + compile_phase = True, + id = "com.google.devtools.ksp.symbol-processing", + options = { + "apclasspath": "{classpath}", + # projectBaseDir shouldn't matter because incremental is disabled + "projectBaseDir": "{temp}", + # Disable incremental mode + "incremental": "false", + # Directory where class files are written to. Files written to this directory are class + # files being written directly from the annotation processor, not Kotlinc + "classOutputDir": "{generatedClasses}", + # Directory where generated Java sources files are written to + "javaOutputDir": "{generatedSources}", + # Directory where generated Kotlin sources files are written to + "kotlinOutputDir": "{generatedSources}", + # Directory where META-INF data is written to. This might not be the most ideal place to + # write this. Maybe just directly to the classes directory? + "resourceOutputDir": "{generatedSources}", + # TODO(bencodes) Not sure what this directory is yet. + "kspOutputDir": "{temp}", + # Directory to write KSP caches. Shouldn't matter because incremental is disabled + "cachesDir": "{temp}", + # Include in compilation as an example. This should be processed in the stubs phase. + "withCompilation": "true", + # Set returnOkOnError to false because we want to fail the build if there are any errors + "returnOkOnError": "false", + "allWarningsAsErrors": "false", + }, + deps = [ + "@rules_kotlin//kotlin/compiler:symbol-processing-api", + "@rules_kotlin//kotlin/compiler:symbol-processing-cmdline", + ], +) + +kt_plugin_cfg( + name = "ksp_moshi", + options = { + }, + plugin = ":ksp", + deps = [ + "@maven//:com_squareup_moshi_moshi", + "@maven//:com_squareup_moshi_moshi_kotlin", + "@maven//:com_squareup_moshi_moshi_kotlin_codegen", + ], +) + +kt_jvm_library( + name = "raw_ksp_coffee_app_lib", + srcs = ["CoffeeAppModel.kt"], + plugins = [ + "//:ksp", + "//:ksp_moshi", + ], + deps = [ + "@maven//:com_google_auto_service_auto_service_annotations", + "@maven//:com_google_auto_value_auto_value_annotations", + "@maven//:com_squareup_moshi_moshi", + "@maven//:com_squareup_moshi_moshi_kotlin", + ], +) + +build_test( + name = "raw_ksp_lib_test", + targets = [ + "//:raw_ksp_coffee_app_lib", + ], +) diff --git a/examples/ksp/MODULE.bazel b/examples/ksp/MODULE.bazel new file mode 100644 index 000000000..00bb18361 --- /dev/null +++ b/examples/ksp/MODULE.bazel @@ -0,0 +1,6 @@ +############################################################################### +# Bazel now uses Bzlmod by default to manage external dependencies. +# Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel. +# +# For more details, please check https://github.com/bazelbuild/bazel/issues/18958 +############################################################################### diff --git a/kotlin/internal/jvm/impl.bzl b/kotlin/internal/jvm/impl.bzl index d74d6c033..393d44950 100644 --- a/kotlin/internal/jvm/impl.bzl +++ b/kotlin/internal/jvm/impl.bzl @@ -385,40 +385,39 @@ def _deshade_embedded_kotlinc_jars(target, ctx, jars, deps): ], ) -def _resolve_plugin_options(id, string_dict): +def _resolve_plugin_options(id, string_list_dict, expand_location): """ Resolves plugin options from a string dict to a dict of strings. Args: id: the plugin id - string_dict: a dict of strings + string_list_dict: a dict of list[string]. Returns: a dict of strings """ options = [] - for (k, v) in string_dict.items(): - if "=" in k: - fail("kt_compiler_plugin options keys cannot contain the = symbol") - options.append(KtCompilerPluginOption(id = id, value = k + "=" + v)) + for (k, vs) in string_list_dict.items(): + for v in vs: + if "=" in k: + fail("kotlin compiler option keys cannot contain the = symbol") + value = k + "=" + expand_location(v) if v else k + options.append(KtCompilerPluginOption(id = id, value = value)) return options # This is naive reference implementation for resolving configurations. # A more complicated plugin will need to provide its own implementation. -def _resolve_plugin_cfg(info, options, deps): - classpath = [] - for dep in deps: - if JavaInfo in dep: - classpath.append(dep[JavaInfo].compile_jars) +def _resolve_plugin_cfg(info, options, deps, expand_location): + ji = java_common.merge([dep[JavaInfo] for dep in deps if JavaInfo in dep]) + classpath = depset(ji.runtime_output_jars, transitive = [ji.transitive_runtime_jars]) return KtPluginConfiguration( id = info.id, - options = _resolve_plugin_options(info.id, options), - classpath = depset(transitive = classpath), + options = _resolve_plugin_options(info.id, options, expand_location), + classpath = classpath, data = depset(), ) def kt_compiler_plugin_impl(ctx): plugin_id = ctx.attr.id - options = _resolve_plugin_options(plugin_id, ctx.attr.options) deps = ctx.attr.deps info = None @@ -437,6 +436,9 @@ def kt_compiler_plugin_impl(ctx): classpath = depset(info.runtime_output_jars, transitive = [info.transitive_runtime_jars]) + # TODO(1035): Migrate kt_compiler_plugin.options to string_list_dict + options = _resolve_plugin_options(plugin_id, {k: [v] for (k, v) in ctx.attr.options.items()}, ctx.expand_location) + return [ DefaultInfo(files = classpath), _KtCompilerPluginInfo( @@ -451,7 +453,7 @@ def kt_compiler_plugin_impl(ctx): def kt_plugin_cfg_impl(ctx): plugin = ctx.attr.plugin[_KtCompilerPluginInfo] - return plugin.resolve_cfg(plugin, ctx.attr.options, ctx.attr.deps) + return plugin.resolve_cfg(plugin, ctx.attr.options, ctx.attr.deps, ctx.expand_location) def kt_ksp_plugin_impl(ctx): info = java_common.merge([dep[JavaInfo] for dep in ctx.attr.deps]) diff --git a/kotlin/internal/jvm/jvm.bzl b/kotlin/internal/jvm/jvm.bzl index a98e5a927..fef824844 100644 --- a/kotlin/internal/jvm/jvm.bzl +++ b/kotlin/internal/jvm/jvm.bzl @@ -622,9 +622,10 @@ kt_plugin_cfg = rule( "plugin": attr.label( doc = "The plugin to associate with this configuration", providers = [_KtCompilerPluginInfo], + mandatory = True, ), - "options": attr.string_dict( - doc = "A list of plugin configuration options.", + "options": attr.string_list_dict( + doc = "A dictionary of flag to values to be used as plugin configuration options.", ), "deps": attr.label_list( doc = "Dependencies for this configuration.", diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationTask.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationTask.kt index 9f8dbf30a..a5b0ff212 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationTask.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationTask.kt @@ -97,13 +97,15 @@ internal fun JvmCompilationTask.plugins( xFlag("plugin", it) } - val dirTokens = mapOf( + val optionTokens = mapOf( "{generatedClasses}" to directories.generatedClasses, "{stubs}" to directories.stubs, + "{temp}" to directories.temp, "{generatedSources}" to directories.generatedSources, + "{classpath}" to classpath.joinToString(File.pathSeparator) ) options.forEach { opt -> - val formatted = dirTokens.entries.fold(opt) { formatting, (token, value) -> + val formatted = optionTokens.entries.fold(opt) { formatting, (token, value) -> formatting.replace(token, value) } flag("-P", "plugin:$formatted") diff --git a/src/main/starlark/core/plugin/providers.bzl b/src/main/starlark/core/plugin/providers.bzl index ce523d382..93c610bd7 100644 --- a/src/main/starlark/core/plugin/providers.bzl +++ b/src/main/starlark/core/plugin/providers.bzl @@ -13,7 +13,8 @@ KtCompilerPluginInfo = provider( "stubs": "Run this plugin during kapt stub generation.", "compile": "Run this plugin during koltinc compilation.", "options": "List of plugin options, represented as KtCompilerPluginOption, to be passed to the compiler", - "resolve_cfg": """"A Callable[[KtCompilerPluginInfo, Dict[str,str], List[Target], KtPluginConfiguration] that resolves an associated plugin configuration.""", + "resolve_cfg": "A Callable[[KtCompilerPluginInfo, Dict[str,str], List[Target], KtPluginConfiguration]" + + " that resolves an associated plugin configuration.", }, ) diff --git a/src/main/starlark/core/repositories/setup.bzl b/src/main/starlark/core/repositories/setup.bzl index bec1edc7b..72afe746a 100644 --- a/src/main/starlark/core/repositories/setup.bzl +++ b/src/main/starlark/core/repositories/setup.bzl @@ -29,8 +29,6 @@ def kt_configure(): native.register_toolchains("@released_rules_kotlin//kotlin/internal:default_toolchain") - native.register_toolchains("@released_rules_kotlin//kotlin/internal:default_toolchain") - maven_install( name = "kotlin_rules_maven", fetch_sources = True,