【问题标题】:Linking to JVM asm-defined classes from Kotlin using Gradle使用 Gradle 从 Kotlin 链接到 JVM asm 定义的类
【发布时间】:2016-03-17 12:42:59
【问题描述】:

我对 Android 应用进行了以下设置:

├── build.gradle
└── src
    └── main
        ├── AndroidManifest.xml
        ├── asm
        │   └── SomeJVMClass.j
        ├── kotlin
        │   └── activity.kt
        └── res
            └── values
                └── strings.xml

src/main/asm/SomeJVMClass.j中的源文件是Krakatau格式的JVM汇编(和Jasmin差不多)。我想使用它从我的主要 Kotlin 源代码 activity.kt 定义的类。

在我尝试使用 Gradle 自动执行此操作之前,仅手动将文件组装到 build 并没有帮助。这是我尝试过的:

  1. 执行gradle build 以获取骨架build 目录(这当然会失败,因为Kotlin 编译器找不到SomeJVMClass
  2. 我手动运行 Krakatau 以将其类文件放入 build/intermediates/classes/{debug,release}

    $ for flavor in debug release; do ~/prog/jvm/krakatau/assemble.py -out build/intermediates/classes/$flavor -r src/main/asm ;done
    
    Processing file src/main/asm/SomeJVMClass.j, 1/1 remaining
    Class written to build/intermediates/classes/debug/com/example/JVMServer/SomeJVMClass.class
    
    Processing file src/main/asm/SomeJVMClass.j, 1/1 remaining
    Class written to build/intermediates/classes/release/com/example/JVMServer/SomeJVMClass.class
    
  3. 重新运行grade build,希望Kotlin 现在可以找到.class文件;但没有任何改善:

:compileDebugKotlin
e: /home/cactus/prog/android/kotlin-asm/src/main/kotlin/activity.kt (3,20): 
   Unresolved reference: JVMServer
e: /home/cactus/prog/android/kotlin-asm/src/main/kotlin/activity.kt: (12,14): 
   Unresolved reference: SomeJVMClass

所以第一个问题显然是,我将生成的.class 文件放在哪里,以便 Kotlin 编译器可以找到它们。第二个后续问题是如何实现自动化,以便单个 gradle build 命令首先运行 Krakatau 汇编器,然后再运行 Kotlin 编译器。

作为参考,这里是我的源文件:

src/main/asm/SomeJVMClass.j:

.class public com/example/JVMServer/SomeJVMClass
.super java/lang/Object

.method public static foo: ()Ljava/lang/String;
  .code stack 2 locals 0
    ldc "JVM bytecode works"
    areturn
  .end code
.end method

.end class  

src/main/kotlin/activity.kt:

package com.example.JVMClient

import com.example.JVMServer.SomeJVMClass    
import android.app.Activity
import android.os.Bundle

class MainActivity: Activity() {
  protected override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setTitle(SomeJVMClass.foo())
  }
}

【问题讨论】:

    标签: java gradle android-gradle-plugin kotlin jasmin


    【解决方案1】:

    编辑:事实证明这种方法不适用于 android-gradle

    这与 gradle 的关系比 Kotlin 更重要,您可以通过在依赖项中添加语句 compile files("build/intermediates/classes/debug") 来告诉 gradle 在编译期间包含 .class 文件。

    这会将 .class 文件放在 Kotlin 应该能够找到它们的类路径中。

    【讨论】:

    • 听起来很有希望,但后来我从:prepareDebugDependencies得到Only Jar-type local dependencies are supported. Cannot handle: build/intermediates/classes/debug
    • 此外,如果我将我的SomeJVMClass.class 文件放在.jar 中并使用compile files("build/intermediates/classes/debug/asm.jar"),它稍后会在:transformClassesWithDexForDebugUncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/example/JVMServer/SomeJVMClass 中失败
    • @Cactus 将其作为 .jar 文件放在构建目录中可能会触发自动包含,请尝试删除编译行但保留 .jar
    • @Cactus 该文档实际上可能会解决您的问题:docs.gradle.org/current/javadoc/org/gradle/api/tasks/…
    猜你喜欢
    • 1970-01-01
    • 2022-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多