cberner / fuser

Filesystem in Userspace (FUSE) for Rust
MIT License
836 stars 114 forks source link

Can not generate statically linked binary. #170

Closed kofj closed 2 years ago

kofj commented 3 years ago

When I use fuser and set target x86_64-unknown-linux-musl will compile failed:

$ cargo build --release --target=x86_64-unknown-linux-musl
   Compiling fuser v0.8.0
error[E0308]: mismatched types
   --> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/fuser-0.8.0/src/mnt/fuse_pure.rs:161:29
    |
161 |             msg_controllen: cmsg_buffer.len(),
    |                             ^^^^^^^^^^^^^^^^^ expected `u32`, found `usize`

error: cannot construct `msghdr` with struct literal syntax due to inaccessible fields
   --> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/fuser-0.8.0/src/mnt/fuse_pure.rs:155:19
    |
155 |         message = libc::msghdr {
    |                   ^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0308`.
error: could not compile `fuser` due to 2 previous errors
cberner commented 3 years ago

I haven't tested fuser on ARM, so good chance it doesn't work. It looks like your platform has a different and incompatible libc. Try building with the libfuse feature flag

kofj commented 3 years ago

I haven't tested fuser on ARM, so good chance it doesn't work. It looks like your platform has a different and incompatible libc. Try building with the feature flaglibfuse

Not ARM, it's x86 with musl libc, that just for static compile binary offered by Rust official.

cberner commented 3 years ago

Oops, my bad. I looked up linux-musl and the first hit was about Arm. Then I didn't read the rest of the error message =P

How did you setup the environment to build against the musl target? I added it to rustup, but that leads to the following message:

  --- stderr
  pkg-config has not been configured to support cross-compilation.

                  Install a sysroot for the target platform and configure it via
                  PKG_CONFIG_SYSROOT_DIR and PKG_CONFIG_PATH, or install a
                  cross-compiling wrapper for pkg-config and set it via
                  PKG_CONFIG environment variable.
  pkg-config has not been configured to support cross-compilation.

                  Install a sysroot for the target platform and configure it via
                  PKG_CONFIG_SYSROOT_DIR and PKG_CONFIG_PATH, or install a
                  cross-compiling wrapper for pkg-config and set it via
                  PKG_CONFIG environment variable.
  thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ()', build.rs:41:22
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
error: build failed
paradigm commented 3 years ago

I also have interest in building static musl-libc fuser-based binaries; this issue affects me as well.

I was able to reproduce the issue kofj described via:

git clone --depth=1 https://github.com/cberner/fuser.git
cd fuser
cargo build --release --target=x86_64-unknown-linux-musl --no-default-features

on Linux, where I believe the --no-default-features opts out of using pkg-build and libfuse, thereby avoiding the need to set up pkg-config for musl. Presumably kofj is also building for Linux where, if I understood fuser's README.md properly, pkg-build and libfuse are not required. In kofj's compilation output, note the reference to fuse_pure.rs rather than one of the libfuse items.


This appears to be the relevant section of fuser's code where cmsg_buffer is a vector whose length is of type usize. It is then used in conditionalized sections as either usize for Linux (musl and glibc) or u32 for OSX. I added a as u32 in the Linux section, mimicking the OSX section, and found it resolved the first error in kofj's output.

Rust's libc appears to have this field size variable not only across Linux and OSX, but a number of libcs and instruction set architectures. I cloned https://github.com/rust-lang/libc and found:

$ rg msg_controllen src/unix/linux_like/linux 
src/unix/linux_like/linux/gnu/mod.rs
87:        pub msg_controllen: ::size_t,

src/unix/linux_like/linux/mod.rs
3058:            + (*mhdr).msg_controllen as usize;

src/unix/linux_like/linux/musl/b32/mod.rs
23:        pub msg_controllen: ::socklen_t,

src/unix/linux_like/linux/uclibc/arm/mod.rs
37:        pub msg_controllen: ::socklen_t,

src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs
212:        pub msg_controllen: ::size_t,

src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs
154:        pub msg_controllen: ::size_t,

src/unix/linux_like/linux/musl/b64/mod.rs
104:        pub msg_controllen: ::socklen_t,

src/unix/linux_like/linux/uclibc/x86_64/mod.rs
210:        pub msg_controllen: ::size_t,

While I can imagine a generalized solution being preferable here, in the worst case I suspect additional, more fine-grain #[cfg(...)] blocks for every such condition would resolve it.


For the second issue, I found what I think is the corresponding Rust libc source here. I think those non-pub padding lines are the issue here. After more digging, I found this and this from others who ran into the same issue. Specifically note this comment which explains the intended workflow which presumably will resolve the issue here.


In case it helps kofj, it could be worth pointing out that it is often possible to statically link with glibc via +crt-static, but this doesn't seem to be working for me either:

$ RUSTFLAGS='-Ctarget-feature=+crt-static' cargo build --release
error: cannot produce proc-macro for `zerocopy-derive v0.3.0` as the target `x86_64-unknown-linux-gnu` does not support these crate types

Even if this worked, it's not clear that it's suitable for kofj's needs; musl-libc has trade-offs other than just static linking friendliness which kofj may find preferable, such as license considerations and binary size considerations.

cberner commented 2 years ago

This was fixed by https://github.com/cberner/fuser/pull/185