cross-rs / cross

“Zero setup” cross compilation and “cross testing” of Rust crates
Apache License 2.0
6.49k stars 365 forks source link

ncurses.h: No such file or directory #1343

Open thomas725 opened 11 months ago

thomas725 commented 11 months ago

Checklist

Describe your issue

I tried building my almost empty Rust + Cursive playground application, and failed:

$ cross build  --release                                                                                                                                                                              ✔  26s  
warning: unused manifest key: target.arm-unknown-linux-gnueabihf.linker
warning: unused manifest key: target.powerpc-unknown-linux-gnu.linker
   Compiling signal-hook-registry v1.4.1
   Compiling num-traits v0.2.17
   Compiling getrandom v0.2.10
   Compiling enum-map v2.6.3
   Compiling time v0.3.29
   Compiling term_size v0.3.2
   Compiling crossbeam-channel v0.5.8
   Compiling ncurses v5.101.0
   Compiling enumset v1.1.3
error: failed to run custom build command for `ncurses v5.101.0`

Caused by:
  process didn't exit successfully: `/target/release/build/ncurses-3b76e5da4c5551fd/build-script-build` (exit status: 101)
  --- stdout
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=NCURSESW5_NO_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG
  cargo:rerun-if-env-changed=NCURSESW5_STATIC
  cargo:rerun-if-env-changed=NCURSESW5_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=NCURSESW_NO_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG
  cargo:rerun-if-env-changed=NCURSESW_STATIC
  cargo:rerun-if-env-changed=NCURSESW_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
  cargo:rustc-link-lib=ncursesw
  OPT_LEVEL = Some("z")
  TARGET = Some("x86_64-unknown-linux-gnu")
  HOST = Some("x86_64-unknown-linux-gnu")
  cargo:rerun-if-env-changed=CC_x86_64-unknown-linux-gnu
  CC_x86_64-unknown-linux-gnu = None
  cargo:rerun-if-env-changed=CC_x86_64_unknown_linux_gnu
  CC_x86_64_unknown_linux_gnu = None
  cargo:rerun-if-env-changed=HOST_CC
  HOST_CC = None
  cargo:rerun-if-env-changed=CC
  CC = None
  cargo:rerun-if-env-changed=CRATE_CC_NO_DEFAULTS
  CRATE_CC_NO_DEFAULTS = None
  DEBUG = Some("false")
  CARGO_CFG_TARGET_FEATURE = Some("fxsr,sse,sse2")
  cargo:rerun-if-env-changed=CFLAGS_x86_64-unknown-linux-gnu
  CFLAGS_x86_64-unknown-linux-gnu = None
  cargo:rerun-if-env-changed=CFLAGS_x86_64_unknown_linux_gnu
  CFLAGS_x86_64_unknown_linux_gnu = None
  cargo:rerun-if-env-changed=HOST_CFLAGS
  HOST_CFLAGS = None
  cargo:rerun-if-env-changed=CFLAGS
  CFLAGS = None

  --- stderr
  /target/x86_64-unknown-linux-gnu/release/build/ncurses-e7af6b71caf2e572/out/chtype_size.c:6:10: fatal error: ncurses.h: No such file or directory
      6 | #include <ncurses.h>
        |          ^~~~~~~~~~~
  compilation terminated.
  thread 'main' panicked at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ncurses-5.101.0/build.rs:105:5:
  assertion failed: command.status().expect(\"compilation failed\").success()
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
error[E0463]: can't find crate for `enumset_derive`
   --> /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/enumset-1.1.3/src/lib.rs:199:9
    |
199 | pub use enumset_derive::EnumSetType;
    |         ^^^^^^^^^^^^^^ can't find crate

For more information about this error, try `rustc --explain E0463`.
error: could not compile `enumset` (lib) due to previous error

This error says I'm missng ncurses.h, but I'm not:

$ ls -alih /usr/include/*curses*                                                                                                                                                                              ✔ 
1404502 -rw-r--r-- 1 root root 7,1K 23. Mai 22:02 /usr/include/cursesapp.h
1404503 -rw-r--r-- 1 root root  28K 23. Mai 22:02 /usr/include/cursesf.h
1404501 -rw-r--r-- 1 root root  99K 23. Mai 22:02 /usr/include/curses.h
1404504 -rw-r--r-- 1 root root  20K 23. Mai 22:02 /usr/include/cursesm.h
1404505 -rw-r--r-- 1 root root 8,6K 23. Mai 22:02 /usr/include/cursesp.h
1404506 -rw-r--r-- 1 root root  50K 23. Mai 22:02 /usr/include/cursesw.h
1404513 -rw-r--r-- 1 root root 4,1K 23. Mai 22:02 /usr/include/ncurses_dll.h
1404512 lrwxrwxrwx 1 root root    8 23. Mai 22:02 /usr/include/ncurses.h -> curses.h
  67121 -rw-r--r-- 1 root root  13K 27. Dez 2022  /usr/include/slcurses.h

What target(s) are you cross-compiling for?

powerpc-unknown-linux-gnu

Which operating system is the host (e.g computer cross is on) running?

What architecture is the host?

What container engine is cross using?

cross version

cross 0.2.5 (3c21f9e 2023-10-11)

Example

git clone https://gitlab.com/thomas351/rust-p2p-chat/
cd rust-p2p-chat
cross build --release

Gives the error message /target/x86_64-unknown-linux-gnu/release/build/ncurses-e7af6b71caf2e572/out/chtype_size.c:6:10: fatal error: ncurses.h: No such file or directory

Additional information / notes

The normal cargo build --release works fine.

Emilgardis commented 11 months ago

Hi! First up, targeting powerpc-unknown-linux-gnu is getting trickier since it's deprecated and not supported by Ubuntu for libncurses-dev. Instead, you should probably use powerpc64le-unknown-linux-gnu

The main issue you're encountering stems from cross running in a container that doesnt include libncurses-dev. Installing it on your local system won't affect this isolated container.

To fix this, you'll want to set up a Cross.toml file in your project directory and add:

# Cross.toml
[build]
pre-build = [
    "dpkg --add-architecture $CROSS_DEB_ARCH",
    "apt-get update && apt-get install --assume-yes libncurses-dev:$CROSS_DEB_ARCH"
]

This will install the necessary library in the container for whichever target you're using, see [build] and Linking external libraries. That should make cross run --target powerpc64le-unknown-linux-gnu and cross run --target x86_64-unknown-linux-gnu work just fine.

As for powerpc-unknown-linux-gnu, your options are:

  1. Utilize Debian's jessie repo to obtain the library. The wiki has more details.
  2. Manually compile the library as a step in the pre-build and place it in /usr/powerpc-linux-gnu/lib.
  3. Opt for a more commonly supported target like powerpc64le-unknown-linux-gnu.

If you have more questions, feel free to ask.

thomas725 commented 11 months ago

Thanks for the detailed explanation and the clear guide how to proceed, will try it next!

I'm unsure if powerpc64le is the right architecture for my target system, it's an OpenWRT device with a Freescale MPC85xx P1014 SoC, which I believe is a 32bit PowerPC architecture, but I'm not sure. I'll try with powerpc64le-unknown-linux-gnu in a few hours and report back on my results afterwards :)

thomas725 commented 11 months ago

Okey, so first result, the ncurses.h not found vanished, but it still fails, but I don't understand what the new error is trying to say:

$ cross build  --release --target powerpc64le-unknown-linux-gnu
...
error: failed to run custom build command for `ncurses v5.101.0`

Caused by:
  process didn't exit successfully: `/target/release/build/ncurses-3b76e5da4c5551fd/build-script-build` (exit status: 101)
  --- stdout
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=NCURSESW5_NO_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_powerpc64le-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_powerpc64le_unknown_linux_gnu
  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_powerpc64le-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_powerpc64le_unknown_linux_gnu
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG
  cargo:rerun-if-env-changed=NCURSESW5_STATIC
  cargo:rerun-if-env-changed=NCURSESW5_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_powerpc64le-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_powerpc64le_unknown_linux_gnu
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_powerpc64le-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_powerpc64le_unknown_linux_gnu
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_powerpc64le-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_powerpc64le_unknown_linux_gnu
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=NCURSESW_NO_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_powerpc64le-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_powerpc64le_unknown_linux_gnu
  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_powerpc64le-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_powerpc64le_unknown_linux_gnu
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG
  cargo:rerun-if-env-changed=NCURSESW_STATIC
  cargo:rerun-if-env-changed=NCURSESW_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_powerpc64le-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_powerpc64le_unknown_linux_gnu
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_powerpc64le-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_powerpc64le_unknown_linux_gnu
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_powerpc64le-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_powerpc64le_unknown_linux_gnu
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=SYSROOT
  cargo:rerun-if-env-changed=NCURSESW_STATIC
  cargo:rerun-if-env-changed=NCURSESW_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
  cargo:rustc-link-lib=ncursesw
  cargo:rustc-link-lib=tinfo
  cargo:rustc-link-arg=-Wl,-Bsymbolic-functions
  cargo:rerun-if-env-changed=PKG_CONFIG_powerpc64le-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_powerpc64le_unknown_linux_gnu
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG
  cargo:rerun-if-env-changed=NCURSESW_STATIC
  cargo:rerun-if-env-changed=NCURSESW_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_powerpc64le-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_powerpc64le_unknown_linux_gnu
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_powerpc64le-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_powerpc64le_unknown_linux_gnu
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_powerpc64le-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_powerpc64le_unknown_linux_gnu
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
  OPT_LEVEL = Some("z")
  TARGET = Some("powerpc64le-unknown-linux-gnu")
  HOST = Some("x86_64-unknown-linux-gnu")
  cargo:rerun-if-env-changed=CC_powerpc64le-unknown-linux-gnu
  CC_powerpc64le-unknown-linux-gnu = None
  cargo:rerun-if-env-changed=CC_powerpc64le_unknown_linux_gnu
  CC_powerpc64le_unknown_linux_gnu = Some("powerpc64le-linux-gnu-gcc")
  cargo:rerun-if-env-changed=CRATE_CC_NO_DEFAULTS
  CRATE_CC_NO_DEFAULTS = None
  DEBUG = Some("false")
  CARGO_CFG_TARGET_FEATURE = None
  cargo:rerun-if-env-changed=CFLAGS_powerpc64le-unknown-linux-gnu
  CFLAGS_powerpc64le-unknown-linux-gnu = None
  cargo:rerun-if-env-changed=CFLAGS_powerpc64le_unknown_linux_gnu
  CFLAGS_powerpc64le_unknown_linux_gnu = None
  cargo:rerun-if-env-changed=TARGET_CFLAGS
  TARGET_CFLAGS = None
  cargo:rerun-if-env-changed=CFLAGS
  CFLAGS = None

  --- stderr
  thread 'main' panicked at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ncurses-5.101.0/build.rs:107:10:
  /target/powerpc64le-unknown-linux-gnu/release/build/ncurses-e10af3e277872a3d/out/chtype_size failed: Os { code: 8, kind: Uncategorized, message: "Exec format error" }
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
thomas725 commented 11 months ago

okey, so next I've tried this:

CROSS_CONTAINER_ENGINE=podman cross build --target x86_64-unknown-linux-gnu --release

which worked fine. So my problems are related to the lesser used cpu architecture targets...

thomas725 commented 11 months ago

okey, so now I found that if I replace my code which was the most basic sample from the Cursive CUI library with a simple println!("hello") (and removing the Cursive dependency) I can compile it just fine using cross build --release --target powerpc-unknown-linux-gnu.

So the problem seem to be specific to ncurses (or it's dependencies?) which are used by the Cursive CUI library when compiling for a powerpc archetecture.

thomas725 commented 11 months ago

okey, but copying the resulting binary to my openwrt device and running it there doesn't print the string passed to the println macro, but instead:

-ash: rust-p2p-chat_ppc: not found

thomas725 commented 11 months ago

ah, so after reading this: https://stackoverflow.com/questions/31385121/elf-file-exists-in-usr-bin-but-turns-out-ash-file-not-found

I believe I got differing versions of libc between the build container and the openwrt device, and the build has dynamically linked to that libc present during building.

OpenWRT:

$ opkg list-installed | grep libc
libc - 1.2.3-4
Emilgardis commented 11 months ago

The error you're getting when building ncurses is the same as https://github.com/jeaye/ncurses-rs/issues/184

I'd say what ncurses-rs is doing here is a bit iffy. It compiles using the target cc, and tries to run it.It does then seem like this is not a cross issue, but a general cross-compilation issue for the ncurses crate.

I do know a way to fix this for users of cross (and more) maybe, utilize the runner thats been specified here. Ill see if i can get a fix up for that crate.

Also, you are correct, MPC8540 is powerpc, not ppc64el

Emilgardis commented 11 months ago

There we go, adding

[patch.crates-io]
ncurses = { git = "https://github.com/Emilgardis/ncurses-rs", branch = "fix-runner" }

should fix the issue. Interestingly, I couldn't reproduce the exec error on windows, not sure why :3

as for powerpc, I'm not able to use debian ports nor jessie to install libncurses-dev, something in the repo is fundamentally broken. I'm not sure how to proceed except for maybe to not use ncurses and instead use something rust native like ratatui

thomas725 commented 11 months ago

wow, amazing how much effort you put into solving anonymous peoples problems, thank you for being an amazing human beeing ❤️

For getting to a running binary faster I already downgraded my sample from using Cursive (CUI lib) which is using ncurses, to a only std rust using prtinln!("hello world") - but still failed because of the very old libc version on my OpenWRT router.

Can you help me with that also? Should I create a separate issue for this? I've so far documented my research on that problem here: https://users.rust-lang.org/t/compile-rust-for-powerpc-openwrt-device-with-libc-1-2-3/101147/