New target armv7-unknown-linux-uclibceabihf

Continuing the discussion from How to specify a private repository for one library like libc?:

I'm trying to create a new target (armv7-unknown-linux-uclibc) since I need it for my project. If I'm able to get it to work, I'd be happy to submit a PR, but I need help with it. In the process of trying to get it to work I realized I need to modify libc, but encountered the exact issue that @baoshan encountered in the above topic. The steps to reproduce are in his last post.

The basic problem is that even though I checked out the exact same version of libc locally, just adding the patch in Cargo.toml like so:

[patch.crates-io]

libc = { path = '.../libc' }

yields the error. Shouldn't it just work since the libc I checked out is exactly the same version as the one needed to build rust? Am I missing something?

Warnings for non-path-dependencies are capped so that you don't see them. When you add a path patch, the warnings start to be issued. By default, x.py denies warnings. You can set deny-warnings = false in config.toml to allow the warnings.

I believe the no_std warning would be pretty easy to fix, I think changing it to #![cfg_attr(not(feature = "rustc-dep-of-std"), no_std)] should work.

The cfg_target_vendor issue could be handled by the version detection in build.rs.

2 Likes

@ehuss thank you very much for your help! I've been struggling with this a lot. Hopefully I'll be able to figure it out from here on.

@tsidea: Did you make progress? I am working on the same target specification, and I thought maybe we could collaborate. Currently, I have xargo and a rustc target spec set up, but my final link is failing with undefined reference to '_Unwind_Backtrace'. If I amend the target spec to include -lgcc_eh with the linker invocation, I get multiple definition of '__aeabi_unwind_cpp_pr0'. These are pieces of the C and C++ runtime which I'm not familiar with, but near as I can tell they should be provided by the compiler. However, it's not clear to me why uclibc wants to provide some of them but not others.

Yes, I have a working compiler for this target.

Awesome! Of course!

I had the same issue. I believe it may be related to 47493. I couldn't fix it, I was able to just avoid it.

I've managed to get around it by checking out version 1.47.0 of rust and using that. I also needed to make some modifications to libc. These modifications have already been approved and included in libc.

Right now I'm waiting for a new release of libc which will have my fix for uclibc and for that version to be used by the rust compiler. At that point I'm thinking of attacking the undefined reference to '_Unwind_Backtrace' issue if that will still exist at that point.

Until then, if you want, you can checkout this branch which is already setup to build the compiler for the armv7-unknown-linux-uclibceabihf. You just need to modify the config.toml file and add the location to the armv7-unknown-linux-uclibceabihf toolchain where you see /path/to/toolchain/bin/. Then run x.py build --stage 2 or x.py dist as per this guide. As you can see in the Cargo.toml and Cargo.lock files, I just added an override for the libc library to point to my own fork of libc that contains the fix. Other than that, I just added an armv7_unknown_linux_uclibceabihf.rs file to the spec folder that is based on the armv7_unknown_linux_gnueabihf.rs file.

2 Likes

One more thing. I realized my target is actually armv7-unknown-linux-uclibceabihf. I hope this is still helpful for you.

This is so helpful! My target is armv7-unknown-linux-uclibcgnueabihf, but I think the differences will be minor enough. I will follow your instructions above and see where I get!

The C toolchain I'm using is armv7-unknown-linux-uclibcgnueabihf as well. I just didn't include the gnu in uclibcgnueabihf since it doesn't seem like any other musl or uclibc targets in rust include the gnu in gnueabihf. We'll see what the exact name will be later.

1 Like

@skrap how's it going? Are you coming along with the build?

I did a build based on your repository and the questions above, thanks! The rust compiler and rustup distribution build succeeded, and now I'm working on getting a trivial executable compiled. It's not using the correct linker for cross compilation, so I'm getting errors like

/usr/bin/ld: rust-uclibc/app/target/armv7-unknown-linux-uclibceabihf/debug/deps/app-05bfadf49097eef6.1mzamt4isa78efz.rcgu.o: error adding symbols: file in wrong format

I need to convince cargo to use the correct linker. Then we'll see what the next issue is :slight_smile:

A trivial program now builds and links! I've tried something using a bunch of crates, but things are looking good. Once I can make something non-trivial run, I will report back here.

Thanks again for sharing your wisdom on this! I hope I can return the favor :slight_smile:

I'm glad! I can report that my project is a non-trivial project that includes async/await, tokio, tungstenite (websockets), hyper, serde and it all works.

I needed ENOTSUP, which wasn't defined, so I just submitted this PR to libc.

ooo boy nix is not really happy with uclibc :boom: I will have to do some work there.

I looked at your PR request and I realized you made the same mistake I did at the beginning. You need to spend some time carefully reading the contribution instructions of libc, especially this:

This means that for each platform that libc supports, the path from a leaf module to the root will contain all bindings for the platform in question. Consequently, this indicates where an API should be added! Adding an API at a particular level in the hierarchy means that it is supported on all the child platforms of that level. For example, when adding a Unix API it should be added to src/unix/mod.rs , but when adding a Linux-only API it should be added to src/unix/linux_like/linux/mod.rs .

Basically, it's all a bunch of #if defined ABC #endif. libc will compile different sections given different triples. The uclibc/mips will only compile if in mips architecture and uclibc env. Find the if_cfg statements to guide you.

Thanks. I see that. There's some number of definitions which currently live at the uclibc/mips/mod.rs level which I believe could instead be hoisted to the uclibc/mod.rs level. It's not clear why certain constants ended up in either place, at least to me. However I'm definitely not a uclibc expert (honestly I've never worked with it before) and I am wary about making changes like that as a newcomer to the ecosystem. I'm going to try to track back through the uclibc build process to see if there's a mechanical way to update the uclibc/arm/mod.rs file, or if I'm going to be digging constants out by hand all day :slight_smile:

Thanks again for your helpful comments!

I also wonder why uclibc isn't under the linux-like subdirectory, alongside gnu and musl. That does seem like the proper place for it, given its goals of being a drop-in replacement for glibc.

ok, i got nix building with a lot of libc changes. i'll see about a PR once I get the tests passing.

Just make sure all your additions are present in uclibc.

Passes all libc tests with latest uclibc on arm vexpress cortex a9 (in qemu).

Working on nix next.

1 Like