在编译Kotlin代码之前,从Gradle运行CMake

3
使用Gradle 5.4.1,我想为Android应用程序构建一个CMake项目。这可以在'app/build.gradle'中完成:
externalNativeBuild {
    cmake {
        // Provides a relative path to your CMake build script.
        version "3.13.0+"
        path "../subproject/CMakeLists.txt"
    }
}

这个项目使用SWIG生成了一个共享库和一些Java文件。我可以通过-DJAVA_OUTPUT_DIR=generated/java指定Java源代码的输出目录。
如何强制gradle在编译主应用程序源代码(Kotlin)之前等待CMake构建完成?源代码导入了生成的JAVA文件,当前的构建过程因缺少Java文件而失败。看起来gradle同时运行cmake和Kotlin编译器。
奖励问题:如何将生成的源输出目录添加到AndroidStudio项目树中作为生成的源?树中有一个特殊的条目用于生成的源。
版本信息:
$ ./gradlew --version
------------------------------------------------------------ Gradle 5.4.1 ------------------------------------------------------------
Build time: 2019-04-26 08:14:42 UTC Revision: 261d171646b36a6a28d5a19a69676cd098a4c19d
Kotlin: 1.3.21 Groovy: 2.5.4 Ant: Apache Ant(TM) version 1.9.13 compiled on July 10 2018 JVM: 11.0.5 (Debian 11.0.5+10-post-Debian-1deb10u1) OS: Linux 4.19.0-6-amd64 amd64

这回答了你的问题吗?在使用Android Gradle插件进行编译之前运行任务 - Sergei Voitovich
@SergeyVoytovich 不,我的 Gradle 脚本中没有任何自定义任务。或者我可以写类似于 preBuild.dependsOn(some_cmake_build_task) 这样的东西吗?那么任务的正确名称是什么? - cytrinox
2个回答

3
你应该将cmake任务添加为compileKotlin任务的依赖项。
Gradle任务是部分有序的(某些任务应在其他任务之前启动)。使用依赖关系来表达这种关系。
要声明对externalNativeBuild的依赖项,请将其附加到build.gradle
project.afterEvaluate {
    if (tasks.findByName("externalNativeBuildDebug")) {
        compileDebugKotlin.dependsOn externalNativeBuildDebug
    }
    if (tasks.findByName("externalNativeBuildRelease")) {
        compileReleaseKotlin.dependsOn externalNativeBuildRelease  
    }
}
  • afterEvaluate 是什么?这是 Gradle 生命周期中的一个阶段。在此阶段中,所有定义都被读取并应用。详情请参见此处

  • externalNativeBuildDebugexternalNativeBuildRelease 是什么?它们是对于 externalNativeBuild 任务的引用,具体取决于特定的构建命令。


这个失败了:在类型为org.gradle.api.Project的项目“:app”中找不到未知属性“compileKotlin”。 - cytrinox
1
@cytrinox 看起来 Android 项目中的名称不同。https://dev59.com/h1cP5IYBdhLWcg3wl7GY。我更新了答案。 - Sergei Voitovich
1
最后一行应该是compileReleaseKotlin而不是compileDebugKotlin吗? - cytrinox

2

虽然已接受的答案很好,但我使用了libraryVariants来实现这一点。我个人认为这更加优雅。以下是我在Kotlin DSL脚本中的代码:

android {
    libraryVariants.all {
        tasks.findByName("compile${name.capitalize()}Kotlin")
            ?.dependsOn(tasks.findByName("externalNativeBuild${name.capitalize()}"))
    }
}

这种解决方案的重要优势在于它不受您构建变体的影响,并且如果您更改/添加变体,它将继续工作而无需修改。

1
我得到的印象是OP的项目是一个应用程序项目,因此在这种情况下,应该使用applicationVariants.all而不是libraryVariants.all - Michael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接