mozilla / rust-android-gradle

Apache License 2.0
1.03k stars 67 forks source link

Gradle build task packages my rust library only in release APK #113

Closed JonForShort closed 1 year ago

JonForShort commented 1 year ago

Hi, when I do a full clean build from the command line (i.e. ./gradlew clean build) for my project, I noticed that my native rust libraries are only included/packaged in the release variant of my APK. For some reason the debug variant does not include the native rust libraries. It includes all other files (e.g. assets, class files, resources, etc.) but just not the native libraries. I am not sure if this is expected behavior. My understanding is that although the cargoBuild task only executes once, that the native libraries should still be packaged into both the release and debug variants of the APK.

Here is the source code for my build script in case it helps.

https://github.com/JonForShort/android-local-vpn/blob/a45938677ea222df5a47d7eb532b5adb6e4a4ce6/source/vpn/build.gradle#L63

Thanks!

ncalexan commented 1 year ago

Hmm, I can't repro this. It might be related to #85 -- could you see if following that approach fixes this issue for you?

Locally, after bumping to version 29 to let the sample projects build with the following patch:

diff --git a/samples/app/build.gradle b/samples/app/build.gradle
index 8c30046..ab6a363 100644
--- a/samples/app/build.gradle
+++ b/samples/app/build.gradle
@@ -16,13 +16,13 @@ apply plugin: 'com.android.application'
 apply plugin: 'org.mozilla.rust-android-gradle.rust-android'

 android {
-    compileSdkVersion 27
+    compileSdkVersion 29
     ndkVersion "23.1.7779620"

     defaultConfig {
         applicationId "com.nishtahir.androidrust"
         minSdkVersion 21
-        targetSdkVersion 27
+        targetSdkVersion 29
         versionCode 1
         versionName "1.0"
         testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

I see:

$ env ANDROID_SDK_ROOT=/Users/nalexander/.mozbuild/android-sdk-macosx ./gradlew -p samples/app clean build

> Task :cargoBuildArm
    Finished dev [unoptimized + debuginfo] target(s) in 0.04s

> Task :lintDebug FAILED
Wrote HTML report to file:///Users/nalexander/Mozilla/rust-android-gradle/samples/app/build/reports/lint-results-debug.html
Lint found 1 error and 5 warnings. First failure:
/Users/nalexander/Mozilla/rust-android-gradle/samples/app/build.gradle:53: Error: Version 28 (intended for Android Pie and below) is the last version of the legacy support library, so we recommend that you migrate to AndroidX libraries when using Android Q and moving forward. The IDE can help with this: Refactor > Migrate to AndroidX... [GradleCompatible]
    implementation 'com.android.support:appcompat-v7:27.1.1'
                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Lint found errors in the project; aborting build.

Fix the issues identified by lint, or add the following to your build script to proceed with errors:
...
android {
    lintOptions {
        abortOnError false
    }
}
...

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':lintDebug'.
> A failure occurred while executing com.android.build.gradle.internal.lint.AndroidLintTask$AndroidLintLauncherWorkAction
   > There was a failure while executing work items
      > A failure occurred while executing com.android.build.gradle.internal.lint.AndroidLintWorkAction
         > Lint found errors in the project; aborting build.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See https://docs.gradle.org/7.1.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD FAILED in 11s
81 actionable tasks: 72 executed, 9 up-to-date

That's fine, I don't care about lint failures. Then:

$ unzip -l samples/app/build/outputs/apk/debug/app-debug.apk | grep \.so$
  4398132  01-01-1981 01:01   lib/armeabi-v7a/librust.so
$ unzip -l samples/app/build/outputs/apk/release/app-release-unsigned.apk | grep \.so$
  4398132  01-01-1981 01:01   lib/armeabi-v7a/librust.so

In addition, I see:

$ env ANDROID_SDK_ROOT=/Users/nalexander/.mozbuild/android-sdk-macosx ./gradlew -p samples/app sourceSets

> Task :sourceSets

------------------------------------------------------------
Root project 'app'
------------------------------------------------------------

...

debug
-----
Compile configuration: debugCompile
build.gradle name: android.sourceSets.debug
Java sources: [src/debug/java]
Kotlin sources: [src/debug/java, src/debug/kotlin]
Manifest file: src/debug/AndroidManifest.xml
Android resources: [src/debug/res]
Assets: [src/debug/assets]
AIDL sources: [src/debug/aidl]
RenderScript sources: [src/debug/rs]
JNI sources: [src/debug/jni]
JNI libraries: [src/debug/jniLibs]
Java-style resources: [src/debug/resources]

main
----
Compile configuration: compile
build.gradle name: android.sourceSets.main
Java sources: [src/main/java]
Kotlin sources: [src/main/java, src/main/kotlin]
Manifest file: src/main/AndroidManifest.xml
Android resources: [src/main/res]
Assets: [src/main/assets]
AIDL sources: [src/main/aidl]
RenderScript sources: [src/main/rs]
JNI sources: [src/main/jni]
JNI libraries: [src/main/jniLibs, build/rustJniLibs/android]
Java-style resources: [src/main/resources]

release
-------
Compile configuration: releaseCompile
build.gradle name: android.sourceSets.release
Java sources: [src/release/java]
Kotlin sources: [src/release/java, src/release/kotlin]
Manifest file: src/release/AndroidManifest.xml
Android resources: [src/release/res]
Assets: [src/release/assets]
AIDL sources: [src/release/aidl]
RenderScript sources: [src/release/rs]
JNI sources: [src/release/jni]
JNI libraries: [src/release/jniLibs]
Java-style resources: [src/release/resources]
...

You can see the build/rustJniLibs/android in main, which is how both Android variants acquire the same .so. Let me know if you can get this sorted -- it might be that I need to verify that all variants get the libraries packaged to the test suite, etc.

JonForShort commented 1 year ago

Thanks @ncalexan for looking into this for me. Yes, using the approach described in #85 resolves my issue. I am now able to see my native binaries in both debug and release variants of my APK. Thanks!