tectonic-typesetting / tectonic

A modernized, complete, self-contained TeX/LaTeX engine, powered by XeTeX and TeXLive.
https://tectonic-typesetting.github.io/
Other
3.97k stars 161 forks source link

Compile for Android #662

Open naveedpash opened 4 years ago

naveedpash commented 4 years ago

Hi, I'm trying to cross compile tectonic to android using NDK r21 and the cargo plugin cargo-ndk

At first it would give me the error: Unable to find openssl/opensslconf.h

I had to add the following line to Cargo.toml

[target.aarch64-linux-android.dependencies]
openssl = { version = "*", features = ["vendored"] }

Now only one problem left:

error: failed to run custom build command for `tectonic v0.0.0-dev.0 (/home/naveedpash/tectonic)

Caused by:
  process didn't exit successfully: `/home/naveedpash/tectonic/target/release/build/tectonic-ca4c95895b54eba9/build-script-build` (exit code: 101)
  --- stdout
  cargo:rerun-if-changed=src/engines/mod.rs
  cargo:rustc-env=TARGET=aarch64-linux-android
  cargo:rerun-if-env-changed=TECTONIC_DEP_BACKEND
  cargo:rerun-if-env-changed=TECTONIC_PKGCONFIG_FORCE_SEMI_STATIC
  cargo:rerun-if-env-changed=FONTCONFIG HARFBUZZ >= 1.4 HARFBUZZ_ICU ICU_UC FREETYPE2 GRAPHITE2 LIBPNG ZLIB_NO_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_aarch64-linux-android
  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_aarch64_linux_android
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_ALLOW_CROSS
  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS
  cargo:rerun-if-env-changed=PKG_CONFIG_aarch64-linux-android
  cargo:rerun-if-env-changed=PKG_CONFIG_aarch64_linux_android
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_aarch64-linux-android
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_aarch64_linux_android
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR

  --- stderr
  thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: CrossCompilation', build.rs:67:14
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace`

Don't known how to tell pkgconfig crate that it's ok to cross-compile. Help?

pkgw commented 4 years ago

There is a hint in the error output, although it is not obvious:

  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_aarch64-linux-android
  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_aarch64_linux_android
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_ALLOW_CROSS
  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS

I think you need to set the environment variable PKG_CONFIG_ALLOW_CROSS to 1, although you might need to use one of these other variables instead.

Also, you may wish to check out the cross tool for cross-compiling Rust projects. The Tectonic CI/CD system uses a customized version for its cross-compiles to build static or "semi-static" executables that don't have a lot of dependencies on non-system libraries like harfbuzz. Depending on your needs, you might not need a custom version.

People have mentioned Android compilations a few time over the years, so if you might be able to synthesize your work into contributing a new CI/CD build for Android, that would be awesome!

snowinmars commented 3 years ago

@naveedpash , just passing by: I'm working on tectonic dockerization. It's ok as is in #690 , but I'm not loosing hope to fix the volume issue.

So, is it possible, that docker image will solve your issue?

naveedpash commented 3 years ago

Sorry for super late reply; got caught up with my day job

Yes I did try the ubuntu official docker image with stable rust toolchain and android ndk version 22

#dockerfile
RUN apt install -y libfontconfig1-dev libgraphite2-dev libharfbuzz-dev libicu-dev libssl-dev zlib1g-dev **gcc-multilib**

(notice I had to add gcc-multilib otherwise ndk gives an error saying bits/libc-header-start.h cannot be found for reasons I don't understand but something to do with the fact that parts of android run in 32 bits)

then I created .cargo/config with the following lines

[target.aarch64-linux-android]
ar = "/path/to/android-sdk/ndk/<version>/toolchains/llvm/prebuild/linux-x86_64/bin/aarch64-linux-android-ar"
linker = "/path/to/android-sdk/ndk/<version>/toolchains/llvm/prebuild/linux-x86_64/bin/aarch64-linux-android28-clang"

I also had to run git submodule update --init which makes cargo build openssl-sys rather than look for the libssl-dev. Before I did that, I was insanely struggling with trying to get PKG_CONFIG to find the libssl-dev.

Then I run cargo build --target aarch64-linux-android --release

That it gives me 3 errors while trying to compile harfbuzz/src/harfbuzz.cc all of which look like the following

cargo:warning=harfbuzz/src/hb-ot-layout.cc:1008:63: error: cast from pointer to smaller type 'uintptr_t' (aka 'unsigned int') loses information
cargo:warning=    hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) &p - (uintptr_t) &g);
cargo:warning=                                                              ^~~~~~~~~~~~~~
cargo:warning=In file included from harfbuzz/src/harfbuzz.cc:51

I think I also need to define an additional linker for the c++ files like linker = "/path/to/android-sdk/ndk/<version>/toolchains/llvm/prebuild/linux-x86_64/bin/aarch64-linux-android28-clang++" but I'm not sure how to tell cargo to do that.

Any help? I know it's definitely possible to compile libharfbuzz-dev for android because the Termux app for Android definitely has it in their apt repository and their deb package contains both lib/libharfbuzz.so as will as header files in the include/ directory.

pkgw commented 3 years ago

@naveedpash Hmm, I would strongly suggest that you base your work off of the "cross" framework for Rust, which is what we use in our CI systems:

https://github.com/rust-embedded/cross

You can see the relevant CI plumbing here:

https://github.com/tectonic-typesetting/tectonic/blob/master/dist/azure-build-and-test-cross.yml

The challenge historically has been that because Tectonic needs its native support libraries, we've had to use custom cross-builder Docker images with those libraries preinstalled. Generated using this framework:

https://github.com/tectonic-typesetting/tectonic-ci-support/tree/master/cross-images (the supporting README and comments aren't 100% up to date unfortunately)

But one of the big goals of moving to the sub-crate setup with "bridge" crates is to be able to start running these builds on stock Cross images.