rust-lang / cargo

The Rust package manager
https://doc.rust-lang.org/cargo
Apache License 2.0
12.74k stars 2.42k forks source link

Value too large for defined data type; class=Os (2) (but only when using a build.rs) #9545

Open leoniloris opened 3 years ago

leoniloris commented 3 years ago

Problem

I see the error Value too large for defined data type; class=Os (2) when building with cargo on a github action IF AND ONLY IF I have a file build.rs (even if this file is literally just an empty function). When I don't have this file, the problem disappears (the file is doing nothing functionally. it is literally empty)

Steps fully reproducible here:

with only two commits (and two runs on the actions), so one can see that literally, when I remove the file build.rs , the build goes through.

Possible Solution(s)

Remove the file build.rs

Notes

cargo version 1.52.0 (69767412a 2021-04-21)


same issue here https://github.com/uraimo/run-on-arch-action/issues/46 but since I don't know if it is a cargo issue or github actions issue, I'll post on both (for now. I'll close the unrelated one when we discover what's happening)

ehuss commented 3 years ago

Thanks for the detailed reproduction! I believe this is a duplicate of #8719. There is some more detail there, and a link to the qemu bug. It looks like there was some activity just a few months ago about getting new APIs into the Linux kernel, but it sounds like it stalled. I'm still unsure about the libgit2 changes that could potentially make this work.

leoniloris commented 3 years ago

Hello @ehuss , thanks for the quick reply!

So, not really a duplicate, since the problem happens ONLY when I add a build.rs file.

So, the main problem is that this happens only when I use a build.rs file. About the qemu bug, I'm already kinda past that by working around with a tempfs filesystem: https://github.com/leoniloris/test-actions/blob/master/.github/workflows/build.yml#L41-L42 and https://github.com/leoniloris/test-actions/blob/master/.github/workflows/build.yml#L36-L37 .

Does something different on the build process happen when I use build.rs ?

ehuss commented 3 years ago

Oh, yea, sorry, I should have clarified. You should be able to avoid it by printing cargo:rerun-if-changed=build.rs (or rerun-if-changed any files your build script depends on). The reason it happens is that without rerun-if-changed, cargo takes a conservative approach of assuming the build script should be rerun if any file in the package changes. In order to detect that, it uses git to guide it towards which files to check. If you pass rerun-if-changed, then it won't use git to scan.

leoniloris commented 3 years ago

cargo:rerun-if-changed=build.rs (or

Humm, unfortunately, it is still not working, even after adding a line for return if changed https://github.com/leoniloris/test-actions/actions (last two jobs) @ehuss

ehuss commented 3 years ago

Oh, hmm, sorry about that! It does not appear to be working as I expected. There's an edge case during the first build (when target is empty) that it still runs the git scan.

Not sure if you can run it in that tmpfs or not. Or if you can maybe cross compile outside of qemu.

diabloxenon commented 3 years ago

Hi to everyone!

Coincidentally as I mentioned here in #8719, I also faced similar issue yesterday. Historically, there have been issues like GoogleContainerTools/distroless#513 which fixed issues with glibc by adopting to multiarch support i.e. (musl-glibc) like mentioned in GoogleContainerTools/distroless#225 that is slightly different but similar to our case.

Hence, for now there are only three practical solutions remain to this issue for building 32-bit ARM binaries/libraries (armv7).

  1. First solution, as previously mentioned by @jdrouet in docker/buildx#395, by copying the file that needs to be fetched outside of qemu environment i.e. ( environment), it can be copied later on as this problem only occurs when fetching the files from cargo repository from an armv7 emulator, as mentioned earlier by me in #8719. To resolve this, here is this link. Use the parameter --platform=$BUILDPLATFORM while building for supplying the host's architecture to its context. Credits goes to @jdrouet for this solution.
  2. Second solution, although not feasible for large projects, but if you are currently experimenting on, then I must suggest to build on an armv7 platform (i.e. RPi 2/3). That will surely build it perfectly.
  3. Third solution is the most practical one, that is to forsake the whole architecture as there are and will be countless breaking changes and its not worth the headache to maintain each of their unresolved dependencies. By forsaking it, not only your project is being more futureproof and secure but as the trend goes on, 64-bit apps based on architectures like (aarch64, x86_64, mips64, risc-v etc.) are current standard and are widely tested and supported by each major platform. PLEASE NOTE: If you still have something that is real critical to you or your business, then please refer to my earlier points. Sorry to break it to you mate! :(

Lastly, a good experimentation for someone might be to cross-compile an armv7 application on an i686 machine using qemu, just for the sake of curiosity.

EDIT: More details of this problem attached here. There seems to be possibility that problem underlying the QEMU is glibc which could be currently due to uClibc that I mentioned earlier has been fixed in GoogleContainerTools/distroless#513 by multiarch support in musl-glibc.

Another one is rather old but have similarities with our case too enigmagroup/enigmabox-openwrt#10

leoniloris commented 3 years ago

I also faced similar issue yesterday

Hello @diabloxenon . As I have stated on the description of this issue, I can already build it for multiple architectures, using tmpfs. The problem appears ONLY when I add a build.rs file.

diabloxenon commented 3 years ago

Hi @leoniloris. I do understand the problem residing with libgit2 and how you bypassed it with tempfs workaround.

Even though, this problem occurs on different places due to latter using readdir API from uClibc instead of musl-glibc which inherently uses a different solution for supporting multiple architectures.

The point is, there are many dependencies underneath the OS which are using uClibc variant, including and not limited to libgit2. That's why in my previous post, I suggested about either using a physical device instead of emulation or just leaving this platform for now until the patch merges with kernel.

For more information about this problem, read here