{"id":13423231,"url":"https://github.com/japaric/xargo","last_synced_at":"2025-05-14T18:06:46.391Z","repository":{"id":39042734,"uuid":"54798445","full_name":"japaric/xargo","owner":"japaric","description":"The sysroot manager that lets you build and customize `std`","archived":false,"fork":false,"pushed_at":"2023-05-02T22:57:39.000Z","size":695,"stargazers_count":1112,"open_issues_count":64,"forks_count":93,"subscribers_count":22,"default_branch":"master","last_synced_at":"2025-04-13T10:58:00.911Z","etag":null,"topics":["bare-metal","cargo","cross-compilation","no-std","rust","sysroot"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/japaric.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2016-03-26T20:35:55.000Z","updated_at":"2025-04-09T07:08:24.000Z","dependencies_parsed_at":"2022-07-21T21:47:22.851Z","dependency_job_id":"b555d6f0-1f1b-40d2-97f8-e2e789f9c06c","html_url":"https://github.com/japaric/xargo","commit_stats":{"total_commits":377,"total_committers":27,"mean_commits":"13.962962962962964","dds":0.5994694960212201,"last_synced_commit":"68e0ca57cd90837fe02f262f074182f9cfeb6227"},"previous_names":[],"tags_count":56,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/japaric%2Fxargo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/japaric%2Fxargo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/japaric%2Fxargo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/japaric%2Fxargo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/japaric","download_url":"https://codeload.github.com/japaric/xargo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254198514,"owners_count":22030965,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bare-metal","cargo","cross-compilation","no-std","rust","sysroot"],"created_at":"2024-07-31T00:00:25.554Z","updated_at":"2025-05-14T18:06:41.381Z","avatar_url":"https://github.com/japaric.png","language":"Rust","funding_links":[],"categories":["Development tools","Rust","开发工具 Development tools","Tools","开发工具"],"sub_categories":["Embedded","嵌入式 Embedded","Paid and commercially available materials","嵌入式","Community Chat Rooms"],"readme":"# [PSA: Xargo is in maintenance mode](https://github.com/japaric/xargo/issues/193)\n\n[![crates.io](https://img.shields.io/crates/v/xargo.svg)](https://crates.io/crates/xargo)\n[![crates.io](https://img.shields.io/crates/d/xargo.svg)](https://crates.io/crates/xargo)\n\n# `xargo`\n\n\u003e The sysroot manager that lets you build and customize `std`\n\n\u003cp align=\"center\"\u003e\n\u003cimg\n  alt=\"Cross compiling `std` for i686-unknown-linux-gnu\"\n  src=\"assets/xargo.png\"\n  title=\"Cross compiling `std` for i686-unknown-linux-gnu\"\n\u003e\n\u003cbr\u003e\n\u003cem\u003eCross compiling `std` for i686-unknown-linux-gnu\u003c/em\u003e\n\u003c/p\u003e\n\nXargo builds and manages \"sysroots\" (cf. `rustc --print sysroot`). Making it\neasy to cross compile Rust crates for targets that *don't* have binary\nreleases of the standard crates, like the `thumbv*m-none-eabi*` targets. And\nit also lets you build a customized `std` crate, e.g. compiled with `-C\npanic=abort`, for your target.\n\n## Dependencies\n\n- The `rust-src` component, which you can install with `rustup component add\n  rust-src`.\n\n- Rust and Cargo.\n\n## Installation\n\n```\n$ cargo install xargo\n```\n\n## Usage\n\n### `no_std`\n\n`xargo` has the exact same CLI as `cargo`.\n\n```\n# This Just Works\n$ xargo build --target thumbv6m-none-eabi\n   Compiling core v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcore)\n    Finished release [optimized] target(s) in 11.61 secs\n   Compiling lib v0.1.0 (file://$PWD)\n    Finished debug [unoptimized + debuginfo] target(s) in 0.5 secs\n```\n\n`xargo` will cache the sysroot, in this case the `core` crate, so the next\n`build` command will be (very) fast.\n\n```\n$ xargo build --target thumbv6m-none-eabi\n    Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs\n```\n\nBy default, `xargo` will only compile the `core` crate for the target. If you\nneed a bigger subset of the standard crates, specify the dependencies in a\n`Xargo.toml` at the root of your Cargo project (right next to `Cargo.toml`).\n\n```\n$ cat Xargo.toml\n# Alternatively you can use [build.dependencies]\n# the syntax is the same as Cargo.toml's; you don't need to specify path or git\n[target.thumbv6m-none-eabi.dependencies]\ncollections = {}\n\n$ xargo build --target thumbv6m-none-eabi\n   Compiling core v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcore)\n   Compiling alloc v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/liballoc)\n   Compiling std_unicode v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libstd_unicode)\n   Compiling collections v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcollections)\n    Finished release [optimized] target(s) in 15.26 secs\n   Compiling lib v0.1.0 (file://$PWD)\n    Finished debug [unoptimized + debuginfo] target(s) in 0.5 secs\n```\n\n### `std`\n\nYou can compile a customized `std` crate as well, just specify which Cargo\nfeatures to enable.\n\n```\n# Build `std` with `-C panic=abort` (default) and with jemalloc as the default\n# allocator\n$ cat Xargo.toml\n[target.i686-unknown-linux-gnu.dependencies.std]\nfeatures = [\"jemalloc\"]\n\n# Needed to compile `std` with `-C panic=abort`\n$ tail -n2 Cargo.toml\n[profile.release]\npanic = \"abort\"\n\n$ xargo run --target i686-unknown-linux-gnu --release\n    Updating registry `https://github.com/rust-lang/crates.io-index`\n   Compiling libc v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/rustc/libc_shim)\n   Compiling core v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcore)\n   Compiling build_helper v0.1.0 (file://$SYSROOT/lib/rustlib/src/rust/src/build_helper)\n   Compiling gcc v0.3.41\n   Compiling unwind v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libunwind)\n   Compiling std v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libstd)\n   Compiling compiler_builtins v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcompiler_builtins)\n   Compiling alloc_jemalloc v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/liballoc_jemalloc)\n   Compiling alloc v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/liballoc)\n   Compiling rand v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/librand)\n   Compiling std_unicode v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libstd_unicode)\n   Compiling alloc_system v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/liballoc_system)\n   Compiling panic_abort v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libpanic_abort)\n   Compiling collections v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcollections)\n    Finished release [optimized] target(s) in 33.49 secs\n   Compiling hello v0.1.0 (file://$PWD)\n    Finished release [optimized] target(s) in 0.28 secs\n     Running `target/i686-unknown-linux-gnu/release/hello`\nHello, world!\n```\n\nIf you'd like to know what `xargo` is doing under the hood, pass the verbose,\n`-v`, flag to it.\n\n```\n$ xargo build --target thumbv6m-none-eabi -v\n+ \"rustc\" \"--print\" \"target-list\"\n+ \"rustc\" \"--print\" \"sysroot\"\n+ \"cargo\" \"build\" \"--release\" \"--manifest-path\" \"/tmp/xargo.lTBXKnaUGicV/Cargo.toml\" \"--target\" \"thumbv6m-none-eabi\" \"-v\" \"-p\" \"core\"\n   Compiling core v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcore)\n     Running `rustc --crate-name core $SYSROOT/lib/rustlib/src/rust/src/libcore/lib.rs --crate-type lib -C opt-level=3 -C metadata=a5c596f87f7d486b -C extra-filename=-a5c596f87f7d486b --out-dir /tmp/xargo.lTBXKnaUGicV/target/thumbv6m-none-eabi/release/deps --emit=dep-info,link --target thumbv6m-none-eabi -L dependency=/tmp/xargo.lTBXKnaUGicV/target/thumbv6m-none-eabi/release/deps -L dependency=/tmp/xargo.lTBXKnaUGicV/target/release/deps`\n    Finished release [optimized] target(s) in 11.50 secs\n+ \"cargo\" \"build\" \"--target\" \"thumbv6m-none-eabi\" \"-v\"\n   Compiling lib v0.1.0 (file://$PWD)\n     Running `rustc --crate-name lib src/lib.rs --crate-type lib -g -C metadata=461fd0b398821543 -C extra-filename=-461fd0b398821543 --out-dir $PWD/target/thumbv6m-none-eabi/debug/deps --emit=dep-info,link --target thumbv6m-none-eabi -L dependency=$PWD/target/thumbv6m-none-eabi/debug/deps -L dependency=$PWD/lib/target/debug/deps --sysroot $HOME/.xargo`\n    Finished debug [unoptimized + debuginfo] target(s) in 0.5 secs\n```\n\n### Dev channel\n\nOh, and if you want to use `xargo` to compile `std` using a \"dev\" `rustc`, a\nrust compiled from source, you can use the `XARGO_RUST_SRC` environment variable\nto tell `xargo` where the Rust source is.\n\n```\n# `$XARGO_RUST_SRC` must point to the `library` subfolder of a Rust checkout.\n$ export XARGO_RUST_SRC=/path/to/rust/library\n\n$ xargo build --target msp430-none-elf\n```\n\n**NOTE** This also works with the nightly channel but it's not recommended as\nthe Rust source may diverge from what your compiler is able to compile as it may\nmake use of newer features that your compiler doesn't understand.\n\n### Compiling the sysroot with custom rustc flags\n\nXargo uses the same custom rustc flags that apply to the target Cargo project.\nSo you can use either the `RUSTFLAGS` env variable or a `.cargo/config`\nconfiguration file to specify custom rustc flags.\n\n```\n# build the sysroot with debug information\n$ RUSTFLAGS='-g' xargo build --target x86_64-unknown-linux-gnu\n\n# Alternatively\n$ edit .cargo/config \u0026\u0026 cat $_\n[build]\nrustflags = [\"-g\"]\n\n# Then you can omit RUSTFLAGS\n$ xargo build --target x86_64-unknown-linux-gnu\n```\n\n### Compiling the sysroot for a custom target\n\nAt some point you may want to develop a program for a target that's not\nofficially supported by rustc. Xargo's got your back! It supports custom targets\nvia target specifications files, which are not really documented anywhere other\nthan in the [compiler source code][spec-docs]. Luckily you don't need to write\na specification file from scratch; you can start from an existing one.\n\n[spec-docs]: https://github.com/rust-lang/rust/blob/256e497fe63bf4b13f7c0b58fa17360ca849c54d/src/librustc_back/target/mod.rs#L228-L409\n\nFor example, let's say that you want to cross compile a program for a PowerPC\nLinux systems that uses uclibc instead of glibc. There's a similarly looking\ntarget in the list of targets supported by the compiler -- see `rustc --print\ntarget-list` -- and that is `powerpc-unknown-linux-gnu`. So you can start by\ndumping the specification of that target into a file:\n\n``` console\n$ rustc -Z unstable-options --print target-spec-json --target powerpc-unknown-linux-gnu | tee powerpc-unknown-linux-uclibc.json\n```\n\n``` js\n{\n  \"arch\": \"powerpc\",\n  \"data-layout\": \"E-m:e-p:32:32-i64:64-n32\",\n  \"dynamic-linking\": true,\n  \"env\": \"gnu\",\n  \"executables\": true,\n  \"has-elf-tls\": true,\n  \"has-rpath\": true,\n  \"is-builtin\": true,\n  \"linker-flavor\": \"gcc\",\n  \"linker-is-gnu\": true,\n  \"llvm-target\": \"powerpc-unknown-linux-gnu\",\n  \"max-atomic-width\": 32,\n  \"os\": \"linux\",\n  \"position-independent-executables\": true,\n  \"pre-link-args\": {\n    \"gcc\": [\n      \"-Wl,--as-needed\",\n      \"-Wl,-z,noexecstack\",\n      \"-m32\"\n    ]\n  },\n  \"target-endian\": \"big\",\n  \"target-family\": \"unix\",\n  \"target-pointer-width\": \"32\",\n  \"vendor\": \"unknown\"\n}\n```\n\nOne of the things you'll definitively want to do is drop the `is-builtin` field\nas that's reserved for targets that are defined in the compiler itself. Apart\nfrom that the only modification you would have to in this case is change the\n`env` field from `gnu` (glibc) to `uclibc`.\n\n``` diff\n   \"arch\": \"powerpc\",\n   \"data-layout\": \"E-m:e-p:32:32-i64:64-n32\",\n   \"dynamic-linking\": true,\n-  \"env\": \"gnu\",\n+  \"env\": \"uclibc\",\n   \"executables\": true,\n   \"has-elf-tls\": true,\n   \"has-rpath\": true,\n-  \"is-builtin\": true,\n   \"linker-flavor\": \"gcc\",\n   \"linker-is-gnu\": true,\n   \"llvm-target\": \"powerpc-unknown-linux-gnu\",\n```\n\nOnce you have your target specification file you only have to call Xargo with\nthe right target triple; make sure that the specification file is the same\nfolder from where you invoke Xargo because that's where rustc expects it to be.\n\n``` console\n$ ls powerpc-unknown-linux-uclibc.json\npowerpc-unknown-linux-uclibc.json\n\n$ xargo build --target powerpc-unknown-linux-uclibc\n```\n\nYour build may fail because if rustc doesn't support your target then it's\nlikely that the standard library doesn't support it either. In that case you\nwill have to modify the source of the standard library. Xargo helps with that\ntoo because you can make a copy of the original source -- see `rustc --print\nsysroot`, modify it and then point Xargo to it using the `XARGO_RUST_SRC` env\nvariable.\n\n### Multi-stage builds\n\nSome standard crates have implicit dependencies between them. For example, the\n`test` crate implicitly depends on the `std`. Implicit here means that the test\ncrate Cargo.toml [doesn't list std as its dependency][test]. To compile a\nsysroot that contains such crates you can perform the build in stages by\nspecifying which crates belong to each stage in the Xargo.toml file:\n\n[test]: https://github.com/rust-lang/rust/blob/1.17.0/src/libtest/Cargo.toml\n\n``` toml\n[dependencies.std]\nstage = 0\n\n[dependencies.test]\nstage = 1\n```\n\nThis will compile an intermediate sysroot, the stage 0 sysroot, containing the\n`std` crate, and then it will compile the `test` crate against that intermediate\nsysroot. The final sysroot, the stage 1 sysroot, will contain both the `std` and\n`test` crates, and their dependencies.\n\n### Creating a sysroot with custom crates\n\nXargo lets you create a sysroot with custom crates. You can virtually put any\ncrate in the sysroot. However, this feature is mainly used to create [alternative\n`std` facades][rust-3ds], and to replace the `test` crate with [one that supports\n`no_std` targets][utest]. To specify the contents of the sysroot simply list the\ndependencies in the Xargo.toml file as you would do with Cargo.toml:\n\n[steed]: https://github.com/rust3ds/rust3ds-template\n[utest]: https://github.com/japaric/utest\n\n``` toml\n# First build some standard crates.\n[dependencies.alloc]\n[dependencies.panic_abort]\n[dependencies.panic_unwind]\n\n# Then build our custom facade. It (implicitly) requires the crates above to\n# already be in the sysroot, so we need to set the `stage`.\n[dependencies.std]\ngit = \"https://github.com/rust3ds/ctru-rs\"\nstage = 1\n```\n\n### Patching sysroot crates\n\nXargo also supports the `patch` feature from Cargo. This allows you to force the use\nof a custom crate throughout your sysroot's dependency tree. This can be especially\nuseful to force the use of a custom `libc` or `compiler_builtins` without having to\ndo intrusive changes to every transitive dependency.\n\n\n``` toml\n[patch.crates-io.libc]\npath = \"path/to/custom/libc\"\n```\n\nNotice that you should not list patched crates as `[dependencies]`!\n`[dependencies]` determines which crates are built in the first place; `[patch]`\nlets you replace some of their (transitive) dependencies with your own choice.\nHaving a crate listed in both will likely lead to crate duplication.\n\n### Check-only sysroot build\n\nXargo supports performing a 'check build' of the syroot\nvia the `xargo-check` command. This command is invoked exactly\nlike `xargo`, but will invoke `cargo check` instead of `cargo build`\nwhen building the sysroot.\n\nThis is only useful for very specialized applicationsm like Miri.\nThe resulting libstd will *not* be useable in a normal build, since codegen\nwill not be performed. You should almost always run `xargo check` (note the space),\nwhich will perform a normal sysroot build, followed by a 'check' build of *your application*\n\n## Caveats / gotchas\n\n- Xargo won't build a sysroot when used with stable or beta Rust. This is\n  because `std` and other standard crates depend on unstable features so it's\n  not possible to build the sysroot with stable or beta.\n\n- `std` is built as rlib *and* dylib. The dylib needs a panic library and an\n  allocator.  If you do not specify the `panic-unwind` feature, you have to set\n  `panic = \"abort\"` in `Cargo.toml`.\n\n- To build without the `jemalloc` feature include the following in `Xargo.toml`:\n\n  ``` toml\n  [dependencies.std]\n  features = [\"force_alloc_system\"]\n  ```\n\n  What this flag means is that every program compiled with this libstd can only use the system\n  allocator. If your program tries to set its own allocator, compilation will fail because now two\n  allocators are set (one by libstd, one by your program). For some further information on this\n  issue, see\n  [rust-lang/rust#43637](https://github.com/rust-lang/rust/issues/43637#issuecomment-320463578).\n\n- It's recommended that the `--target` option is always used for `xargo`. This is because it must\n  be provided even when compiling for the host platform due to the way cargo handles compiler\n  plugins (e.g. `serde_derive`) and build scripts (`build.rs`). This also applies to how all of the\n  dependant crates get compiled that use compiler plugins or build scripts. You can determine your\n  host's target triple with `rustc -vV`. On *nix, the following rune will extract the triple:\n  `rustc -vV | egrep '^host: ' | sed 's/^host: //'`.\n\n- Remember that `core` and `std` will get implicitly linked to your crate but *all the other sysroot\n  crates* will *not*. This means that if your Xargo.toml contains a crate like `alloc` then you will\n  have to add a `extern crate alloc` *somewhere* in your dependency graph (either in your current\n  crate or in some of its dependencies).\n\n- Remember that rustc will always implicitly link `compiler_builtins` into your final binary, but\n  won't make it available for `use` the same way `core` and `std` are. So if you need to manually\n  call a `compiler_builtins` function, you will still need to manually add an\n  `extern crate compiler_builtins` within your crate.\n\n- Care must be taken not to end up with any \"top-level\" crates (`core`, `std`, `compiler-builtins`)\n  twice in the sysroot. Doing so will cause cargo to error on build with a message like\n  `multiple matching crates for core`. Duplicate crates in the sysroot generally occur when the same\n  crate is built twice with different features as part of a multi-stage build.\n\n## License\n\nLicensed under either of\n\n- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or\n  http://www.apache.org/licenses/LICENSE-2.0)\n- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)\n\nat your option.\n\n### Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in the work by you, as defined in the Apache-2.0 license, shall be\ndual licensed as above, without any additional terms or conditions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaparic%2Fxargo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjaparic%2Fxargo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaparic%2Fxargo/lists"}