diff --git a/docs/kotlin.md b/docs/kotlin.md index 827f240c3..3bca74dc1 100644 --- a/docs/kotlin.md +++ b/docs/kotlin.md @@ -525,6 +525,7 @@ load("@rules_kotlin//kotlin:core.bzl", "define_kt_toolchain") define_kt_toolchain(name, language_version, api_version, jvm_target, experimental_use_abi_jars, experimental_treat_internal_as_private_in_abi_jars, experimental_remove_private_classes_in_abi_jars, + experimental_generate_associates_abi_jars, experimental_remove_debug_info_in_abi_jars, experimental_strict_kotlin_deps, experimental_report_unused_deps, experimental_reduce_classpath_mode, experimental_multiplex_workers, experimental_build_tools_api, javac_options, @@ -546,6 +547,7 @@ Define the Kotlin toolchain. | experimental_use_abi_jars |

-

| `False` | | experimental_treat_internal_as_private_in_abi_jars |

-

| `False` | | experimental_remove_private_classes_in_abi_jars |

-

| `False` | +| experimental_generate_associates_abi_jars |

-

| `False` | | experimental_remove_debug_info_in_abi_jars |

-

| `False` | | experimental_strict_kotlin_deps |

-

| `None` | | experimental_report_unused_deps |

-

| `None` | diff --git a/examples/associates_dagger/.bazelrc b/examples/associates_dagger/.bazelrc new file mode 100644 index 000000000..ce4930041 --- /dev/null +++ b/examples/associates_dagger/.bazelrc @@ -0,0 +1,2 @@ +common --java_runtime_version=remotejdk_21 +common --tool_java_runtime_version=remotejdk_21 diff --git a/examples/associates_dagger/.bazelversion b/examples/associates_dagger/.bazelversion new file mode 120000 index 000000000..96cf94962 --- /dev/null +++ b/examples/associates_dagger/.bazelversion @@ -0,0 +1 @@ +../../.bazelversion \ No newline at end of file diff --git a/examples/associates_dagger/BUILD b/examples/associates_dagger/BUILD new file mode 100644 index 000000000..538ad1b23 --- /dev/null +++ b/examples/associates_dagger/BUILD @@ -0,0 +1,11 @@ +load("@rules_kotlin//kotlin:core.bzl", "define_kt_toolchain") + +define_kt_toolchain( + name = "kotlin_toolchain", + api_version = "2.1", + experimental_generate_associates_abi_jars = True, + experimental_remove_private_classes_in_abi_jars = True, + experimental_treat_internal_as_private_in_abi_jars = True, + experimental_use_abi_jars = True, + language_version = "2.1", +) diff --git a/examples/associates_dagger/MODULE.bazel b/examples/associates_dagger/MODULE.bazel new file mode 100644 index 000000000..b09d32933 --- /dev/null +++ b/examples/associates_dagger/MODULE.bazel @@ -0,0 +1,29 @@ +module(name = "associates-dagger-example") + +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "rules_java", version = "8.9.0") +bazel_dep(name = "rules_kotlin", version = "2.2.0") +local_path_override( + module_name = "rules_kotlin", + path = "../..", +) + +register_toolchains("//:kotlin_toolchain") + +bazel_dep(name = "rules_jvm_external", version = "6.10") + +maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven") +maven.install( + name = "maven_rules_kotlin_example", + artifacts = [ + "com.google.dagger:dagger:2.59", + "com.google.dagger:dagger-compiler:2.59", + "com.google.dagger:dagger-producers:2.59", + "javax.inject:javax.inject:1", + ], + lock_file = "//:maven_install.json", + repositories = [ + "https://repo1.maven.org/maven2", + ], +) +use_repo(maven, "maven_rules_kotlin_example") diff --git a/examples/associates_dagger/WORKSPACE b/examples/associates_dagger/WORKSPACE new file mode 100644 index 000000000..e86bb038a --- /dev/null +++ b/examples/associates_dagger/WORKSPACE @@ -0,0 +1,120 @@ +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "rules_kotlin", + sha256 = "34e8c0351764b71d78f76c8746e98063979ce08dcf1a91666f3f3bc2949a533d", + url = "https://github.com/bazelbuild/rules_kotlin/releases/download/v1.9.5/rules_kotlin-v1.9.5.tar.gz", +) + +load("@rules_kotlin//kotlin:repositories.bzl", "kotlin_repositories", "versions") + +http_archive( + name = "rules_jvm_external", + sha256 = versions.RULES_JVM_EXTERNAL.sha256, + strip_prefix = "rules_jvm_external-%s" % versions.RULES_JVM_EXTERNAL.version, + urls = [url.format(version = versions.RULES_JVM_EXTERNAL.version) for url in versions.RULES_JVM_EXTERNAL.url_templates], +) + +http_archive( + name = "rules_android", + sha256 = versions.RULES_ANDROID.sha256, + strip_prefix = versions.RULES_ANDROID.strip_prefix_template.format(version = versions.RULES_ANDROID.version), + urls = [url.format(version = versions.RULES_ANDROID.version) for url in versions.RULES_ANDROID.url_templates], +) + +http_archive( + name = "rules_shell", + sha256 = "3e114424a5c7e4fd43e0133cc6ecdfe54e45ae8affa14fadd839f29901424043", + strip_prefix = "rules_shell-0.4.0", + url = "https://github.com/bazelbuild/rules_shell/releases/download/v0.4.0/rules_shell-v0.4.0.tar.gz", +) + +http_archive( + name = "bazel_skylib", + sha256 = versions.BAZEL_SKYLIB.sha256, + urls = [url.format(version = versions.BAZEL_SKYLIB.version) for url in versions.BAZEL_SKYLIB.url_templates], +) + +http_archive( + name = "bazel_features", + sha256 = versions.BAZEL_FEATURES.sha256, + strip_prefix = versions.BAZEL_FEATURES.strip_prefix_template.format(version = versions.BAZEL_FEATURES.version), + urls = [url.format(version = versions.BAZEL_FEATURES.version) for url in versions.BAZEL_FEATURES.url_templates], +) + +load("@bazel_features//:deps.bzl", "bazel_features_deps") + +bazel_features_deps() + +http_archive( + name = "bazel_lib", + sha256 = versions.BAZEL_LIB.sha256, + strip_prefix = versions.BAZEL_LIB.strip_prefix_template.format(version = versions.BAZEL_LIB.version), + urls = [url.format(version = versions.BAZEL_LIB.version) for url in versions.BAZEL_LIB.url_templates], +) + +http_archive( + name = "rules_cc", + sha256 = versions.RULES_CC.sha256, + strip_prefix = versions.RULES_CC.strip_prefix_template.format(version = versions.RULES_CC.version), + urls = [url.format(version = versions.RULES_CC.version) for url in versions.RULES_CC.url_templates], +) + +load("@rules_cc//cc:repositories.bzl", "rules_cc_dependencies", "rules_cc_toolchains") + +rules_cc_dependencies() + +rules_cc_toolchains() + +http_archive( + name = "rules_java", + sha256 = versions.RULES_JAVA.sha256, + urls = [url.format(version = versions.RULES_JAVA.version) for url in versions.RULES_JAVA.url_templates], +) + +kotlin_repositories() + +load("@rules_java//java:rules_java_deps.bzl", "rules_java_dependencies") + +rules_java_dependencies() + +load("@com_google_protobuf//bazel/private:proto_bazel_features.bzl", "proto_bazel_features") # buildifier: disable=bzl-visibility + +proto_bazel_features(name = "proto_bazel_features") + +load("@rules_java//java:repositories.bzl", "rules_java_toolchains") + +rules_java_toolchains() + +load("@rules_jvm_external//:repositories.bzl", "rules_jvm_external_deps") + +rules_jvm_external_deps() + +load("@rules_jvm_external//:setup.bzl", "rules_jvm_external_setup") + +rules_jvm_external_setup() + +load("@rules_kotlin//kotlin:core.bzl", "kt_register_toolchains") + +kt_register_toolchains() + +load("@rules_shell//shell:repositories.bzl", "rules_shell_dependencies", "rules_shell_toolchains") + +rules_shell_dependencies() + +rules_shell_toolchains() + +load("@rules_jvm_external//:defs.bzl", "maven_install") + +maven_install( + name = "maven_rules_kotlin_example", + artifacts = [ + "com.google.dagger:dagger:2.57.2", + "com.google.dagger:dagger-compiler:2.57.2", + "com.google.dagger:dagger-producers:2.57.2", + "javax.inject:javax.inject:1", + ], + repositories = [ + "https://repo1.maven.org/maven2", + ], +) diff --git a/examples/associates_dagger/maven_install.json b/examples/associates_dagger/maven_install.json new file mode 100644 index 000000000..2e37cde33 --- /dev/null +++ b/examples/associates_dagger/maven_install.json @@ -0,0 +1,629 @@ +{ + "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL", + "__INPUT_ARTIFACTS_HASH": { + "com.google.dagger:dagger": 232202338, + "com.google.dagger:dagger-compiler": -362498016, + "com.google.dagger:dagger-producers": -1075076722, + "javax.inject:javax.inject": -297932879, + "repositories": -1949687017 + }, + "__RESOLVED_ARTIFACTS_HASH": { + "com.google.code.findbugs:jsr305": 870839855, + "com.google.dagger:dagger": 1575529838, + "com.google.dagger:dagger-compiler": -49134844, + "com.google.dagger:dagger-producers": 1726420995, + "com.google.dagger:dagger-spi": 630982554, + "com.google.devtools.ksp:symbol-processing-api": -732428888, + "com.google.errorprone:error_prone_annotations": 712292353, + "com.google.googlejavaformat:google-java-format": -2085760752, + "com.google.guava:failureaccess": -718864417, + "com.google.guava:guava": -1058030103, + "com.google.guava:listenablefuture": 1079558157, + "com.google.j2objc:j2objc-annotations": 248818742, + "com.squareup:javapoet": -2135371934, + "com.squareup:kotlinpoet": -303024748, + "jakarta.inject:jakarta.inject-api": 188991469, + "javax.inject:javax.inject": 698155243, + "net.ltgt.gradle.incap:incap": 641640589, + "org.checkerframework:checker-compat-qual": -1467964223, + "org.checkerframework:checker-qual": 628949150, + "org.jetbrains.kotlin:kotlin-metadata-jvm": 2058544870, + "org.jetbrains.kotlin:kotlin-reflect": -1488851255, + "org.jetbrains.kotlin:kotlin-stdlib": 689270517, + "org.jetbrains.kotlin:kotlin-stdlib-jdk7": -235243283, + "org.jetbrains.kotlin:kotlin-stdlib-jdk8": -566798102, + "org.jetbrains:annotations": 554168982, + "org.jspecify:jspecify": 117231129 + }, + "artifacts": { + "com.google.code.findbugs:jsr305": { + "shasums": { + "jar": "766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7" + }, + "version": "3.0.2" + }, + "com.google.dagger:dagger": { + "shasums": { + "jar": "94d5b23812cc12fa903c9ac4a42978e7e7b2622e6b51c17f8b12037ceece43cd" + }, + "version": "2.59" + }, + "com.google.dagger:dagger-compiler": { + "shasums": { + "jar": "6a0a2ec75e775ff8cdcd84c8b0bfa975730bf000c24d6178f1662a27b94a098e" + }, + "version": "2.59" + }, + "com.google.dagger:dagger-producers": { + "shasums": { + "jar": "7417ab1a9fbd28cdeec15070c18769706d8554451099cee88ded2f584e8460f0" + }, + "version": "2.59" + }, + "com.google.dagger:dagger-spi": { + "shasums": { + "jar": "e89d1a2c0a55d4238a05a8dedd9e33c4eb87f26d0dcf29164edf10e857ff9edf" + }, + "version": "2.59" + }, + "com.google.devtools.ksp:symbol-processing-api": { + "shasums": { + "jar": "a20644569ecc01467d3efe4f8b9787a8719ce27ed12b6a3475ae1d82bfb16a0e" + }, + "version": "2.2.20-2.0.3" + }, + "com.google.errorprone:error_prone_annotations": { + "shasums": { + "jar": "6ba61510e22944e8aec3fe970972d088d8da132a24f2bc817a43c7b70665cc2b" + }, + "version": "2.45.0" + }, + "com.google.googlejavaformat:google-java-format": { + "shasums": { + "jar": "1265aa761ec2908535324b114995a1c6debaedc8a9e2e8553127babcdb58567f" + }, + "version": "1.33.0" + }, + "com.google.guava:failureaccess": { + "shasums": { + "jar": "8a8f81cf9b359e3f6dfa691a1e776985c061ef2f223c9b2c80753e1b458e8064" + }, + "version": "1.0.2" + }, + "com.google.guava:guava": { + "shasums": { + "jar": "f4d85c3e4d411694337cb873abea09b242b664bb013320be6105327c45991537" + }, + "version": "33.0.0-jre" + }, + "com.google.guava:listenablefuture": { + "shasums": { + "jar": "b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99" + }, + "version": "9999.0-empty-to-avoid-conflict-with-guava" + }, + "com.google.j2objc:j2objc-annotations": { + "shasums": { + "jar": "f02a95fa1a5e95edb3ed859fd0fb7df709d121a35290eff8b74dce2ab7f4d6ed" + }, + "version": "2.8" + }, + "com.squareup:javapoet": { + "shasums": { + "jar": "4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291" + }, + "version": "1.13.0" + }, + "com.squareup:kotlinpoet": { + "shasums": { + "jar": "2887ada1ca03dd83baa2758640d87e840d1907564db0ef88d2289c868a980492" + }, + "version": "1.11.0" + }, + "jakarta.inject:jakarta.inject-api": { + "shasums": { + "jar": "f7dc98062fccf14126abb751b64fab12c312566e8cbdc8483598bffcea93af7c" + }, + "version": "2.0.1" + }, + "javax.inject:javax.inject": { + "shasums": { + "jar": "91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff" + }, + "version": "1" + }, + "net.ltgt.gradle.incap:incap": { + "shasums": { + "jar": "b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd" + }, + "version": "0.2" + }, + "org.checkerframework:checker-compat-qual": { + "shasums": { + "jar": "d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d" + }, + "version": "2.5.3" + }, + "org.checkerframework:checker-qual": { + "shasums": { + "jar": "2f9f245bf68e4259d610894f2406dc1f6363dc639302bd566e8272e4f4541172" + }, + "version": "3.41.0" + }, + "org.jetbrains.kotlin:kotlin-metadata-jvm": { + "shasums": { + "jar": "8524eac90f7e8e0f1366883f2c6c820c93bfa61df3d76857c8d3e803cf67315d" + }, + "version": "2.2.20" + }, + "org.jetbrains.kotlin:kotlin-reflect": { + "shasums": { + "jar": "3277ac102ae17aad10a55abec75ff5696c8d109790396434b496e75087854203" + }, + "version": "1.6.10" + }, + "org.jetbrains.kotlin:kotlin-stdlib": { + "shasums": { + "jar": "8836ccffd3585fadda9901244b20d42901d2f3cd581058d8434e2ffabcf3a3e7" + }, + "version": "2.2.20" + }, + "org.jetbrains.kotlin:kotlin-stdlib-jdk7": { + "shasums": { + "jar": "2aedcdc6b69b33bdf5cc235bcea88e7cf6601146bb6bcdffdb312bbacd7be261" + }, + "version": "1.6.10" + }, + "org.jetbrains.kotlin:kotlin-stdlib-jdk8": { + "shasums": { + "jar": "1456d82d039ea30d8485b032901f52bbf07e7cdbe8bb1f8708ad32a8574c41ce" + }, + "version": "1.6.10" + }, + "org.jetbrains:annotations": { + "shasums": { + "jar": "ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478" + }, + "version": "13.0" + }, + "org.jspecify:jspecify": { + "shasums": { + "jar": "1fad6e6be7557781e4d33729d49ae1cdc8fdda6fe477bb0cc68ce351eafdfbab" + }, + "version": "1.0.0" + } + }, + "dependencies": { + "com.google.dagger:dagger": [ + "jakarta.inject:jakarta.inject-api", + "javax.inject:javax.inject", + "org.jspecify:jspecify" + ], + "com.google.dagger:dagger-compiler": [ + "com.google.code.findbugs:jsr305", + "com.google.dagger:dagger", + "com.google.dagger:dagger-spi", + "com.google.devtools.ksp:symbol-processing-api", + "com.google.googlejavaformat:google-java-format", + "com.google.guava:failureaccess", + "com.google.guava:guava", + "com.squareup:javapoet", + "com.squareup:kotlinpoet", + "javax.inject:javax.inject", + "net.ltgt.gradle.incap:incap", + "org.checkerframework:checker-compat-qual", + "org.jetbrains.kotlin:kotlin-metadata-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "com.google.dagger:dagger-producers": [ + "com.google.dagger:dagger", + "com.google.guava:failureaccess", + "com.google.guava:guava", + "javax.inject:javax.inject", + "org.checkerframework:checker-compat-qual" + ], + "com.google.dagger:dagger-spi": [ + "com.google.code.findbugs:jsr305", + "com.google.dagger:dagger", + "com.google.devtools.ksp:symbol-processing-api", + "com.google.guava:failureaccess", + "com.google.guava:guava", + "com.squareup:javapoet", + "javax.inject:javax.inject" + ], + "com.google.devtools.ksp:symbol-processing-api": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "com.google.googlejavaformat:google-java-format": [ + "com.google.guava:guava" + ], + "com.google.guava:guava": [ + "com.google.code.findbugs:jsr305", + "com.google.errorprone:error_prone_annotations", + "com.google.guava:failureaccess", + "com.google.guava:listenablefuture", + "com.google.j2objc:j2objc-annotations", + "org.checkerframework:checker-qual" + ], + "com.squareup:kotlinpoet": [ + "org.jetbrains.kotlin:kotlin-reflect", + "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + ], + "org.jetbrains.kotlin:kotlin-metadata-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.kotlin:kotlin-reflect": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.kotlin:kotlin-stdlib": [ + "org.jetbrains:annotations" + ], + "org.jetbrains.kotlin:kotlin-stdlib-jdk7": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.kotlin:kotlin-stdlib-jdk8": [ + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlin:kotlin-stdlib-jdk7" + ] + }, + "packages": { + "com.google.code.findbugs:jsr305": [ + "javax.annotation", + "javax.annotation.concurrent", + "javax.annotation.meta" + ], + "com.google.dagger:dagger": [ + "dagger", + "dagger.assisted", + "dagger.internal", + "dagger.multibindings" + ], + "com.google.dagger:dagger-compiler": [ + "dagger.internal.codegen", + "dagger.internal.codegen.base", + "dagger.internal.codegen.binding", + "dagger.internal.codegen.bindinggraphvalidation", + "dagger.internal.codegen.compileroption", + "dagger.internal.codegen.componentgenerator", + "dagger.internal.codegen.kotlin", + "dagger.internal.codegen.model", + "dagger.internal.codegen.processingstep", + "dagger.internal.codegen.validation", + "dagger.internal.codegen.writing", + "dagger.internal.codegen.xprocessing", + "dagger.spi.internal.shaded.androidx.room3.compiler.codegen", + "dagger.spi.internal.shaded.androidx.room3.compiler.codegen.compat", + "dagger.spi.internal.shaded.androidx.room3.compiler.codegen.impl", + "dagger.spi.internal.shaded.androidx.room3.compiler.codegen.java", + "dagger.spi.internal.shaded.androidx.room3.compiler.codegen.kotlin", + "dagger.spi.internal.shaded.androidx.room3.compiler.processing", + "dagger.spi.internal.shaded.androidx.room3.compiler.processing.compat", + "dagger.spi.internal.shaded.androidx.room3.compiler.processing.javac", + "dagger.spi.internal.shaded.androidx.room3.compiler.processing.javac.kotlin", + "dagger.spi.internal.shaded.androidx.room3.compiler.processing.ksp", + "dagger.spi.internal.shaded.androidx.room3.compiler.processing.ksp.synthetic", + "dagger.spi.internal.shaded.androidx.room3.compiler.processing.util" + ], + "com.google.dagger:dagger-producers": [ + "dagger.producers", + "dagger.producers.internal", + "dagger.producers.monitoring", + "dagger.producers.monitoring.internal" + ], + "com.google.dagger:dagger-spi": [ + "dagger.internal.codegen.extension", + "dagger.model", + "dagger.spi", + "dagger.spi.internal.shaded.com.google.auto.common", + "dagger.spi.internal.shaded.com.squareup.kotlinpoet.javapoet", + "dagger.spi.model" + ], + "com.google.devtools.ksp:symbol-processing-api": [ + "com.google.devtools.ksp", + "com.google.devtools.ksp.processing", + "com.google.devtools.ksp.symbol", + "com.google.devtools.ksp.visitor" + ], + "com.google.errorprone:error_prone_annotations": [ + "com.google.errorprone.annotations", + "com.google.errorprone.annotations.concurrent" + ], + "com.google.googlejavaformat:google-java-format": [ + "com.google.googlejavaformat", + "com.google.googlejavaformat.java", + "com.google.googlejavaformat.java.filer", + "com.google.googlejavaformat.java.javadoc" + ], + "com.google.guava:failureaccess": [ + "com.google.common.util.concurrent.internal" + ], + "com.google.guava:guava": [ + "com.google.common.annotations", + "com.google.common.base", + "com.google.common.base.internal", + "com.google.common.cache", + "com.google.common.collect", + "com.google.common.escape", + "com.google.common.eventbus", + "com.google.common.graph", + "com.google.common.hash", + "com.google.common.html", + "com.google.common.io", + "com.google.common.math", + "com.google.common.net", + "com.google.common.primitives", + "com.google.common.reflect", + "com.google.common.util.concurrent", + "com.google.common.xml", + "com.google.thirdparty.publicsuffix" + ], + "com.google.j2objc:j2objc-annotations": [ + "com.google.j2objc.annotations" + ], + "com.squareup:javapoet": [ + "com.squareup.javapoet" + ], + "com.squareup:kotlinpoet": [ + "com.squareup.kotlinpoet", + "com.squareup.kotlinpoet.jvm", + "com.squareup.kotlinpoet.tags" + ], + "jakarta.inject:jakarta.inject-api": [ + "jakarta.inject" + ], + "javax.inject:javax.inject": [ + "javax.inject" + ], + "net.ltgt.gradle.incap:incap": [ + "net.ltgt.gradle.incap" + ], + "org.checkerframework:checker-compat-qual": [ + "org.checkerframework.checker.nullness.compatqual" + ], + "org.checkerframework:checker-qual": [ + "org.checkerframework.checker.builder.qual", + "org.checkerframework.checker.calledmethods.qual", + "org.checkerframework.checker.compilermsgs.qual", + "org.checkerframework.checker.fenum.qual", + "org.checkerframework.checker.formatter.qual", + "org.checkerframework.checker.guieffect.qual", + "org.checkerframework.checker.i18n.qual", + "org.checkerframework.checker.i18nformatter.qual", + "org.checkerframework.checker.index.qual", + "org.checkerframework.checker.initialization.qual", + "org.checkerframework.checker.interning.qual", + "org.checkerframework.checker.lock.qual", + "org.checkerframework.checker.mustcall.qual", + "org.checkerframework.checker.nullness.qual", + "org.checkerframework.checker.optional.qual", + "org.checkerframework.checker.propkey.qual", + "org.checkerframework.checker.regex.qual", + "org.checkerframework.checker.signature.qual", + "org.checkerframework.checker.signedness.qual", + "org.checkerframework.checker.tainting.qual", + "org.checkerframework.checker.units.qual", + "org.checkerframework.common.aliasing.qual", + "org.checkerframework.common.initializedfields.qual", + "org.checkerframework.common.reflection.qual", + "org.checkerframework.common.returnsreceiver.qual", + "org.checkerframework.common.subtyping.qual", + "org.checkerframework.common.util.report.qual", + "org.checkerframework.common.value.qual", + "org.checkerframework.dataflow.qual", + "org.checkerframework.framework.qual" + ], + "org.jetbrains.kotlin:kotlin-metadata-jvm": [ + "kotlin.metadata", + "kotlin.metadata.internal", + "kotlin.metadata.internal.common", + "kotlin.metadata.internal.extensions", + "kotlin.metadata.internal.metadata", + "kotlin.metadata.internal.metadata.builtins", + "kotlin.metadata.internal.metadata.deserialization", + "kotlin.metadata.internal.metadata.jvm", + "kotlin.metadata.internal.metadata.jvm.deserialization", + "kotlin.metadata.internal.metadata.jvm.serialization", + "kotlin.metadata.internal.metadata.serialization", + "kotlin.metadata.internal.protobuf", + "kotlin.metadata.jvm", + "kotlin.metadata.jvm.internal" + ], + "org.jetbrains.kotlin:kotlin-reflect": [ + "kotlin.reflect.full", + "kotlin.reflect.jvm", + "kotlin.reflect.jvm.internal", + "kotlin.reflect.jvm.internal.calls", + "kotlin.reflect.jvm.internal.impl", + "kotlin.reflect.jvm.internal.impl.builtins", + "kotlin.reflect.jvm.internal.impl.builtins.functions", + "kotlin.reflect.jvm.internal.impl.builtins.jvm", + "kotlin.reflect.jvm.internal.impl.descriptors", + "kotlin.reflect.jvm.internal.impl.descriptors.annotations", + "kotlin.reflect.jvm.internal.impl.descriptors.deserialization", + "kotlin.reflect.jvm.internal.impl.descriptors.impl", + "kotlin.reflect.jvm.internal.impl.descriptors.java", + "kotlin.reflect.jvm.internal.impl.descriptors.runtime.components", + "kotlin.reflect.jvm.internal.impl.descriptors.runtime.structure", + "kotlin.reflect.jvm.internal.impl.incremental", + "kotlin.reflect.jvm.internal.impl.incremental.components", + "kotlin.reflect.jvm.internal.impl.load.java", + "kotlin.reflect.jvm.internal.impl.load.java.components", + "kotlin.reflect.jvm.internal.impl.load.java.descriptors", + "kotlin.reflect.jvm.internal.impl.load.java.lazy", + "kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors", + "kotlin.reflect.jvm.internal.impl.load.java.lazy.types", + "kotlin.reflect.jvm.internal.impl.load.java.sources", + "kotlin.reflect.jvm.internal.impl.load.java.structure", + "kotlin.reflect.jvm.internal.impl.load.java.typeEnhancement", + "kotlin.reflect.jvm.internal.impl.load.kotlin", + "kotlin.reflect.jvm.internal.impl.load.kotlin.header", + "kotlin.reflect.jvm.internal.impl.metadata", + "kotlin.reflect.jvm.internal.impl.metadata.builtins", + "kotlin.reflect.jvm.internal.impl.metadata.deserialization", + "kotlin.reflect.jvm.internal.impl.metadata.jvm", + "kotlin.reflect.jvm.internal.impl.metadata.jvm.deserialization", + "kotlin.reflect.jvm.internal.impl.name", + "kotlin.reflect.jvm.internal.impl.platform", + "kotlin.reflect.jvm.internal.impl.protobuf", + "kotlin.reflect.jvm.internal.impl.renderer", + "kotlin.reflect.jvm.internal.impl.resolve", + "kotlin.reflect.jvm.internal.impl.resolve.calls.inference", + "kotlin.reflect.jvm.internal.impl.resolve.constants", + "kotlin.reflect.jvm.internal.impl.resolve.deprecation", + "kotlin.reflect.jvm.internal.impl.resolve.descriptorUtil", + "kotlin.reflect.jvm.internal.impl.resolve.jvm", + "kotlin.reflect.jvm.internal.impl.resolve.sam", + "kotlin.reflect.jvm.internal.impl.resolve.scopes", + "kotlin.reflect.jvm.internal.impl.resolve.scopes.receivers", + "kotlin.reflect.jvm.internal.impl.serialization", + "kotlin.reflect.jvm.internal.impl.serialization.deserialization", + "kotlin.reflect.jvm.internal.impl.serialization.deserialization.builtins", + "kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors", + "kotlin.reflect.jvm.internal.impl.storage", + "kotlin.reflect.jvm.internal.impl.types", + "kotlin.reflect.jvm.internal.impl.types.checker", + "kotlin.reflect.jvm.internal.impl.types.error", + "kotlin.reflect.jvm.internal.impl.types.model", + "kotlin.reflect.jvm.internal.impl.types.typeUtil", + "kotlin.reflect.jvm.internal.impl.types.typesApproximation", + "kotlin.reflect.jvm.internal.impl.util", + "kotlin.reflect.jvm.internal.impl.util.capitalizeDecapitalize", + "kotlin.reflect.jvm.internal.impl.util.collectionUtils", + "kotlin.reflect.jvm.internal.impl.utils", + "kotlin.reflect.jvm.internal.pcollections" + ], + "org.jetbrains.kotlin:kotlin-stdlib": [ + "kotlin", + "kotlin.annotation", + "kotlin.collections", + "kotlin.collections.builders", + "kotlin.collections.jdk8", + "kotlin.collections.unsigned", + "kotlin.comparisons", + "kotlin.concurrent", + "kotlin.concurrent.atomics", + "kotlin.concurrent.internal", + "kotlin.contracts", + "kotlin.coroutines", + "kotlin.coroutines.cancellation", + "kotlin.coroutines.intrinsics", + "kotlin.coroutines.jvm.internal", + "kotlin.enums", + "kotlin.experimental", + "kotlin.internal", + "kotlin.internal.jdk7", + "kotlin.internal.jdk8", + "kotlin.io", + "kotlin.io.encoding", + "kotlin.io.path", + "kotlin.jdk7", + "kotlin.js", + "kotlin.jvm", + "kotlin.jvm.functions", + "kotlin.jvm.internal", + "kotlin.jvm.internal.markers", + "kotlin.jvm.internal.unsafe", + "kotlin.jvm.jdk8", + "kotlin.jvm.optionals", + "kotlin.math", + "kotlin.properties", + "kotlin.random", + "kotlin.random.jdk8", + "kotlin.ranges", + "kotlin.reflect", + "kotlin.sequences", + "kotlin.streams.jdk8", + "kotlin.system", + "kotlin.text", + "kotlin.text.jdk8", + "kotlin.time", + "kotlin.time.jdk8", + "kotlin.uuid" + ], + "org.jetbrains.kotlin:kotlin-stdlib-jdk7": [ + "kotlin.internal.jdk7", + "kotlin.io.path", + "kotlin.jdk7" + ], + "org.jetbrains.kotlin:kotlin-stdlib-jdk8": [ + "kotlin.collections.jdk8", + "kotlin.internal.jdk8", + "kotlin.jvm.jdk8", + "kotlin.random.jdk8", + "kotlin.streams.jdk8", + "kotlin.text.jdk8", + "kotlin.time.jdk8" + ], + "org.jetbrains:annotations": [ + "org.intellij.lang.annotations", + "org.jetbrains.annotations" + ], + "org.jspecify:jspecify": [ + "org.jspecify.annotations" + ] + }, + "repositories": { + "https://repo1.maven.org/maven2/": [ + "com.google.code.findbugs:jsr305", + "com.google.dagger:dagger", + "com.google.dagger:dagger-compiler", + "com.google.dagger:dagger-producers", + "com.google.dagger:dagger-spi", + "com.google.devtools.ksp:symbol-processing-api", + "com.google.errorprone:error_prone_annotations", + "com.google.googlejavaformat:google-java-format", + "com.google.guava:failureaccess", + "com.google.guava:guava", + "com.google.guava:listenablefuture", + "com.google.j2objc:j2objc-annotations", + "com.squareup:javapoet", + "com.squareup:kotlinpoet", + "jakarta.inject:jakarta.inject-api", + "javax.inject:javax.inject", + "net.ltgt.gradle.incap:incap", + "org.checkerframework:checker-compat-qual", + "org.checkerframework:checker-qual", + "org.jetbrains.kotlin:kotlin-metadata-jvm", + "org.jetbrains.kotlin:kotlin-reflect", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlin:kotlin-stdlib-jdk7", + "org.jetbrains.kotlin:kotlin-stdlib-jdk8", + "org.jetbrains:annotations", + "org.jspecify:jspecify" + ] + }, + "services": { + "com.google.dagger:dagger-compiler": { + "com.google.devtools.ksp.processing.SymbolProcessorProvider": [ + "dagger.internal.codegen.KspComponentProcessor$Provider" + ], + "javax.annotation.processing.Processor": [ + "dagger.internal.codegen.ComponentProcessor" + ] + }, + "com.google.googlejavaformat:google-java-format": { + "java.util.spi.ToolProvider": [ + "com.google.googlejavaformat.java.GoogleJavaFormatToolProvider" + ], + "javax.tools.Tool": [ + "com.google.googlejavaformat.java.GoogleJavaFormatTool" + ] + }, + "org.jetbrains.kotlin:kotlin-metadata-jvm": { + "kotlin.metadata.internal.extensions.MetadataExtensions": [ + "kotlin.metadata.jvm.internal.JvmMetadataExtensions" + ] + }, + "org.jetbrains.kotlin:kotlin-reflect": { + "kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoader": [ + "kotlin.reflect.jvm.internal.impl.serialization.deserialization.builtins.BuiltInsLoaderImpl" + ], + "kotlin.reflect.jvm.internal.impl.resolve.ExternalOverridabilityCondition": [ + "kotlin.reflect.jvm.internal.impl.load.java.ErasedOverridabilityCondition", + "kotlin.reflect.jvm.internal.impl.load.java.FieldOverridabilityCondition", + "kotlin.reflect.jvm.internal.impl.load.java.JavaIncompatibilityRulesOverridabilityCondition" + ] + } + }, + "version": "3" +} diff --git a/examples/associates_dagger/projects/service/api/BUILD.bazel b/examples/associates_dagger/projects/service/api/BUILD.bazel new file mode 100644 index 000000000..b333e035a --- /dev/null +++ b/examples/associates_dagger/projects/service/api/BUILD.bazel @@ -0,0 +1,8 @@ +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") + +package(default_visibility = ["//projects/service:__subpackages__"]) + +kt_jvm_library( + name = "api", + srcs = glob(["src/main/kotlin/**/*.kt"]), +) diff --git a/examples/associates_dagger/projects/service/api/src/main/kotlin/service/api/Greeter.kt b/examples/associates_dagger/projects/service/api/src/main/kotlin/service/api/Greeter.kt new file mode 100644 index 000000000..236d9937b --- /dev/null +++ b/examples/associates_dagger/projects/service/api/src/main/kotlin/service/api/Greeter.kt @@ -0,0 +1,5 @@ +package service.api + +interface Greeter { + fun greet(): String +} diff --git a/examples/associates_dagger/projects/service/api/src/main/kotlin/service/api/Logger.kt b/examples/associates_dagger/projects/service/api/src/main/kotlin/service/api/Logger.kt new file mode 100644 index 000000000..3c3b99abd --- /dev/null +++ b/examples/associates_dagger/projects/service/api/src/main/kotlin/service/api/Logger.kt @@ -0,0 +1,5 @@ +package service.api + +interface Logger { + fun log(message: String) +} diff --git a/examples/associates_dagger/projects/service/app/BUILD.bazel b/examples/associates_dagger/projects/service/app/BUILD.bazel new file mode 100644 index 000000000..fc59904a6 --- /dev/null +++ b/examples/associates_dagger/projects/service/app/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_java//java:defs.bzl", "java_binary") +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") + +kt_jvm_library( + name = "app", + srcs = glob(["src/main/kotlin/**/*.kt"]), + deps = [ + "//projects/service/api", + "//projects/service/di", + ], +) + +java_binary( + name = "service", + main_class = "service.app.MainKt", + visibility = ["//visibility:public"], + runtime_deps = [":app"], +) diff --git a/examples/associates_dagger/projects/service/app/src/main/kotlin/service/app/Main.kt b/examples/associates_dagger/projects/service/app/src/main/kotlin/service/app/Main.kt new file mode 100644 index 000000000..e9caf48fb --- /dev/null +++ b/examples/associates_dagger/projects/service/app/src/main/kotlin/service/app/Main.kt @@ -0,0 +1,9 @@ +package service.app + +import service.di.DaggerServiceComponent + +fun main() { + val component = DaggerServiceComponent.builder().build() + val greeting = component.greeter().greet() + println(greeting) +} diff --git a/examples/associates_dagger/projects/service/di/BUILD.bazel b/examples/associates_dagger/projects/service/di/BUILD.bazel new file mode 100644 index 000000000..3dfa715fa --- /dev/null +++ b/examples/associates_dagger/projects/service/di/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") + +kt_jvm_library( + name = "di", + srcs = glob(["src/main/kotlin/**/*.kt"]), + associates = [ + "//projects/service/impl", + ], + visibility = ["//projects/service:__subpackages__"], + deps = [ + "//third_party:dagger", + ], +) diff --git a/examples/associates_dagger/projects/service/di/src/main/kotlin/service/di/ServiceComponent.kt b/examples/associates_dagger/projects/service/di/src/main/kotlin/service/di/ServiceComponent.kt new file mode 100644 index 000000000..a0bb941c1 --- /dev/null +++ b/examples/associates_dagger/projects/service/di/src/main/kotlin/service/di/ServiceComponent.kt @@ -0,0 +1,11 @@ +package service.di + +import dagger.Component +import service.api.Greeter +import javax.inject.Singleton + +@Singleton +@Component(modules = [ServiceModule::class]) +interface ServiceComponent { + fun greeter(): Greeter +} diff --git a/examples/associates_dagger/projects/service/di/src/main/kotlin/service/di/ServiceModule.kt b/examples/associates_dagger/projects/service/di/src/main/kotlin/service/di/ServiceModule.kt new file mode 100644 index 000000000..89e0ac956 --- /dev/null +++ b/examples/associates_dagger/projects/service/di/src/main/kotlin/service/di/ServiceModule.kt @@ -0,0 +1,20 @@ +package service.di + +import dagger.Binds +import dagger.Module +import service.api.Greeter +import service.api.Logger +import service.impl.ConsoleLogger +import service.impl.DefaultGreeter +import javax.inject.Singleton + +@Module +internal abstract class ServiceModule { + @Binds + @Singleton + abstract fun bindLogger(impl: ConsoleLogger): Logger + + @Binds + @Singleton + abstract fun bindGreeter(impl: DefaultGreeter): Greeter +} diff --git a/examples/associates_dagger/projects/service/impl/BUILD.bazel b/examples/associates_dagger/projects/service/impl/BUILD.bazel new file mode 100644 index 000000000..374c2f588 --- /dev/null +++ b/examples/associates_dagger/projects/service/impl/BUILD.bazel @@ -0,0 +1,11 @@ +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") + +kt_jvm_library( + name = "impl", + srcs = glob(["src/main/kotlin/**/*.kt"]), + associates = ["//projects/service/api"], + visibility = ["//projects/service:__subpackages__"], + deps = [ + "@maven_rules_kotlin_example//:javax_inject_javax_inject", + ], +) diff --git a/examples/associates_dagger/projects/service/impl/src/main/kotlin/service/impl/ConsoleLogger.kt b/examples/associates_dagger/projects/service/impl/src/main/kotlin/service/impl/ConsoleLogger.kt new file mode 100644 index 000000000..186a4e436 --- /dev/null +++ b/examples/associates_dagger/projects/service/impl/src/main/kotlin/service/impl/ConsoleLogger.kt @@ -0,0 +1,10 @@ +package service.impl + +import service.api.Logger +import javax.inject.Inject + +internal class ConsoleLogger @Inject constructor() : Logger { + override fun log(message: String) { + println("[LOG] $message") + } +} diff --git a/examples/associates_dagger/projects/service/impl/src/main/kotlin/service/impl/DefaultGreeter.kt b/examples/associates_dagger/projects/service/impl/src/main/kotlin/service/impl/DefaultGreeter.kt new file mode 100644 index 000000000..ee9737990 --- /dev/null +++ b/examples/associates_dagger/projects/service/impl/src/main/kotlin/service/impl/DefaultGreeter.kt @@ -0,0 +1,15 @@ +package service.impl + +import service.api.Greeter +import service.api.Logger +import javax.inject.Inject + +internal class DefaultGreeter @Inject constructor( + private val logger: Logger, +) : Greeter { + override fun greet(): String { + val message = "Hello from DefaultGreeter!" + logger.log(message) + return message + } +} diff --git a/examples/associates_dagger/third_party/BUILD.bazel b/examples/associates_dagger/third_party/BUILD.bazel new file mode 100644 index 000000000..785b50aaf --- /dev/null +++ b/examples/associates_dagger/third_party/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_java//java:java_library.bzl", "java_library") +load("@rules_java//java:java_plugin.bzl", "java_plugin") + +java_plugin( + name = "dagger_component_plugin", + generates_api = True, + processor_class = "dagger.internal.codegen.ComponentProcessor", + visibility = ["//visibility:private"], + deps = [ + "@maven_rules_kotlin_example//:com_google_dagger_dagger_compiler", + ], +) + +java_library( + name = "dagger", + exported_plugins = [":dagger_component_plugin"], + visibility = ["//visibility:public"], + exports = [ + "@maven_rules_kotlin_example//:com_google_dagger_dagger", + "@maven_rules_kotlin_example//:javax_inject_javax_inject", + ], +) diff --git a/kotlin/internal/jvm/associates.bzl b/kotlin/internal/jvm/associates.bzl index 71f1c7f0d..57a20907f 100644 --- a/kotlin/internal/jvm/associates.bzl +++ b/kotlin/internal/jvm/associates.bzl @@ -29,19 +29,27 @@ def _collect_associates(ctx, toolchains, associate): """Collects the associate jars from the provided dependency and returns them as a depset. - There are three outcomes for this marco: - 1. When `experimental_remove_private_classes_in_abi_jars` is enabled and the tag override has not been provided, only the + There are four outcomes for this macro: + 1. When the associate provides an associates_abi_jar (generated by ExperimentalAssociatesAbiGen plugin), + that jar is used directly. It contains ABI classes with internal visibility preserved. + 2. When `experimental_remove_private_classes_in_abi_jars` is enabled and the tag override has not been provided, only the direct java_output CLASS jars will be collected for each associate target. Due to the stripping of internal and private symbols from the compile jar, class jar is the only one that will contain the internal symbols an associate has access to. - 2. When `experimental_strict_associate_dependencies` is enabled and the tag override has not been provided, only the + 3. When `experimental_strict_associate_dependencies` is enabled and the tag override has not been provided, only the direct java_output COMPILE jars will be collected for each associate target. - 3. When `experimental_strict_associate_dependencies` is disabled, the complete transitive set of compile jars will - be collected for each assoicate target. + 4. When `experimental_strict_associate_dependencies` is disabled, the complete transitive set of compile jars will + be collected for each associate target. """ jars_depset = None abi_jars_set = _sets.make() - if (not "kt_remove_private_classes_in_abi_plugin_incompatible" in ctx.attr.tags and - toolchains.kt.experimental_remove_private_classes_in_abi_jars): + + # Prefer the associates ABI jar when available — it's an ABI jar that preserves internal visibility + associates_abi_jar = associate[_KtJvmInfo].associates_abi_jar if _KtJvmInfo in associate and hasattr(associate[_KtJvmInfo], "associates_abi_jar") else None + if associates_abi_jar: + jars_depset = depset(direct = [associates_abi_jar]) + abi_jars_set = _sets.union(abi_jars_set, _sets.make([a.compile_jar for a in associate[JavaInfo].java_outputs])) + elif (not "kt_remove_private_classes_in_abi_plugin_incompatible" in ctx.attr.tags and + toolchains.kt.experimental_remove_private_classes_in_abi_jars): jars_depset = depset(direct = [a.class_jar for a in associate[JavaInfo].java_outputs]) abi_jars_set = _sets.union(abi_jars_set, _sets.make([a.compile_jar for a in associate[JavaInfo].java_outputs])) elif (toolchains.kt.experimental_strict_associate_dependencies and diff --git a/kotlin/internal/jvm/compile.bzl b/kotlin/internal/jvm/compile.bzl index b3182c2a6..cc39b3e90 100644 --- a/kotlin/internal/jvm/compile.bzl +++ b/kotlin/internal/jvm/compile.bzl @@ -767,6 +767,7 @@ def _kt_jvm_produce_output_jar_actions( output_jars = outputs_struct.output_jars generated_src_jars = outputs_struct.generated_src_jars annotation_processing = outputs_struct.annotation_processing + associates_abi_jar = outputs_struct.associates_abi_jar # If this rule has any resources declared setup a zipper action to turn them into a jar. if len(ctx.files.resources) + len(extra_resources) > 0: @@ -849,6 +850,7 @@ def _kt_jvm_produce_output_jar_actions( annotation_processing = annotation_processing, additional_generated_source_jars = generated_src_jars, all_output_jars = output_jars, + associates_abi_jar = associates_abi_jar, ), ) @@ -919,6 +921,7 @@ def _run_kt_java_builder_actions( java_infos = [] # Build Kotlin + kt_associates_abi_jar = None if has_kt_sources: kt_runtime_jar = ctx.actions.declare_file(ctx.label.name + "-kt.jar") if not "kt_abi_plugin_incompatible" in ctx.attr.tags and toolchains.kt.experimental_use_abi_jars == True: @@ -927,6 +930,11 @@ def _run_kt_java_builder_actions( "abi_jar": kt_compile_jar, "output": kt_runtime_jar, } + + # Produce associates ABI jar (preserves internal visibility) alongside the regular ABI jar + if not "kt_associates_abi_plugin_incompatible" in ctx.attr.tags and toolchains.kt.experimental_generate_associates_abi_jars == True: + kt_associates_abi_jar = ctx.actions.declare_file(ctx.label.name + "-kt.associates-abi.jar") + outputs["associates_abi_jar"] = kt_associates_abi_jar else: kt_compile_jar = kt_runtime_jar outputs = { @@ -987,12 +995,19 @@ def _run_kt_java_builder_actions( # annotation processors in `deps` also. if len(srcs.kt) > 0: javac_opts.append("-proc:none") + + # Add associate ABI jars so javac (and annotation processors like Dagger) + # can resolve internal types from associated modules. + associates_java_infos = [ + JavaInfo(compile_jar = jar, output_jar = jar, neverlink = True) + for jar in compile_deps.associate_jars.to_list() + ] java_info = java_common.compile( ctx, source_files = srcs.java, source_jars = generated_kapt_src_jars + srcs.src_jars + generated_ksp_src_jars, output = ctx.actions.declare_file(ctx.label.name + "-java.jar"), - deps = compile_deps.deps + kt_stubs_for_java + [p[JavaInfo] for p in ctx.attr.plugins if JavaInfo in p], + deps = associates_java_infos + compile_deps.deps + kt_stubs_for_java + [p[JavaInfo] for p in ctx.attr.plugins if JavaInfo in p], java_toolchain = toolchains.java, plugins = _plugin_mappers.targets_to_annotation_processors_java_plugin_info(ctx.attr.plugins), javac_opts = javac_opts, @@ -1057,6 +1072,7 @@ def _run_kt_java_builder_actions( output_jars = output_jars, generated_src_jars = generated_kapt_src_jars + generated_ksp_src_jars, annotation_processing = annotation_processing, + associates_abi_jar = kt_associates_abi_jar, ) def _create_annotation_processing(annotation_processors, ap_class_jar, ap_source_jar): diff --git a/kotlin/internal/toolchains.bzl b/kotlin/internal/toolchains.bzl index bda1452ec..a2bc260e6 100644 --- a/kotlin/internal/toolchains.bzl +++ b/kotlin/internal/toolchains.bzl @@ -86,6 +86,7 @@ def _kotlin_toolchain_impl(ctx): experimental_use_abi_jars = ctx.attr.experimental_use_abi_jars, experimental_treat_internal_as_private_in_abi_jars = ctx.attr.experimental_treat_internal_as_private_in_abi_jars, experimental_remove_private_classes_in_abi_jars = ctx.attr.experimental_remove_private_classes_in_abi_jars, + experimental_generate_associates_abi_jars = ctx.attr.experimental_generate_associates_abi_jars, experimental_remove_debug_info_in_abi_jars = ctx.attr.experimental_remove_debug_info_in_abi_jars, experimental_strict_kotlin_deps = ctx.attr.experimental_strict_kotlin_deps, experimental_report_unused_deps = ctx.attr.experimental_report_unused_deps, @@ -138,6 +139,14 @@ _kt_toolchain = rule( doc = "Enables experimental support for Build Tools API integration", default = False, ), + "experimental_generate_associates_abi_jars": attr.bool( + doc = """Generate separate ABI jars for associates that preserve internal visibility. + When enabled, associate dependencies use these jars instead of full class jars, + improving build cache hit rates while maintaining access to internal symbols. + Can be disabled for an individual target using the tag. + `kt_associates_abi_plugin_incompatible`""", + default = False, + ), "experimental_multiplex_workers": attr.bool( doc = """Run workers in multiplex mode.""", default = False, @@ -349,6 +358,7 @@ def define_kt_toolchain( experimental_use_abi_jars = False, experimental_treat_internal_as_private_in_abi_jars = False, experimental_remove_private_classes_in_abi_jars = False, + experimental_generate_associates_abi_jars = False, experimental_remove_debug_info_in_abi_jars = False, experimental_strict_kotlin_deps = None, experimental_report_unused_deps = None, @@ -379,6 +389,7 @@ def define_kt_toolchain( }), experimental_treat_internal_as_private_in_abi_jars = experimental_treat_internal_as_private_in_abi_jars, experimental_remove_private_classes_in_abi_jars = experimental_remove_private_classes_in_abi_jars, + experimental_generate_associates_abi_jars = experimental_generate_associates_abi_jars, experimental_remove_debug_info_in_abi_jars = experimental_remove_debug_info_in_abi_jars, experimental_multiplex_workers = experimental_multiplex_workers, experimental_strict_kotlin_deps = experimental_strict_kotlin_deps, diff --git a/src/main/kotlin/BUILD b/src/main/kotlin/BUILD index d532ad4e4..8d03ffd06 100644 --- a/src/main/kotlin/BUILD +++ b/src/main/kotlin/BUILD @@ -20,6 +20,13 @@ jar_jar( visibility = ["//visibility:public"], ) +jar_jar( + name = "associates-abi-gen", + input_jar = "//src/main/kotlin/io/bazel/kotlin/plugin/associates:associates-abi-gen_deploy.jar", + rules = "shade.jarjar", + visibility = ["//visibility:public"], +) + alias( name = "build", actual = "//src/main/kotlin/io/bazel/kotlin/builder/cmd:build", @@ -47,6 +54,7 @@ alias( release_archive( name = "pkg", srcs = [ + ":associates-abi-gen.jar", ":jdeps-gen.jar", ":skip-code-gen.jar", ], diff --git a/src/main/kotlin/BUILD.release.bazel b/src/main/kotlin/BUILD.release.bazel index 00d75a9ca..bbad9a09d 100644 --- a/src/main/kotlin/BUILD.release.bazel +++ b/src/main/kotlin/BUILD.release.bazel @@ -46,9 +46,15 @@ java_import( jars = ["jdeps-gen.jar"], ) +java_import( + name = "associates-abi-gen", + jars = ["associates-abi-gen.jar"], +) + java_binary( name = "build", data = [ + ":associates-abi-gen", ":jdeps-gen", ":skip-code-gen", "//kotlin/compiler:jvm-abi-gen", @@ -70,6 +76,7 @@ java_binary( "-D@com_github_jetbrains_kotlin...jvm-abi-gen=$(rlocationpath //kotlin/compiler:jvm-abi-gen)", "-D@com_github_jetbrains_kotlin...kotlin-compiler=$(rlocationpath //kotlin/compiler:kotlin-compiler)", "-D@com_github_jetbrains_kotlin...kapt=$(rlocationpath //kotlin/compiler:kotlin-annotation-processing)", + "-D@rules_kotlin...associates-abi-gen=$(rlocationpath //src/main/kotlin:associates-abi-gen)", "-D@rules_kotlin...jdeps-gen=$(rlocationpath //src/main/kotlin:jdeps-gen)", "-D@rules_kotlin...skip-code-gen=$(rlocationpath //src/main/kotlin:skip-code-gen)", "-D@rules_kotlin...compiler=$(rlocationpath //src/main/kotlin/io/bazel/kotlin/compiler)", diff --git a/src/main/kotlin/io/bazel/kotlin/builder/cmd/BUILD.bazel b/src/main/kotlin/io/bazel/kotlin/builder/cmd/BUILD.bazel index f167ae561..3da95741f 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/cmd/BUILD.bazel +++ b/src/main/kotlin/io/bazel/kotlin/builder/cmd/BUILD.bazel @@ -18,6 +18,7 @@ kt_bootstrap_binary( "//kotlin/compiler:jvm-abi-gen", "//kotlin/compiler:kotlin-annotation-processing", "//kotlin/compiler:kotlin-compiler", + "//src/main/kotlin:associates-abi-gen", "//src/main/kotlin:jdeps-gen", "//src/main/kotlin:skip-code-gen", "//src/main/kotlin/io/bazel/kotlin/compiler:compiler.jar", @@ -36,6 +37,7 @@ kt_bootstrap_binary( "-D@com_github_jetbrains_kotlin...jvm-abi-gen=$(rlocationpath //kotlin/compiler:jvm-abi-gen)", "-D@com_github_jetbrains_kotlin...kotlin-compiler=$(rlocationpath //kotlin/compiler:kotlin-compiler)", "-D@com_github_jetbrains_kotlin...kapt=$(rlocationpath //kotlin/compiler:kotlin-annotation-processing)", + "-D@rules_kotlin...associates-abi-gen=$(rlocationpath //src/main/kotlin:associates-abi-gen)", "-D@rules_kotlin...jdeps-gen=$(rlocationpath //src/main/kotlin:jdeps-gen)", "-D@rules_kotlin...skip-code-gen=$(rlocationpath //src/main/kotlin:skip-code-gen)", "-D@rules_kotlin...compiler=$(rlocationpath //src/main/kotlin/io/bazel/kotlin/compiler:compiler.jar)", diff --git a/src/main/kotlin/io/bazel/kotlin/builder/cmd/Build.kt b/src/main/kotlin/io/bazel/kotlin/builder/cmd/Build.kt index ab20e8658..0d2754ef5 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/cmd/Build.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/cmd/Build.kt @@ -37,6 +37,7 @@ object Build { toolchain.skipCodeGen, toolchain.kapt3Plugin, toolchain.jdepsGen, + toolchain.associatesAbiGen, ) val compilerBuilder = KotlinToolchain.KotlincInvokerBuilder(toolchain) val jvmTaskExecutor = KotlinJvmTaskExecutor(compilerBuilder, plugins) 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 55d3e6e02..f46eba095 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt @@ -83,6 +83,7 @@ class KotlinBuilder( REDUCED_CLASSPATH_MODE("--reduced_classpath_mode"), INSTRUMENT_COVERAGE("--instrument_coverage"), BUILD_TOOLS_API("--build_tools_api"), + ASSOCIATES_ABI_JAR("--associates_abi_jar"), } } @@ -211,6 +212,7 @@ class KotlinBuilder( generatedJavaStubJar = this } argMap.optionalSingle(KotlinBuilderFlags.ABI_JAR)?.let { abijar = it } + argMap.optionalSingle(KotlinBuilderFlags.ASSOCIATES_ABI_JAR)?.let { associatesAbiJar = it } argMap.optionalSingle(KotlinBuilderFlags.GENERATED_CLASS_JAR)?.let { generatedClassJar = it } @@ -232,6 +234,13 @@ class KotlinBuilder( getOutputDirPath(moduleName, "abi_classes"), ).toString() } + if (argMap.hasAll(KotlinBuilderFlags.ASSOCIATES_ABI_JAR)) { + associatesAbiClasses = + workingDir + .resolveNewDirectories( + getOutputDirPath(moduleName, "associates_abi_classes"), + ).toString() + } generatedClasses = workingDir .resolveNewDirectories(getOutputDirPath(moduleName, "generated_classes")) 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 87fd7a8e0..0399065fd 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 @@ -288,6 +288,21 @@ internal fun JvmCompilationTask.createAbiJar() = it.execute() } +/** + * Produce the associates ABI jar (with internal visibility preserved). + */ +internal fun JvmCompilationTask.createAssociatesAbiJar() = + JarCreator( + path = Paths.get(outputs.associatesAbiJar), + normalize = true, + verbose = false, + ).also { + it.addDirectory(Paths.get(directories.associatesAbiClasses)) + it.addDirectory(Paths.get(directories.generatedClasses)) + it.setJarOwner(info.label, info.bazelRuleKind) + it.execute() + } + /** * Produce a jar of sources generated by KAPT. */ diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/InternalCompilerPlugins.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/InternalCompilerPlugins.kt index 6dccca731..f63dada1d 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/InternalCompilerPlugins.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/InternalCompilerPlugins.kt @@ -24,4 +24,5 @@ class InternalCompilerPlugins constructor( val skipCodeGen: KotlinToolchain.CompilerPlugin, val kapt: KotlinToolchain.CompilerPlugin, val jdeps: KotlinToolchain.CompilerPlugin, + val associatesAbiGen: KotlinToolchain.CompilerPlugin, ) diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt index 32b8260d0..d6538a098 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt @@ -100,6 +100,14 @@ class KotlinJvmTaskExecutor( given(outputs.jar).empty { plugin(plugins.skipCodeGen) } + }.given(outputs.associatesAbiJar) + .notEmpty { + plugin(plugins.associatesAbiGen) { + flag("outputDir", directories.associatesAbiClasses) + if (info.removeDebugInfo) { + flag("removeDebugInfo", "true") + } + } }, printOnFail = false, ) @@ -136,6 +144,9 @@ class KotlinJvmTaskExecutor( if (outputs.abijar.isNotEmpty()) { context.execute("create abi jar", ::createAbiJar) } + if (outputs.associatesAbiJar.isNotEmpty()) { + context.execute("create associates abi jar", ::createAssociatesAbiJar) + } if (outputs.generatedJavaSrcJar.isNotEmpty()) { context.execute("creating KAPT generated Java source jar", ::createGeneratedJavaSrcJar) } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt index d8ae3fcca..9d5787e02 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt @@ -29,6 +29,7 @@ class KotlinToolchain private constructor( val jvmAbiGen: CompilerPlugin, val skipCodeGen: CompilerPlugin, val jdepsGen: CompilerPlugin, + val associatesAbiGen: CompilerPlugin, ) { companion object { private val JVM_ABI_PLUGIN by lazy { @@ -66,6 +67,13 @@ class KotlinToolchain private constructor( ).toPath() } + private val ASSOCIATES_ABI_GEN_PLUGIN by lazy { + BazelRunFiles + .resolveVerifiedFromProperty( + "@rules_kotlin...associates-abi-gen", + ).toPath() + } + private val KOTLINC by lazy { BazelRunFiles .resolveVerifiedFromProperty( @@ -116,6 +124,7 @@ class KotlinToolchain private constructor( KOTLINX_SERIALIZATION_CORE_JVM.toFile(), KOTLINX_SERIALIZATION_JSON.toFile(), KOTLINX_SERIALIZATION_JSON_JVM.toFile(), + ASSOCIATES_ABI_GEN_PLUGIN.verified().absoluteFile, ) @JvmStatic @@ -130,6 +139,7 @@ class KotlinToolchain private constructor( kotlinxSerializationCoreJvm: File, kotlinxSerializationJson: File, kotlinxSerializationJsonJvm: File, + associatesAbiGenFile: File, ): KotlinToolchain = KotlinToolchain( listOf( @@ -139,6 +149,7 @@ class KotlinToolchain private constructor( jvmAbiGenFile, skipCodeGenFile, jdepsGenFile, + associatesAbiGenFile, kotlinxSerializationCoreJvm, kotlinxSerializationJson, kotlinxSerializationJsonJvm, @@ -163,6 +174,11 @@ class KotlinToolchain private constructor( kaptFile.path, "org.jetbrains.kotlin.kapt3", ), + associatesAbiGen = + CompilerPlugin( + associatesAbiGenFile.path, + "io.bazel.kotlin.plugin.ExperimentalAssociatesAbiGen", + ), ) } diff --git a/src/main/kotlin/io/bazel/kotlin/plugin/associates/BUILD.bazel b/src/main/kotlin/io/bazel/kotlin/plugin/associates/BUILD.bazel new file mode 100644 index 000000000..29b40f357 --- /dev/null +++ b/src/main/kotlin/io/bazel/kotlin/plugin/associates/BUILD.bazel @@ -0,0 +1,47 @@ +# Copyright 2024 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_java//java:defs.bzl", "java_binary") +load("//kotlin/internal/utils:generate_jvm_service.bzl", "generate_jvm_service") +load("//src/main/kotlin:bootstrap.bzl", "kt_bootstrap_library") + +# The compiler binary, this is co-located in the kotlin compiler classloader. +kt_bootstrap_library( + name = "associates-abi-gen-lib", + srcs = glob(["*.kt"]), + visibility = ["//src:__subpackages__"], + deps = [ + "//kotlin/compiler:jvm-abi-gen", + "//kotlin/compiler:kotlin-compiler", + ], +) + +# services to integrate with the plugin. +generate_jvm_service( + name = "associates-abi-gen-services", + services = { + "io.bazel.kotlin.plugin.associates.ExperimentalAssociatesAbiGenCommandLineProcessor": "org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor", + "io.bazel.kotlin.plugin.associates.ExperimentalAssociatesAbiGenRegistrar": "org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar", + }, +) + +# The plugin binary. +java_binary( + name = "associates-abi-gen", + visibility = ["//src:__subpackages__"], + runtime_deps = [ + ":associates-abi-gen-lib", + ":associates-abi-gen-services", + ], +) diff --git a/src/main/kotlin/io/bazel/kotlin/plugin/associates/ExperimentalAssociatesAbiGen.kt b/src/main/kotlin/io/bazel/kotlin/plugin/associates/ExperimentalAssociatesAbiGen.kt new file mode 100644 index 000000000..f9e924f4e --- /dev/null +++ b/src/main/kotlin/io/bazel/kotlin/plugin/associates/ExperimentalAssociatesAbiGen.kt @@ -0,0 +1,178 @@ +/* + * Copyright 2024 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. + * + */ +package io.bazel.kotlin.plugin.associates + +import org.jetbrains.kotlin.compiler.plugin.AbstractCliOption +import org.jetbrains.kotlin.compiler.plugin.CliOption +import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException +import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor +import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar +import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.CompilerConfigurationKey +import org.jetbrains.kotlin.jvm.abi.JvmAbiComponentRegistrar +import org.jetbrains.kotlin.jvm.abi.JvmAbiConfigurationKeys + +@OptIn(ExperimentalCompilerApi::class) +class ExperimentalAssociatesAbiGenCommandLineProcessor : CommandLineProcessor { + companion object { + const val COMPILER_PLUGIN_ID = + "io.bazel.kotlin.plugin.ExperimentalAssociatesAbiGen" + + val OUTPUT_DIR = + CompilerConfigurationKey( + "associates abi output directory", + ) + val REMOVE_DEBUG_INFO = + CompilerConfigurationKey( + "associates abi remove debug info", + ) + val PRESERVE_DECLARATION_ORDER = + CompilerConfigurationKey( + "associates abi preserve declaration order", + ) + val REMOVE_DATA_CLASS_COPY_IF_CONSTRUCTOR_IS_PRIVATE = + CompilerConfigurationKey( + "associates abi remove data class copy if constructor is private", + ) + + val OUTPUT_DIR_OPTION = + CliOption( + "outputDir", + "", + "Output directory for associates ABI classes", + required = true, + ) + val REMOVE_DEBUG_INFO_OPTION = + CliOption( + "removeDebugInfo", + "", + "Remove debug info", + required = false, + ) + val PRESERVE_DECLARATION_ORDER_OPTION = + CliOption( + "preserveDeclarationOrder", + "", + "Preserve declaration order", + required = false, + ) + val REMOVE_DATA_CLASS_COPY_IF_CONSTRUCTOR_IS_PRIVATE_OPTION = + CliOption( + "removeDataClassCopyIfConstructorIsPrivate", + "", + "Remove data class copy if constructor is private", + required = false, + ) + } + + override val pluginId: String = COMPILER_PLUGIN_ID + + override val pluginOptions: Collection = + listOf( + OUTPUT_DIR_OPTION, + REMOVE_DEBUG_INFO_OPTION, + PRESERVE_DECLARATION_ORDER_OPTION, + REMOVE_DATA_CLASS_COPY_IF_CONSTRUCTOR_IS_PRIVATE_OPTION, + ) + + override fun processOption( + option: AbstractCliOption, + value: String, + configuration: CompilerConfiguration, + ) { + when (option) { + OUTPUT_DIR_OPTION -> + configuration.put(OUTPUT_DIR, value) + REMOVE_DEBUG_INFO_OPTION -> + configuration.put(REMOVE_DEBUG_INFO, value == "true") + PRESERVE_DECLARATION_ORDER_OPTION -> + configuration.put( + PRESERVE_DECLARATION_ORDER, + value == "true", + ) + REMOVE_DATA_CLASS_COPY_IF_CONSTRUCTOR_IS_PRIVATE_OPTION -> + configuration.put( + REMOVE_DATA_CLASS_COPY_IF_CONSTRUCTOR_IS_PRIVATE, + value == "true", + ) + else -> + throw CliOptionProcessingException( + "Unknown option: ${option.optionName}", + ) + } + } +} + +@OptIn(ExperimentalCompilerApi::class) +class ExperimentalAssociatesAbiGenRegistrar : CompilerPluginRegistrar() { + override val pluginId: String = + ExperimentalAssociatesAbiGenCommandLineProcessor.COMPILER_PLUGIN_ID + + override val supportsK2: Boolean = true + + override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) { + val outputDir = + configuration.get( + ExperimentalAssociatesAbiGenCommandLineProcessor.OUTPUT_DIR, + ) ?: return + + // Build a configuration with the keys + // JvmAbiComponentRegistrar expects, hardcoding + // removePrivateClasses=true and treatInternalAsPrivate=false + // so that the associates ABI jar preserves internal visibility. + val abiConfig = CompilerConfiguration() + abiConfig.put( + JvmAbiConfigurationKeys.OUTPUT_PATH, + outputDir, + ) + abiConfig.put( + JvmAbiConfigurationKeys.REMOVE_PRIVATE_CLASSES, + true, + ) + abiConfig.put( + JvmAbiConfigurationKeys.TREAT_INTERNAL_AS_PRIVATE, + false, + ) + abiConfig.put( + JvmAbiConfigurationKeys.REMOVE_DEBUG_INFO, + configuration.get( + ExperimentalAssociatesAbiGenCommandLineProcessor + .REMOVE_DEBUG_INFO, + ) ?: false, + ) + abiConfig.put( + JvmAbiConfigurationKeys.PRESERVE_DECLARATION_ORDER, + configuration.get( + ExperimentalAssociatesAbiGenCommandLineProcessor + .PRESERVE_DECLARATION_ORDER, + ) ?: false, + ) + abiConfig.put( + JvmAbiConfigurationKeys + .REMOVE_DATA_CLASS_COPY_IF_CONSTRUCTOR_IS_PRIVATE, + configuration.get( + ExperimentalAssociatesAbiGenCommandLineProcessor + .REMOVE_DATA_CLASS_COPY_IF_CONSTRUCTOR_IS_PRIVATE, + ) ?: false, + ) + + with(JvmAbiComponentRegistrar()) { + registerExtensions(abiConfig) + } + } +} diff --git a/src/main/protobuf/kotlin_model.proto b/src/main/protobuf/kotlin_model.proto index 781292e75..040d7059e 100644 --- a/src/main/protobuf/kotlin_model.proto +++ b/src/main/protobuf/kotlin_model.proto @@ -112,6 +112,8 @@ message JvmCompilationTask { string java_classes = 8; // The destination directory for code coverage metadata. string coverage_metadata_classes = 9; + // The destination directory for associates ABI classes. + string associates_abi_classes = 10; } // Outputs produced by the builder. @@ -133,6 +135,8 @@ message JvmCompilationTask { string generated_ksp_src_jar = 8; // The path to the jar containing the generated KSP classes string generated_ksp_classes_jar = 9; + // The path to the associates ABI jar. + string associates_abi_jar = 10; } message Inputs { diff --git a/src/main/starlark/core/compile/common.bzl b/src/main/starlark/core/compile/common.bzl index 795fd80c3..4973c48c0 100644 --- a/src/main/starlark/core/compile/common.bzl +++ b/src/main/starlark/core/compile/common.bzl @@ -45,6 +45,7 @@ KtJvmInfo = provider( "additional_generated_source_jars": "Returns additional Jars containing generated source files from kapt, ksp, etc. [bazel-bsp-aspect]", "all_output_jars": "Returns all the output Jars produced by this rule. [bazel-bsp-aspect]", "annotation_processing": "Generated annotation processing jars. [intellij-aspect]", + "associates_abi_jar": "ABI jar that preserves internal visibility for associates.", "exported_compiler_plugins": "compiler plugins to be invoked by targets depending on this.", "language_version": "version of kotlin used. [intellij-aspect]", "module_jars": "Jars comprising the module (logical compilation unit), a.k.a. associates", diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java index 7e494fb3c..6ef6c1542 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java @@ -237,7 +237,8 @@ static KotlinToolchain toolchainForTest() { new File(Deps.Dep.fromLabel("//kotlin/compiler:kotlin-annotation-processing").singleCompileJar()), new File(Deps.Dep.fromLabel("@kotlinx_serialization_core_jvm//file").singleCompileJar()), new File(Deps.Dep.fromLabel("@kotlinx_serialization_json//file").singleCompileJar()), - new File(Deps.Dep.fromLabel("@kotlinx_serialization_json_jvm//file").singleCompileJar()) + new File(Deps.Dep.fromLabel("@kotlinx_serialization_json_jvm//file").singleCompileJar()), + new File(Deps.Dep.fromLabel("//src/main/kotlin:associates-abi-gen").singleCompileJar()) ); } } diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java index 08f91bf02..d7d5acddc 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java +++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java @@ -102,7 +102,8 @@ private static KotlinJvmTaskExecutor jvmTaskExecutor() { toolchain.getJvmAbiGen(), toolchain.getSkipCodeGen(), toolchain.getKapt3Plugin(), - toolchain.getJdepsGen() + toolchain.getJdepsGen(), + toolchain.getAssociatesAbiGen() ); KotlinToolchain.KotlincInvokerBuilder compilerBuilder = new KotlinToolchain.KotlincInvokerBuilder(toolchain); diff --git a/src/test/kotlin/io/bazel/kotlin/defs.bzl b/src/test/kotlin/io/bazel/kotlin/defs.bzl index 030032959..35a8cc50d 100644 --- a/src/test/kotlin/io/bazel/kotlin/defs.bzl +++ b/src/test/kotlin/io/bazel/kotlin/defs.bzl @@ -32,6 +32,7 @@ def kt_rules_test(name, **kwargs): args["deps"] = args.setdefault("deps", []) + ["//src/test/kotlin/io/bazel/kotlin/builder:test_lib"] for dep in [ "//src/main/kotlin/io/bazel/kotlin/compiler:compiler.jar", + "//src/main/kotlin:associates-abi-gen", "//src/main/kotlin:skip-code-gen", "//src/main/kotlin:jdeps-gen", "//kotlin/compiler:annotations",