Repository navigation
Description
When I upgraded to a recent toolchain (2021-03-25) and updated some crates to today's latest as a result, I started getting errors about missing libc::pwrite64() for my uclibc-based target. I haven't tracked it all the way back to see when the error first started happening, but I think the issue is that the standard library source requires pwrite64() for non-Android Linux:
https://github.com/rust-lang/rust/blob/48691ea6e639640f110b43e33d4aba1f07e7415c/library/std/src/sys/unix/fd.rs#L167-L183
#[cfg(target_os = "linux")]
use libc::pwrite64;
cvt(pwrite64(fd, buf, count, offset))Whereas pwrite64() is disallowed for uclibc in the libc crate:
libc/src/unix/linux_like/mod.rs
Lines 1671 to 1685 in f913fc5
| cfg_if! { | |
| if #[cfg(not(target_env = "uclibc"))] { | |
| extern "C" { | |
| pub fn preadv64( | |
| fd: ::c_int, | |
| iov: *const ::iovec, | |
| iovcnt: ::c_int, | |
| offset: ::off64_t, | |
| ) -> ::ssize_t; | |
| pub fn pwrite64( | |
| fd: ::c_int, | |
| buf: *const ::c_void, | |
| count: ::size_t, | |
| offset: off64_t, | |
| ) -> ::ssize_t; |
However, the companion function pread64() is permitted for uclibc:
libc/src/unix/linux_like/mod.rs
Lines 1543 to 1548 in f913fc5
| pub fn pread64( | |
| fd: ::c_int, | |
| buf: *mut ::c_void, | |
| count: ::size_t, | |
| offset: off64_t, | |
| ) -> ::ssize_t; |
The actual pwrite64() function is available on my uclibc target. Considering that libc contains a SYS_pwrite64 value for uclibc targets, I suspect this is just an oversight in the libc crate, and that pwrite64() was not intended to be caveated by cfg(not(target_env = "uclibc")). Unless there is some other reason for disallowing pwrite64() on uclibc-based Linux targets, could this function be promoted to work for uclibc variants?
Activity
Auto merge of #2131 - JohnTitor:pwrite64-uclibc, r=Amanieu
JohnTitor commentedon Mar 30, 2021
Thanks for reporting, yeah, I think there's no reason to disable
pwrite64on uclibc. Submitted #2131 as a fix.drmikehenry commentedon Apr 2, 2021
I tested with a custom copy of
stdusing this newlibcand it works great. Thanks for the lightning-fast fix.JohnTitor commentedon Apr 2, 2021
Anytime :)
zvirja commentedon Apr 10, 2021
@drmikehenry Could you please share an example of how you consumed this fix? I tried playing with
xargoand the patch feature, but no luck 😟I created a PR to rust to update the
libcdep, but want to consume it in the meanwhile.Thanks
drmikehenry commentedon Apr 11, 2021
@zvirja I'd be happy to post the steps I followed once I retrieve them from the office early next week. Mostly I just followed somebody's tutorial on re-compiling the Rust standard library, but there are indeed a number of steps involved and without notes I'd be lost :-)
drmikehenry commentedon Apr 14, 2021
@zvirja I'm having trouble replicating this change with my home setup, but it appears that your pull request has gone through already, so perhaps you can use a new nightly toolchain to get the libc updates.
drmikehenry commentedon Apr 15, 2021
@zvirja You probably won't need this if you use the very latest Rust sources; commit
e41f378f825488a537b024fc3ed599d9c12fda96bumped thelibcversion dependency to0.2.93. But in case you want to use an older toolchain with the new libc, here are the steps I used to testlibc-0.2.92.First, install a nightly toolchain and make it the default:
Clone Rust sources and enter
rustdirectory:Optionally, checkout a branch or commit hash as the desired starting point, perhaps using the hash from the active compiler:
rustc -vV | grep commit-hashwith output:
Checkout this commit:
Initialize and update the submodules:
For use with Cargo's build-std feature, the Rust sources need to live in the expected location below
~/.rustup. Using this example toolchain (nightly-2021-03-01), enter the toolchain'srustlibdirectory, createsrc(if necessary), and entersrc:If there's already a
rust/directory, it must be deleted or renamed out of the way:Create a symlink to the cloned Rust sources:
ln -s ~/projects/custom-std/rust rustCreate an example project to test:
Add the following to
Cargo.toml:At this point, Cargo's build-std feature should work:
Building with Xargo should work as well, if a
Xargo.tomlis created, e.g.:Then install Xargo and build:
With Xargo, it's not necessary to place the sources below
~/.rustup; instead, an environment variable can be set to point directly to the cloned sources, e.g.:You might need to remove
~/.xargoto force a rebuild of everything.To use
libc-0.2.92, clone thelibcsource and checkout the0.2.92branch:Edit the Rust standard library's
Cargo.tomlfile to use this new version; the changes are shown via this command:with sample output:
The change involves requesting
version = "=0.2.92"(matching the version inlibc/Cargo.toml) and setting thepathto point to thelibcworking copy (note that relative paths are taken relative to the directory containinglibrary/std/Cargo.toml).It may be necessary to clean the workspace and remove the
~/.xargotree before rebuilding::rm -rf ~/.xargo cargo clean xargo build \ --target x86_64-unknown-linux-gnu \ --releaseThe indication that the local copies are being used is in these lines of output:
The reason I couldn't replicate this earlier is that I'd been using
version = "0.2.92"to request version0.2.92. I'd mistakenly thought this would request the version exactly, but it turns out that this is equivalent to a "caret requirement""^0.2.92", which asks Cargo to use the newest version of the form0.2.xforx >= 92. The day I initially tried this, the newest version on crates.io was0.2.92, so that's the version Cargo selected. Since I'd placed version0.2.92at thepathlocation, Cargo used my local working copy. But when I later tried to replicate this,libc-0.2.93had been published. Cargo selected0.2.93as the best version, then skipped over my local working copy oflibcbecause it contained the wrong version (0.2.92).