zargo 0.1.1

The sysroot manager that lets you build and customize `std`
Documentation
[![Crates.io](https://img.shields.io/crates/v/zargo.svg?style=for-the-badge)](https://crates.io/crates/zargo)
[![License](https://img.shields.io/crates/l/zargo.svg?style=for-the-badge)](https://github.com/rust-lang/zargo)
[![CI](https://img.shields.io/github/actions/workflow/status/rust-lang/zargo/ci.yml?branch=main&style=for-the-badge)](https://github.com/rust-lang/zargo/actions)
[![Docs](https://img.shields.io/docsrs/zargo?style=for-the-badge)](https://docs.rs/zargo)

# ๐Ÿš€ `zargo`

> ๐Ÿ”ง The sysroot manager that lets you build and customize `std`

**Note:** Zargo is a hard fork of [xargo](https://github.com/japaric/xargo).

Zargo builds and manages "sysroots" (cf. `rustc --print sysroot`). Making it
easy to cross compile Rust crates for targets that _don't_ have binary
releases of the standard crates, like the `thumbv*m-none-eabi*` targets. And
it also lets you build a customized `std` crate, e.g. compiled with `-C
panic=abort`, for your target.

## ๐Ÿ“‹ Dependencies

- The `rust-src` component, which you can install with `rustup component add
rust-src`.

- Rust and Cargo.

## ๐Ÿ“ฆ Installation

```bash
cargo install zargo
```

## ๐Ÿš€ Usage

### ๐Ÿ”ฅ `no_std`

`zargo` has the exact same CLI as `cargo`.

```bash
# This Just Works
zargo build --target thumbv6m-none-eabi
```

```
  Compiling core v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcore)
   Finished release [optimized] target(s) in 11.61 secs
  Compiling lib v0.1.0 (file://$PWD)
   Finished debug [unoptimized + debuginfo] target(s) in 0.5 secs
```

`zargo` will cache the sysroot, in this case the `core` crate, so the next
`build` command will be (very) fast.

```bash
$ zargo build --target thumbv6m-none-eabi
    Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
```

By default, `zargo` will only compile the `core` crate for the target. If you
need a bigger subset of the standard crates, specify the dependencies in a
`Zargo.toml` at the root of your Cargo project (right next to `Cargo.toml`).

```toml
# Alternatively you can use [build.dependencies]
# the syntax is the same as Cargo.toml's; you don't need to specify path or git
[target.thumbv6m-none-eabi.dependencies]
collections = {}
```

```bash
$ zargo build --target thumbv6m-none-eabi
   Compiling core v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcore)
   Compiling alloc v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/liballoc)
   Compiling std_unicode v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libstd_unicode)
   Compiling collections v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcollections)
    Finished release [optimized] target(s) in 15.26 secs
   Compiling lib v0.1.0 (file://$PWD)
    Finished debug [unoptimized + debuginfo] target(s) in 0.5 secs
```

### ๐Ÿ“š `std`

You can compile a customized `std` crate as well, just specify which Cargo
features to enable.

```toml
# Build `std` with `-C panic=abort` (default) and with jemalloc as the default
# allocator
[target.i686-unknown-linux-gnu.dependencies.std]
features = ["jemalloc"]
```

```toml
# Needed to compile `std` with `-C panic=abort`
[profile.release]
panic = "abort"
```

```bash
zargo run --target i686-unknown-linux-gnu --release
```

If you'd like to know what `zargo` is doing under the hood, pass the verbose,
`-v`, flag to it.

```bash
zargo build --target thumbv6m-none-eabi -v
```

### ๐Ÿงช Dev channel

To use `zargo` with a development version of `rustc` (compiled from source), set the `ZARGO_RUST_SRC` environment variable to specify the location of your Rust source code.

```bash
# `$ZARGO_RUST_SRC` must point to the `library` subfolder of a Rust checkout.
export ZARGO_RUST_SRC=/path/to/rust/library

zargo build --target msp430-none-elf
```

> โš ๏ธ **NOTE** This also works with the nightly channel but it's not recommended as
> the Rust source may diverge from what your compiler is able to compile as it may
> make use of newer features that your compiler doesn't understand.

### โš™๏ธ Compiling the sysroot with custom rustc flags

Zargo uses the same custom rustc flags that apply to the target Cargo project.
So you can use either the `RUSTFLAGS` env variable or a `.cargo/config`
configuration file to specify custom rustc flags.

```bash
# build the sysroot with debug information
RUSTFLAGS='-g' zargo build --target x86_64-unknown-linux-gnu
```

```toml
# Alternatively
[build]
rustflags = ["-g"]
```

### ๐ŸŽฏ Compiling the sysroot for a custom target

At some point you may want to develop a program for a target that's not
officially supported by rustc. Zargo's got your back! It supports custom targets
via target specifications files, which are not really documented anywhere other
than in the [compiler source code][spec-docs].

[spec-docs]: https://github.com/rust-lang/rust/blob/256e497fe63bf4b13f7c0b58fa17360ca849c54d/src/librustc_back/target/mod.rs#L228-L409

For example, let's say that you want to cross compile a program for a PowerPC
Linux systems that uses uclibc instead of glibc. You can start by dumping the
specification of a similar target into a file:

```bash
rustc -Z unstable-options --print target-spec-json --target powerpc-unknown-linux-gnu | tee powerpc-unknown-linux-uclibc.json
```

Once you have your target specification file you only have to call Zargo with
the right target triple:

```bash
zargo build --target powerpc-unknown-linux-uclibc
```

### ๐Ÿ”„ Multi-stage builds

Some standard crates have implicit dependencies between them. To compile a
sysroot that contains such crates you can perform the build in stages:

```toml
[dependencies.std]
stage = 0

[dependencies.test]
stage = 1
```

### ๐Ÿ“ฆ Creating a sysroot with custom crates

Zargo lets you create a sysroot with custom crates:

```toml
# First build some standard crates.
[dependencies.alloc]
[dependencies.panic_abort]
[dependencies.panic_unwind]

# Then build our custom facade.
[dependencies.std]
git = "https://github.com/rust3ds/ctru-rs"
stage = 1
```

### ๐Ÿ”ง Patching sysroot crates

Zargo supports the `patch` feature from Cargo:

```toml
[patch.crates-io.libc]
path = "path/to/custom/libc"
```

### โœ… Check-only sysroot build

Zargo supports performing a 'check build' of the sysroot via the `zargo-check` command:

```bash
zargo-check build --target thumbv6m-none-eabi
```

## โš ๏ธ Caveats / gotchas

- Zargo won't build a sysroot when used with stable or beta Rust. This is
  because `std` and other standard crates depend on unstable features so it's
  not possible to build the sysroot with stable or beta.

- `std` is built as rlib _and_ dylib. The dylib needs a panic library and an
  allocator. If you do not specify the `panic-unwind` feature, you have to set
  `panic = "abort"` in `Cargo.toml`.

- To build without the `jemalloc` feature include the following in `Zargo.toml`:

  ```toml
  [dependencies.std]
  features = ["force_alloc_system"]
  ```

- It's recommended that the `--target` option is always used for `zargo`.

- Remember that `core` and `std` will get implicitly linked to your crate but _all the other sysroot
  crates_ will _not_.

- Remember that rustc will always implicitly link `compiler_builtins` into your final binary.

- Care must be taken not to end up with any "top-level" crates (`core`, `std`, `compiler-builtins`)
  twice in the sysroot.

## ๐Ÿ“„ License

Licensed under either of

- Apache License, Version 2.0 ([LICENSE-APACHE]./LICENSE-APACHE
- MIT license [LICENSE-MIT]./LICENSE-MIT

at your option.

### ๐Ÿค Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.