mozilla / rust-android-gradle

Apache License 2.0
1.03k stars 67 forks source link

Help specifying toolchain #39

Open tbraun96 opened 3 years ago

tbraun96 commented 3 years ago

By default, the build runs the following command:

rustc --crate-name lusna_ffi --edition=2018 lusna_ffi\src\lib.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type cdylib --emit=dep-info,link -Cembed-bitcode=no -C debuginfo=2 -C metadata=fcf7fc3e883754d2 --out-dir C:\hyxe_wave\target\x86_64-linux-android\debug\deps --target x86_64-linux-android -C linker=C:\Users\tbrau\AndroidStudioProjects\Lusna\build\linker-wrapper\linker-wrapper.bat -C incremental=C:\hyxe_wave\target\x86_64-linux-android\debug\incremental -L dependency=C:\hyxe_wave\target\x86_64-linux-android\debug\deps -L dependency=C:\hyxe_wave\target\debug\deps --extern libc=C:\hyxe_wave\target\x86_64-linux-android\debug\deps\liblibc-f65a499a1c08d6d0.rlib -Ctarget-feature=+aes,+sse2,+sse4.1,+ssse3

Notice: linker=C:\Users\tbrau\AndroidStudioProjects\Lusna\build\linker-wrapper\linker-wrapper.bat

This fails with a nonzero exit code.

However, when I run the command in the command prompt with:

rustc --crate-name lusna_ffi --edition=2018 lusna_ffi\src\lib.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type cdylib --emit=dep-info,link -Cembed-bitcode=no -C debuginfo=2 -C metadata=fcf7fc3e883754d2 --out-dir C:\hyxe_wave\target\x86_64-linux-android\debug\deps --target x86_64-linux-android -C linker=C:/android-ndk-r21d/toolchains/llvm/prebuilt/windows-x86_64/bin/x86_64-linux-android30-clang.cmd -C incremental=C:\hyxe_wave\target\x86_64-linux-android\debug\incremental -L dependency=C:\hyxe_wave\target\x86_64-linux-android\debug\deps -L dependency=C:\hyxe_wave\target\debug\deps --extern libc=C:\hyxe_wave\target\x86_64-linux-android\debug\deps\liblibc-f65a499a1c08d6d0.rlib -Ctarget-feature=+aes,+sse2,+sse4.1,+ssse3

where linker=C:/android-ndk-r21d/toolchains/llvm/prebuilt/windows-x86_64/bin/x86_64-linux-android30-clang.cmd, it runs perfectly (zero exit code). I see that I can change the local.properties to specify the ndk toolchain location, but which directory should be input therein? Thanks

ncalexan commented 3 years ago

Hi! There are at least two things at play here, and we'll need more details to sort out what's really happening.

First, the linker wrapper has a specific purpose: it's about avoiding cache invalidation due to linker arguments, see https://github.com/mozilla/rust-android-gradle/commit/eddfc9e42708d9605ccde7e9963c88bdd41228d1.

Second, the linker wrapper is not invoking the NDK clang directly; it's invoking whatever Rust is saying is the linker, and that probably includes arguments. So your substitution isn't what Rust itself would do (I think).

Now, to debug -- I'll need details of what happens in the linker wrapper invocation. There are lots of environment variables that control everything; can you try to figure out what command the linker wrapper actually is invoking on Windows? And then we'll have to dig into whether it's the linker wrapper that is failing or the underlying Rust (cargo) invocation. If you cargo build --target android-... or whatever, does that succeed? So it's really the r-a-g plugin that's causing issues?

tbraun96 commented 3 years ago

If you cargo build --target android-... or whatever, does that succeed?

Yes, it builds like a charm. In the crate's .cargo/config, I have:

[target.x86_64-linux-android]
ar = "C:/android-ndk-r21d/toolchains/llvm/prebuilt/windows-x86_64/bin/x86_64-linux-android-ar"
linker = "C:/android-ndk-r21d/toolchains/llvm/prebuilt/windows-x86_64/bin/x86_64-linux-android30-clang.cmd"

[target.aarch64-linux-android]
ar = "C:/android-ndk-r21d/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android-ar"
linker = "C:/android-ndk-r21d/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android30-clang.cmd"

[target.armv7-linux-androideabi]
ar = "C:/android-ndk-r21d/toolchains/llvm/prebuilt/windows-x86_64/bin/armv7a-linux-androideabi-ar"
linker = "C:/android-ndk-r21d/toolchains/llvm/prebuilt/windows-x86_64/bin/armv7a-linux-androideabi-android30-clang.cmd"

[target.i686-linux-android]
ar = "C:/android-ndk-r21d/toolchains/llvm/prebuilt/windows-x86_64/bin/i686-linux-android-ar"
linker = "C:/android-ndk-r21d/toolchains/llvm/prebuilt/windows-x86_64/bin/i686-linux-android30-clang.cmd"

In the build.gradle file:

cargo {
    module  = "../../../../../foo/bar_ffi"       // Or whatever directory contains your Cargo.toml
    libname = "bar_ffi"          // Or whatever matches Cargo.toml's [package] name.
    targets = ["arm64"]  // See bellow for a longer list of options
    targetDirectory = '../../../../../foo/target'
    verbose = true
    // UNCOMMENT FOR RELEASE MODE profile = 'release'
}
ncalexan commented 3 years ago

Oh I see, you are using .cargo/config to specify the linker yourself. Hmm.

Digging into https://github.com/mozilla/rust-android-gradle/blob/6e553c13ef2d9bb40b58a7675b96e0757d1b0443/plugin/src/main/kotlin/com/nishtahir/CargoBuildTask.kt#L205-L217, it looks like you can use the "bail out" exec method to overwrite RUST_ANDROID_GRADLE_CC in the environment. That's what the linker wrapper is invoking -- see if you can set it to the path for the NDK command that you want to run, and if that works?

Detailed logs showing if it's the linker failing or if it's Python failing or something else would help.

tbraun96 commented 3 years ago

Bingo, that looks like it did it! Maybe, exposing that setting directly in the cargo { } block would make it pretty convenient for downstream users.

ncalexan commented 3 years ago

Bingo, that looks like it did it! Maybe, exposing that setting directly in the cargo { } block would make it pretty convenient for downstream users.

I'm glad we found a workaround!

I haven't time to do this myself but I would merge a patch. Sadly, my former colleague Thom, who managed release of this plugin, is no longer working for Mozilla (Corporation) so I'll have to dust off my shell history to relearn how to publish.