rust-lang / rustc_codegen_cranelift

Cranelift based backend for rustc
Apache License 2.0
1.52k stars 94 forks source link

How do you build this for Android ("Tier 2 without Host Tools") #1450

Open LagradOst opened 5 months ago

LagradOst commented 5 months ago

7 mo ago I tried to build this project for android and being successfully able to compile rust project on android, however I was unable to link it (missing libc.so.6 ect) and JIT PTE was not implemented. Now I tested https://github.com/bytecodealliance/cranelift-jit-demo and it worked on an android device, and now I want to port the entirety of the compiler to android using JIT to run the code.

I use https://github.com/cross-rs/cross to "cross build --target aarch64-linux-android --release" this project and add to the toml

rustc_middle = { path = "../rustc_middle" }
rustc_ast = { path = "../rustc_ast" }
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_fs_util = { path = "../rustc_fs_util" }
rustc_hir = { path = "../rustc_hir" }
rustc_incremental = { path = "../rustc_incremental" }
rustc_index = { path = "../rustc_index" }
rustc_interface = { path = "../rustc_interface" }
rustc_span = { path = "../rustc_span" }
rustc_metadata = { path = "../rustc_metadata" }
rustc_session = { path = "../rustc_session" }
rustc_target = { path = "../rustc_target" }
rustc_driver = { path = "../rustc_driver" }

and

[env] 
CFG_RELEASE="1.77.0-nightly"
CFG_RELEASE_CHANNEL="nightly" # https://github.com/rust-lang/rust/blob/fabf9298633ca64450fa2af535252dc44a3b1080/src/bootstrap/tool.rs#L179
RUSTC_INSTALL_BINDIR = "C:\\Users\\v\\.cargo\\bin"
CFG_COMPILER_HOST_TRIPLE = "aarch64-linux-android"
REAL_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
CFG_VERSION="1.77.0-nightly (62d7ed4a6 2024-01-11)"
CFG_RELEASE_NUM = "1.77.0"
DOC_RUST_LANG_ORG_CHANNEL="nightly" 
CFG_VER_DATE="2024-01-11"
CFG_SHORT_COMMIT_HASH = "62d7ed4a6"
CFG_COMMIT_HASH = "62d7ed4a6775c4490e493093ca98ef7c215b835b"

And this works fine for building the librustc_driver.so and librustc_codegen_cranelift.so, however it cant compile without a sysroot.

How can I compile the sysroot (to target android) to be able to compile it? Screenshot_20240113_171757_com example teest

bjorn3 commented 5 months ago

If I understand correctly what you are doing, you are making cargo compile rustc_driver + dependencies and then rustc_codegen_cranelift for android and then loading it into an existing rustc executable. That won't work. You need to link codegen backends against the exact same librustc_driver.so as rustc itself. Otherwise you either have abi mismatches or duplicated thread local storage. Both of which will lead to the compiler crashing. Or did I misunderstand what you did?

If I did misunderstand what you did and it does work, then you could try building the sysroot by changing rust-toolchain.toml to match the nightly you compiled librustc_codegen_cranelift.so for and then with an unmodified source of cg_clif run TARGET_TRIPLE="aarch64-linux-android" ./y.sh build. This should build the standard library for aarch64-linux-android and put it in dist/lib/rustlib/aarch64-linux-android. You need to put this dir at lib/rustlib/aarch64-linux-android of the sysroot of the rustc running on your phone.

I did however recommend building rustc itself with the cranelift backend enabled using a config.toml like the following in your local checkout of https://github.com/rust-lang/rust/

profile = "compiler"

[rust]
codegen-backends = ["llvm", "cranelift"]

[target.aarch64-linux-android]
cc = "/path/to/clang"
cxx = "/path/to/clang++"
linker = "/path/to/clang"

where you need to point it to the clang included in the android ndk and then doing ./x.py build --host aarch64-linux-android --target aarch64-linux-android. I haven't tested this though. Also the resulting rustc will use LLVM by default, but you can switch to cg_clif using -Zcodegen-backend=cranelift. Rust's build system unfortunately doesn't support specifying a different set of codegen backends to compile for each target and compiling rustc itself with cg_clif will result in a pretty slow compiler.

LagradOst commented 5 months ago

If I understand correctly what you are doing, you are making cargo compile rustc_driver + dependencies and then rustc_codegen_cranelift for android and then loading it into an existing rustc executable. That won't work. You need to link codegen backends against the exact same librustc_driver.so as rustc itself. Otherwise you either have abi mismatches or duplicated thread local storage. Both of which will lead to the compiler crashing. Or did I misunderstand what you did?

What I am actually doing is compiling this repo, but including the rustc_driver as a dependency, last time I did this I somehow got it working fine but the linker refused to work. The reason why I use cranelift over LLVM is because that is a real pain in the ass to compile and cranelift supports JIT so I can avoid linking.

All I want to do is to be able to compile a simple rust program with std on android and run it, but because it is not a host target shit just refuses to work.

LagradOst commented 5 months ago

@bjorn3 using the default library does not work with JIT, however not using JIT forces me to link it, and I cant for the love of god get it to link correctly. I also tried compiling both the compiler and cranelift, but got weird errors.

eg TARGET_TRIPLE="aarch64-linux-android" ./y.sh build gave build/stdlib_target/aarch64-linux-android/release/deps/std-c3180c3c34b5771d.104560jli91o8tef.rcgu.o: error adding symbols: file in wrong format

So I am wondering how I should compile the sysroot to give JIT lib files, because right now -C llvm-args=mode=jit causes Screenshot_20240124_195824_com example teest

and not using it causes Screenshot_20240124_224715_com example teest

bjorn3 commented 5 months ago

eg TARGET_TRIPLE="aarch64-linux-android" ./y.sh build gave build/stdlib_target/aarch64-linux-android/release/deps/std-c3180c3c34b5771d.104560jli91o8tef.rcgu.o: error adding symbols: file in wrong format

You probably need to copy https://github.com/rust-lang/rustc_codegen_cranelift/blob/24361a1b99b122806afdc01c3aae1c43fdcc7e0a/build_system/utils.rs#L25-L34 to and adapt it for the "aarch64-linux-android" target, pointing to the linker in the NDK. You can remove the self.runner as that only matters for running tests.

So I am wondering how I should compile the sysroot to give JIT lib files, because right now -C llvm-args=mode=jit causes

The JIT mode requires all dependencies to be available as linked dylibs. I've got a branch somewhere to add a fake LTO mode to cg_clif which would likely help here, but that branch is quite out of date and doesn't actually wire it up to the JIT mode, only the default AOT mode.