Specific profiles for workspace members - rust

Is it possible to specify specific profiles for members of a workspace?
If I write a profile into the member Cargo.toml I get:
warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
I also tried to put a specific profile into workspace root's Cargo.toml:
[profile.release]
opt-level = 3
[profile.release.hal]
# optimizer kills assembly code
opt-level = 1
However, it seems to be ignored too, as the applied options in the the verbose output show:
Running `rustc --crate-name hal src/hal/lib.rs --crate-type lib -C opt-level=3 --emit=dep-info,link [...]
Is there any other way beside avoiding workspaces at all?

This is now supported and stabilized since Rust 1.43:
[profile.release]
opt-level = 3
[profile.release.package.hal]
# optimizer kills assembly code
opt-level = 1
See: https://doc.rust-lang.org/cargo/reference/profiles.html#overrides

Related

Empty rust file creates massive WASM build

Building the following rust file is producing a binary of 720KB.
I would expect a virtually empty build, what am I missing here? Is the full core libary getting included somehow?
Here's the code
#![no_std]
#[panic_handler]
fn handle_panic(_: &core::panic::PanicInfo) -> ! {
unreachable!()
}
And the cargo.toml
[package]
name = "wasm_test"
version = "0.0.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[profile.release]
opt-level = 's'
lto = true
And the command I'm using to build:
cargo build --target wasm32-unknown-unknown
Ok turns out I had two problems:
I was building this as a crate in a workspace, and that apparently ignores crate specific profiles
When i copied the crate out to mess around with it and isolate the problem, i was forgetting to add the --release flag, thanks #isaactfa.
In other cases i have received this warning.
warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
for some reason I wasn't getting it when doing the workspace builds.
I've added the crate to the workspace exclude list and am building it seperately, and its compiling to a far more appropriate 411 bytes, down from 727151 bytes.

How to fix "error: could not find native static library `c`, perhaps an -L flag is missing?" or how do I compile rust binaries for openwrt?

I'm wanting to compile binaries for openwrt 19.07.7 on mips with limited space.
OpenWrt 19.07.7, r11306-c4a6851c72
-----------------------------------------------------
root#OpenWrt:~# df /
Filesystem 1K-blocks Used Available Use% Mounted on
overlayfs:/overlay 3392 1276 2116 38% /
root#OpenWrt:~# ls -s
662 crosshello 3 helloworld
root#OpenWrt:~# ldd --version
musl libc (mips-sf)
Version 1.1.24
Above you can see the size of crosshello (cross compiled using rust) and helloworld (cross compiled using gcc). There is limited space on the target as you can see.
I followed https://github.com/japaric/rust-cross and it works. However I had to reduce the size of the binary to get it to fit. Following https://github.com/johnthagen/min-sized-rust I got the binary (the "Cross compiling with cargo" hello world with clap from the first link) to fit. I haven't compiled my own program yet. I got stuck a the "Optimize libstd with build-std" section.
I'm getting the above error:
$ cargo +nightly build -Z build-std=std,panic_abort --target=mips-unknown-linux-musl --release
Compiling libc v0.2.106
...
error: could not find native static library `c`, perhaps an -L flag is missing?
error: could not compile `libc` due to previous error
warning: build failed, waiting for other jobs to finish...
error: build failed
How do I fix that? I don't want to static link against the system libc, I want it dynamically linked like other binaries on that platform. But not sure how to do that. If I use the standard libstd the binaries are dynamically linked just fine.
Alternatively I could try nostd but my code would need significant modification and I'm not sure that would fix this problem anyway. Alternatively I could just go ahead compile my actual project with libstd and it might fit. However my project is doing data logging, so the binary is competing for space with data I want to store, so I want to minimize space as much as possible.
I've also seen reference to cargo-bloat so I'll probably check that out to find what all the space is being used for in the binary.
I'm open to different strategies to achieve what I want if anyone has ideas?
On my dev system:
$ cat .cargo/config
[target.mips-unknown-linux-musl]
ar = "/home/alex/projects/openwrt-sdk-19.07.7-ath79-generic_gcc-7.5.0_musl.Linux-x86_64/staging_dir/toolchain-mips_24kc_gcc-7.5.0_musl/bin/mips-openwrt-linux-ar"
linker = "/home/alex/projects/openwrt-sdk-19.07.7-ath79-generic_gcc-7.5.0_musl.Linux-x86_64/staging_dir/toolchain-mips_24kc_gcc-7.5.0_musl/bin/mips-openwrt-linux-gcc"
$ cat Cargo.toml
#cargo-features = ["strip"]
[package]
name = "crosshello"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = "3.0.0-beta.5"
[profile.release]
#strip = true
opt-level = "z"
lto = true
codegen-units = 1
panic = "abort"
(The binaries are stripped, currently I'm stripping them manually.)

Rust Cargo build and crosscompile for specific CPU

I want to compile two binaries for different target architectures (eg. Skylake and Sandy Bridge).
These are usually two lengthy cargo commands:
RUSTFLAGS="-C target-cpu=skylake" cargo build --target
x86_64-unknown-linux-gnu --release
How can I set up cargo to build both binaries (with different names) from the same main.rs automatically?
Ideally in either the config.toml or the Cargo.toml so I can add it to a repository.
You can add the following text to your config.toml:
[build]
target = x86_64-unknown-linux-gnu
rustflags = ["-C","target-cpu=skylake"]
[profile.dev] #do not need to add `--release` now
opt-level = 3
debug = false
debug-assertions = false
overflow-checks = false
lto = false
panic = 'unwind'
incremental = false
codegen-units = 16
rpath = false
But it seems like it can't compile for two different target architectures with one config.toml, so you may have to create two config.toml and use cargo --manifest-path PATH/TO/CONFIG to compile two binaries separately.

How can I optionally pass rustc flags depending on a Cargo feature?

The program I'm writing runs much faster when the -C target-cpu=native flag is passed to rustc. I want to give users a simple, platform-independent way to enable this when compiling, so I added a Cargo feature cpu_native = [] in Cargo.toml and created this Cargo config in my project:
[target.'cfg(cpu_native)']
rustflags = ["-C", "target-cpu=native"]
However, this has no effect on my program, and passing --features cpu_native to Cargo does not even trigger a recompile. Changing to the following Cargo config does force re-compilation with faster instructions:
[build]
rustflags = ["-C", "target-cpu=native"]
However, this will compile with target-cpu=native with the default Cargo features, which was not what I wanted. From the Cargo book, what I want seems to be possible, but I don't see what I'm doing wrong.
I don't think this is supported (yet?). I enhanced Cargo to print out what config flags are checked against when resolving:
[
Name("debug_assertions"),
Name("proc_macro"),
KeyPair("target_arch", "x86_64"),
KeyPair("target_endian", "little"),
KeyPair("target_env", ""),
KeyPair("target_family", "unix"),
KeyPair("target_os", "macos"),
KeyPair("target_pointer_width", "64"),
Name("unix"),
]
[target.'cfg(cpu_native)']
This is the incorrect syntax for a Cargo feature; it would normally be cfg(feature = "cpu_native").

Linking to optimised crate from a debug build

I would like to separate some performance intensive code into a .so (I am running Kubuntu Linux) while the main quantity of my code is compiled in debug mode. I want the faster compiles and run time support in my code, but it's unacceptable to run the small amount of intensive code with all the debug checks in it.
Is it possible to do this using Cargo? It seems that Cargo propagates the top level profile to the dependencies, so they are all compiled as release or debug, depending on what is requested of the main crate.
This is possible as of Rust 1.41 via overrides:
[package]
name = "speedy"
version = "0.1.0"
authors = ["An Devloper <an.devloper#example.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
image = "0.21.1"
# All dependencies (but not this crate itself or any workspace member)
# will be compiled with -Copt-level=2 . This includes build dependencies.
[profile.dev.package."*"]
opt-level = 2
The output with some details elided:
$ cargo build --verbose
Compiling image v0.23.0
Running `rustc [...] --crate-name image [...] -C opt-level=2 -C debuginfo=2 -C debug-assertions=on [...]`
Compiling speedy v0.1.0 (/private/tmp/speedy)
Running `rustc [...] --crate-name speedy [...] -C debuginfo=2 [...]`

Resources