rules_kotlin icon indicating copy to clipboard operation
rules_kotlin copied to clipboard

Android rules not working properly with exported Java plugins

Open Kernald opened this issue 3 years ago • 20 comments

Following Dagger's recommended Hilt integration, when using this android_library target with the following Java class, the code generation runs fine:

android_library(
    name = "app",
    srcs = ["SampleApplication.java"],
    manifest = "AndroidManifest.xml",
    deps = [
        ":res",
        "//third_party/dagger/hilt:hilt-android",
    ],
)
package fr.enoent.android.sample;

import android.app.Application;
import dagger.hilt.android.HiltAndroidApp;

@HiltAndroidApp(Application.class)
public class SampleApplication extends Sample_BurgApplication {
}

The exact same set-up with a kt_android_library, however, doesn't end up calling the plugins exported by //third_party/dagger/hilt:hilt-android at all. Even when only passing the same Java file to kt_android_library - the compilation fails because the generated superclass isn't generated.

From there, I tried passing the plugins explicitly to the kt_android_library's plugins attribute. With a Java file, they don't seem to run at all either (maybe expected?). With a Kotlin file, some seem to run, but either not all or not in the correct order, I'm really not familiar enough with annotation processors to understand what's going on there - one of the Hilt plugins fails because the superclass hasn't been generated.

I'm not sure how much of that is working as intended, but it's a strong behavioural difference from the native android_library (and I believe kt_jvm_library as well?).

Kernald avatar Mar 30 '21 00:03 Kernald

Btw, I noticed, if kt_android_library has //:dagger dependency all corresponding _Factorys are generated. dagger target is java_library, while //:hilt-android is android_library.

geaden avatar Jun 17 '21 19:06 geaden

It seems one can lose android_library.exported_plugins in:

https://github.com/bazelbuild/rules_kotlin/blob/b637ddf908ca276dcfb28f02f9bd03dcb3d87238/kotlin/internal/jvm/plugins.bzl#L78

So, I changed the line to:

elif ctx.rule.kind in ["java_library", "android_library"]:

Now I started to get compilation errors from Hilt:

error: [Hilt]
public final class MyApplication {
             ^
  @HiltAndroidApp class expected to extend Hilt_MyApplication. Found: Object

But with no luck to resolve them yet. Looks like code generation still not working.

geaden avatar Jun 19 '21 12:06 geaden

I've come upon the same issue when using dagger_android_rules. These also wrap a java_plugin in android_library, but unlike with Hilt there is only one processor class.

As @geaden wrote plugins.bzl quite clearly doesn't handle android_library rules. I was able to reproduce the issue here and make the tests pass again with the proposed fix. Not sure why Hilt is still failing, it might be a separate issue.

lukaciko avatar Jun 24 '21 09:06 lukaciko

Here is a demo app to demonstrate that hilt annotation processors are not running.

geaden avatar Jun 24 '21 19:06 geaden

@Kernald,

Btw, I noticed that you extended Sample_BurgApplication. Shouldn't it be Hilt_SampleApplication? Does the fix resolve the issue in your case?

geaden avatar Jul 01 '21 19:07 geaden

@geaden Sorry I edited the code I posted to keep things at their simplest and made a typo there - the code in my initial comment is indeed incorrect, but what I have locally is correct. I'll give that fix a try asap.

Kernald avatar Jul 02 '21 01:07 Kernald

@geaden I tried this fix and get a similar error as above about the app class extending Object. I'm not really sure what's running or not, or if Hilt is running on the wrong jar maybe...

Kernald avatar Jul 03 '21 04:07 Kernald

@Kernald Thanks a lot for letting know! I thought I had wrong Hilt setup. I keep digging into the issue, but unsuccessfully so far.

geaden avatar Jul 03 '21 07:07 geaden

This is a long-standing issue, it seems, related to how the rules collect plugin info - we special case java_library, and don't special case android_library. This is wrong, but it's been wrong for years. We should (and will) roll a fix, but it pre-exists, and we won't block 1.5 for it.

That said, it's awful and we should roll a fix. I'll try to get it in before release, but no promises. However, it should be in 1.6, now that we understand it.

cgruber avatar Aug 06 '21 19:08 cgruber

https://github.com/bazelbuild/rules_kotlin/pull/351

geaden avatar Oct 15 '21 04:10 geaden

Btw, with the latest rules_kotlin, Kotlin 1.5.21 and fix from #351 I'm getting:

error: wrong plugin option format: null, should be plugin:<pluginId>:<optionName>=<value>

Updated demo-app

geaden avatar Nov 22 '21 08:11 geaden

Sorry, do we have any progress here?

Nikolas-LFDesigns avatar May 25 '22 15:05 Nikolas-LFDesigns

Bumping up this thread again to see if there is any proper way to solve the issue.

TLDR; Hilt's library annotation processing doesn't work on kt_android_library's Kotlin files.

wsoesanto avatar Sep 13 '22 04:09 wsoesanto

Are you still able to reproduce this on a newer version of Bazel where the JavaPluginInfo provider exists? When rules_kotlin has access to this new provider, it doesn't apply the kt_jvm_plugin_aspect and collects the JavaPluginInfo directly.

Bencodes avatar Sep 23 '22 07:09 Bencodes

Haven't made a separate demo app, but I'm seeing this as well. However, it seems like the kt_android_library rule builds but the android_binary depending on that rule now has the issue.

Bazel version:

❯ bazel --version
bazel 6.0.0-pre.20220608.2

kt_android_library:

❯ bazel build //android/app/src/com/highgravitydays/android:highgravity
DEBUG: /private/var/tmp/_bazel_vple/f3403029ac4265720a1f6e63b005c1fd/external/io_bazel_rules_kotlin/kotlin/kotlin.bzl:104:10: kt_jvm_library should be loaded from //kotlin:jvm.bzl
INFO: Analyzed target //android/app/src/com/highgravitydays/android:highgravity (76 packages loaded, 1488 targets configured).
INFO: Found 1 target...
INFO: From Merging manifest for //android/app/src/com/highgravitydays/android:highgravity_base:
Warning: /private/var/tmp/_bazel_vple/f3403029ac4265720a1f6e63b005c1fd/sandbox/darwin-sandbox/784/execroot/__main__/android/app/src/com/highgravitydays/android/AndroidManifest.xml:32:9-35:35 Warning:
	provider#androidx.startup.InitializationProvider was tagged at AndroidManifest.xml:32 to remove other declarations but no other declaration present
INFO: From Merging compiled Android resources for //android/app/src/com/highgravitydays/android:highgravity_base:
Warning: /private/var/tmp/_bazel_vple/f3403029ac4265720a1f6e63b005c1fd/sandbox/darwin-sandbox/1024/execroot/__main__/bazel-out/darwin_arm64-fastbuild/bin/android/app/src/com/highgravitydays/android/_renamed/highgravity_base/AndroidManifest.xml:37:9-40:35 Warning:
	provider#androidx.startup.InitializationProvider was tagged at AndroidManifest.xml:37 to remove other declarations but no other declaration present
Target //android/app/src/com/highgravitydays/android:highgravity up-to-date:
  bazel-bin/android/app/src/com/highgravitydays/android/libhighgravity.jar
INFO: Elapsed time: 28.413s, Critical Path: 8.58s
INFO: 455 processes: 13 internal, 440 darwin-sandbox, 2 worker.
INFO: Build completed successfully, 455 total actions

android_binary:

❯ bazel build //android/app:app
INFO: Build option --fat_apk_cpu has changed, discarding analysis cache.
DEBUG: /private/var/tmp/_bazel_vple/f3403029ac4265720a1f6e63b005c1fd/external/io_bazel_rules_kotlin/kotlin/kotlin.bzl:104:10: kt_jvm_library should be loaded from //kotlin:jvm.bzl
INFO: Analyzed target //android/app:app (81 packages loaded, 1839 targets configured).
INFO: Found 1 target...
ERROR: /Users/vple/climb/android/app/src/com/highgravitydays/android/BUILD.bazel:5:19: KotlinKapt //android/app/src/com/highgravitydays/android:highgravity_kt { kt: 31, java: 0, srcjars: 0 } for armeabi-v7a failed: (Exit 1): build failed: error executing command (from target //android/app/src/com/highgravitydays/android:highgravity_kt) bazel-out/darwin_arm64-opt-exec-2B5CBBC6/bin/external/io_bazel_rules_kotlin/src/main/kotlin/build ... (remaining 1 argument skipped)
error: /var/folders/tc/qpt243215ss5h5x4qf_xl86w0000gn/T/pwd10869448029639228200/_kotlinc/android_app_src_com_highgravitydays_android-highgravity_kt_jvm/temp/stubs/com/highgravitydays/android/HighGravityApplication.java:7: error: [Hilt]
public final class HighGravityApplication {
             ^
  @HiltAndroidApp class expected to extend Hilt_HighGravityApplication. Found: Object
  [Hilt] Processing did not complete. See error above for details.
android/app/src/com/highgravitydays/android/HighGravityApplication.kt:7:32: error: unresolved reference: Hilt_HighGravityApplication
class HighGravityApplication : Hilt_HighGravityApplication() {
                               ^
Sep 29, 2022 11:06:50 PM worker request 0
SEVERE: Compilation failure: compile phase failed:Target //android/app:app failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 11.936s, Critical Path: 9.45s
INFO: 38 processes: 11 internal, 27 darwin-sandbox.
FAILED: Build did NOT complete successfully

The android_binary has the kt_android_rule as its only dep:

android_binary(
    name = "app",
    srcs = [],
    custom_package = "com.highgravitydays.android",
    dex_shards = 2,
    manifest = "//android/app/src/com/highgravitydays/android:AndroidManifest.xml",
    manifest_values = {
        "versionCode": "1",
        "minSdkVersion": "24",
        "targetSdkVersion": "31",
    },
    multidex = "native",
    deps = ["//android/app/src/com/highgravitydays/android:highgravity"],
)

vple avatar Sep 30 '22 03:09 vple

Okay, I forked @geaden's demo and attempted to update all the build config to match my project. MyActivity and MyApplication were updated to extend the corresponding Hilt_* classes, otherwise I left the app as is. Hopefully I didn't miss something.

https://github.com/vple/bazel_hilt_demo

Building the kt_android_library and android_binary targets seems to have a similar result to my above post--the kt_android_library builds but the android_binary does not.

❯ bazel clean
INFO: Starting clean.
INFO: Multiplexer process for Javac has closed its output stream
❯ bazel build //kotlin/com/example/app:examplelib
INFO: Analyzed target //kotlin/com/example/app:examplelib (69 packages loaded, 1219 targets configured).
INFO: Found 1 target...
Target //kotlin/com/example/app:examplelib up-to-date:
  bazel-bin/kotlin/com/example/app/libexamplelib.jar
INFO: Elapsed time: 9.347s, Critical Path: 4.35s
INFO: 165 processes: 10 internal, 153 darwin-sandbox, 2 worker.
INFO: Build completed successfully, 165 total actions
❯ bazel build //:exampleapp
INFO: Analyzed target //:exampleapp (5 packages loaded, 449 targets configured).
INFO: Found 1 target...
INFO: From Dexing external/maven/_dx/androidx_viewpager_viewpager/classes_and_libs_merged.jar_desugared.jar with applicable dexopts []:
Info: Stripped invalid locals information from 1 method.
Info in bazel-out/android-armeabi-v7a-fastbuild/bin/external/maven/_dx/androidx_viewpager_viewpager/classes_and_libs_merged.jar_desugared.jar:androidx/viewpager/widget/PagerTitleStrip.class:
Methods with invalid locals information:
  void androidx.viewpager.widget.PagerTitleStrip.updateTextPositions(int, float, boolean)
  Information in locals-table is invalid with respect to the stack map table. Local refers to non-present stack map type for register: 37 with constraint INT.
Info: Some warnings are typically a sign of using an outdated Java toolchain. To fix, recompile the source with an updated toolchain.
INFO: From Dexing external/maven/_dx/androidx_compose_ui_ui/classes_and_libs_merged.jar_desugared.jar with applicable dexopts []:
Info: Stripped invalid locals information from 1 method.
Info in bazel-out/android-armeabi-v7a-fastbuild/bin/external/maven/_dx/androidx_compose_ui_ui/classes_and_libs_merged.jar_desugared.jar:androidx/compose/ui/input/pointer/util/VelocityTracker.class:
Methods with invalid locals information:
  long androidx.compose.ui.input.pointer.util.VelocityTracker.getImpulseVelocity-9UxMQ8M()
  Information in locals-table is invalid with respect to the stack map table. Local refers to non-present stack map type for register: 8 with constraint LONG.
Info: Some warnings are typically a sign of using an outdated Java toolchain. To fix, recompile the source with an updated toolchain.
ERROR: /Users/vple/bazel_hilt_demo/kotlin/com/example/app/BUILD:3:19: KotlinKapt //kotlin/com/example/app:examplelib_kt { kt: 4, java: 0, srcjars: 0 } for armeabi-v7a failed: (Exit 1): build failed: error executing command (from target //kotlin/com/example/app:examplelib_kt) 
  (cd /private/var/tmp/_bazel_vple/5076266c303c1ab027859b6e56989c6e/execroot/__main__ && \
  exec env - \
    LC_CTYPE=en_US.UTF-8 \
    REPOSITORY_NAME=io_bazel_rules_kotlin \
  bazel-out/darwin_arm64-opt-exec-2B5CBBC6/bin/external/io_bazel_rules_kotlin/src/main/kotlin/build '--flagfile=bazel-out/android-armeabi-v7a-fastbuild/bin/kotlin/com/example/app/examplelib_kt-kapt-gensrc.jar-0.params')
# Configuration: a38a52272c28682b0c767b8d11bd23502b8f8836f39cc636f916800bb17781dc
# Execution platform: @local_config_platform//:host
error: /var/folders/tc/qpt243215ss5h5x4qf_xl86w0000gn/T/pwd12205052944019787285/_kotlinc/kotlin_com_example_app-examplelib_kt_jvm/temp/stubs/com/example/app/MyActivity.java:7: error: [Hilt]
public final class MyActivity {
             ^
  @AndroidEntryPoint class expected to extend Hilt_MyActivity. Found: Object
  [Hilt] Processing did not complete. See error above for details.
error: /var/folders/tc/qpt243215ss5h5x4qf_xl86w0000gn/T/pwd12205052944019787285/_kotlinc/kotlin_com_example_app-examplelib_kt_jvm/temp/stubs/com/example/app/MyApplication.java:7: error: [Hilt]
public final class MyApplication {
             ^
  @HiltAndroidApp class expected to extend Hilt_MyApplication. Found: Object
  [Hilt] Processing did not complete. See error above for details.
kotlin/com/example/app/MyActivity.kt:10:20: error: unresolved reference: Hilt_MyActivity
class MyActivity : Hilt_MyActivity() {
                   ^
kotlin/com/example/app/MyActivity.kt:12:43: error: unresolved reference. None of the following candidates is applicable because of receiver type mismatch: 
public inline fun <reified VM : ViewModel> ComponentActivity.viewModels(noinline extrasProducer: (() -> CreationExtras)? = ..., noinline factoryProducer: (() -> ViewModelProvider.Factory)? = ...): Lazy<TypeVariable(VM)> defined in androidx.activity
    private val viewModel: MyViewModel by viewModels()
                                          ^
kotlin/com/example/app/MyApplication.kt:7:23: error: unresolved reference: Hilt_MyApplication
class MyApplication : Hilt_MyApplication()
                      ^
Sep 30, 2022 12:18:56 AM worker request 0
SEVERE: Compilation failure: compile phase failed:Target //:exampleapp failed to build
INFO: Elapsed time: 50.154s, Critical Path: 26.76s
INFO: 633 processes: 36 internal, 533 darwin-sandbox, 64 worker.
FAILED: Build did NOT complete successfully

vple avatar Sep 30 '22 04:09 vple

Circling back here - I looked into this issue some. From what I saw the plugins are in fact being picked up correctly. I haven't figured out why but I think there's something wrong with this particular plugin and Kapt that causes the annotation processors to not work correctly.

Bencodes avatar Nov 07 '22 16:11 Bencodes

Any updates on this issue? I'm running into this error when I try to add exported_plugins to kt_android_library:

does not have mandatory providers: 'JavaPluginInfo'. Since this rule was created by the macro 'kt_android_library', the error might have been caused by the macro implementation

yvonnewong avatar May 02 '23 02:05 yvonnewong

No immediate updates here at the moment, but I expect this to be resolved once we switch to the Starlark implementation of rules_android.

Bencodes avatar May 23 '23 00:05 Bencodes

I don't have a solution here, but digging into this more, this does appear to be resolved from the rules_kotlin side, and instead this stems from the annotation processor itself. An example application class like:

@HiltAndroidApp(Application::class)
class DemoApplication : Hilt_DemoApplication()

Results in the annotation processor (this line) seeing Object as the application's superclass, rather than Hilt_DemoApplication.

I've opened this as google/dagger#4075. I have a work-around I can share if people would like (it's linked in the Dagger issue), but it's a bit of a hack.

pswaminathan avatar Sep 20 '23 14:09 pswaminathan