Linking to optimised crate from a debug build - rust

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 [...]`

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.)

Could not able to release a file. getting error: could not compile 'libc'

I am very new to this language and coding field. Beginner to coding field as well.
I tried to build and release file but getting an error Compiling libc v0.2.62
error: Could not compile `libc`
pi#raspberrypi:~/Ganesh_Rust/Real_time/led_blink/src $ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.09s
Running `/home/pi/Ganesh_Rust/Real_time/led_blink/target/debug/led_blink`
pi#raspberrypi:~/Ganesh_Rust/Real_time/led_blink/src $ cargo build --release
Compiling libc v0.2.62
error: Could not compile `libc`.
Caused by:
process didn't exit successfully: `rustc --crate-name build_script_build /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.62/build.rs --color always --crate-type bin --emit=dep-info,link -C opt-level=3 --cfg 'feature="default"' --cfg 'feature="std"' -C metadata=b79e3ef31fa8c249 -C extra-filename=-b79e3ef31fa8c249 --out-dir /home/pi/Ganesh_Rust/Real_time/led_blink/target/release/build/libc-b79e3ef31fa8c249 -L dependency=/home/pi/Ganesh_Rust/Real_time/led_blink/target/release/deps --cap-lints allow` (signal: 11, SIGSEGV: invalid memory reference)
code: this program which i wrote in VS code to blink LED on raspberry pi 3
use rust_gpiozero::*;
use std::thread;
use std::time::Duration;
fn main() {
//create a new LEd attached to pin 17 of raspberry pi
let led = LED::new(17);
//blink the led 5 times
for _ in 0.. 5{
led.on();
thread::sleep(Duration::from_secs(10));
led.off();
thread::sleep(Duration::from_secs(10));
}
}
cargo.toml file:
[package]
name = "led_blink"
version = "0.1.0"
authors = ["pi"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rust_gpiozero = "0.2.0"
I am getting output on Raspberry pi but executable file and binary files are large (5MB). So i thought if i do release maybe i can reduce size so tried to release using cargo build --release command but getting this error.
If you're using rustup-provided binaries, then this is a known issue upstream. There is a workaround in that issue, which is to set the following in Cargo.toml:
[profile.release]
codegen-units = 1
As an alternative, you can use the Debian rustc and cargo packages instead of rustup, which should work just fine. You can either download the packages from https://packages.debian.org/rustc and https://packages.debian.org/cargo, or you can add an appropriate APT line into /etc/sources.list (see https://deb.debian.org/ for an example). Note that Debian does not always have the latest version, but they should work.

Why does clap fail to compile when added to Cargo.toml?

Summary
I'm fairly new to Rust and decided to use it to port an existing project into it. I intended to use clap to handle CLI options, but I keep getting errors.
What do I need to do for clap to install correctly so that it's usable in my project as a dependency (e.g. extern crate clap; [...] use clap::App; [...]?
I haven't had problems with other crates (so far), so I'm not sure what's so different here or if there's a problem with the crate itself.
I've already seen a few questions (e.g. this one), which simply suggests that the dependency be added into the .toml file or don't seem to provide a solution to what I'm seeing.
I'm in Ubuntu Linux, if that makes a difference.
What I Tried
Adding clap = "2.33.0" to my Cargo.toml file (see https://crates.io/crates/clap) causes VSCode (through RLS) to log the following:
{
"resource": "[...]/Projects/takeout/Cargo.toml",
"owner": "rust",
"severity": 8,
"message": "Could not compile `clap`.\nprocess didn't exit successfully: `[...]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rls --crate-name clap [...]/.cargo/registry/src/github.com-1ecc6299db9ec823/clap-2.33.0/src/lib.rs --color never --crate-type lib --emit=dep-info,metadata -C debuginfo=2 --cfg 'feature=\"ansi_term\"' --cfg 'feature=\"atty\"' --cfg 'feature=\"color\"' --cfg 'feature=\"default\"' --cfg 'feature=\"strsim\"' --cfg 'feature=\"suggestions\"' --cfg 'feature=\"vec_map\"' -C metadata=630980a214d5fd10 -C extra-filename=-630980a214d5fd10 --out-dir [...]/Projects/takeout/target/rls/debug/deps -L dependency=[...]/Projects/takeout/target/rls/debug/deps --extern ansi_term=[...]/Projects/takeout/target/rls/debug/deps/libansi_term-1510a9addefc0253.rmeta --extern atty=[...]/Projects/takeout/target/rls/debug/deps/libatty-7c4847fd9fc1e3d9.rmeta --extern bitflags=[...]/Projects/takeout/target/rls/debug/deps/libbitflags-8369a9aec15a5abb.rmeta --extern strsim=[...]/Projects/takeout/target/rls/debug/deps/libstrsim-301d1cf239e9cd24.rmeta --extern textwrap=[...]/Projects/takeout/target/rls/debug/deps/libtextwrap-a799d71e2d028df4.rmeta --extern unicode_width=[...]/Projects/takeout/target/rls/debug/deps/libunicode_width-58e38dd9d658dcfb.rmeta --extern vec_map=[...]/Projects/takeout/target/rls/debug/deps/libvec_map-4f8e59c92e9953d8.rmeta --cap-lints allow --error-format=json --sysroot [...]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu` (exit code: 101)",
"startLineNumber": 1,
"startColumn": 1,
"endLineNumber": 10000,
"endColumn": 1
}
According to the README in the clap repo itself, just adding it should work:
For full usage, add clap as a dependency in your Cargo.toml to use from crates.io:
[dependencies]
clap = "~2.33"
But it doesn't.
I've tried it with and without the ~ prefix as well as clap = {version = "2.33", features = ["yaml"]}, which is also shown in the repo, but no luck. (Yes, I'm trying to load the CLI options from a .yaml file.)
Trying cargo install clap --version 2.33.0 from the shell simply returns an error message saying: error: specified package has no binaries.
Aiming directly at the Git repo also produces the same error message:
cargo install --git https://github.com/clap-rs/clap.git --tag v2.31.2 --features yaml 101 ↵
Updating git repository `https://github.com/clap-rs/clap.git`
Installing clap v2.31.2 (https://github.com/clap-rs/clap.git?tag=v2.31.2#07c15d28)
error: specified package has no binaries
Note that there's no v2.33.0 tag in the Git repo (at the time of this writing).
Bonus if you know how to get VSCode to stop marking everything as an error:
cargo install
There's misunderstanding about the cargo install command. You can learn more about it here.
This command manages Cargo’s local set of installed binary crates. Only packages which have executable [[bin]] or [[example]] targets can be installed, and all executables are installed into the installation root’s bin folder.
It's not your case. The only thing you have to do is to list clap in the dependencies section (Cargo.toml). That's all. No need to use cargo install at all. cargo build, cargo run, ... commands will download & compile & statically link all dependencies.
An example
Folder structure:
.
├── Cargo.toml
└── src
   ├── cli.yaml
   └── main.rs
Current directory:
$ pwd
/Users/robertvojta/Projects/stackoverflow/clap-yaml
Cargo.toml content:
[package]
name = "clap-yaml"
version = "0.1.0"
authors = ["Zrzka"]
edition = "2018"
[dependencies]
clap = { version = "2.33.0", features = ["yaml"] }
src/cli.yaml content:
name: clap-yaml
version: "1.0"
author: Zrzka
about: Stackoverflow sample
args:
- lang:
short: l
long: lang
default_value: cz
takes_value: true
possible_values:
- cz
- en
src/main.rs content:
use clap::{App, load_yaml};
fn main() {
let yaml = load_yaml!("cli.yaml");
let matches = App::from_yaml(yaml).get_matches();
match matches.value_of("lang").unwrap() {
"cz" => println!("Ahoj"),
"en" => println!("Hello"),
_ => unreachable!("see possible_values in yaml, handled by clap"),
};
}
Run it with cargo:
$ cargo -q run -- --lang en
Hello
Run it directly:
$ cargo build
...
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
$ target/debug/clap-yaml --lang cz
Ahoj
Visual Studio Code
I still have vscode complaining and underlining everything in red in the Cargo.toml file. Any suggestions to fix this completely? It seems close to a full resolution.
I can confirm that this problem do exist in Rust 1.34.0. I did install this version and I've got same symptoms:
could not compile clap
the whole Cargo.toml is underlined (error)
There're two ways how to fix this.
Update your Cargo.toml file dependencies section manually if you'd like to stick with Rust 1.34.0:
[dependencies]
bitflags = "=1.0.4"
clap = { version = "2.33.0", features = ["yaml"] }
Or update your Rust toolchain to >= 1.35.0.
I just tested both ways and it works.
Related issues:
Could not compile clap. process didn't exit successfully
Compiler panics on latest RLS when compiling crates that depend on bitflags 1.0.5

How to troubleshoot why cargo/rustc links in rust standard library symbols even when no_std is used?

I am trying to create an embed-friendly executable (small footprint and without dependency on the Rust standard library) that uses a library (wasmi) that already has support for a no_std build. New to Rust, I am simply piecing together instructions, but the gist of it appears to be follow the steps.
For the executable:
#![no_std]
#![no_main]
use core::panic::PanicInfo;
/// This function is called on panic.
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
#[no_mangle]
pub extern "C" fn _start(_argc: isize, _argv: *const *const u8) -> ! {
interpret(_argc, _argv);
loop {}
}
That is to:
include #![no_std]
define our entry (not main since we don't have a runtime that will call it)
and define a panic handler since the Rust std lib is not included to define it for us.
My Cargo file to compile this looks like this:
[package]
name = "driver"
version = "0.1.0"
edition = "2018"
[dependencies.wasmi]
path = "../../github_dev/wasmi"
features = ["core"]
default-features = false
test=false
bench=false
[profile.release]
panic = "abort"
lto = true
incremental=false
debug=true
opt-level = "z"
test=false
bench=false
and produces a very small binary that excludes any standard library symbols (using nm to check) and runs as expected.
The problem occurs when I actually try to call a function from the wasmi library. It is built with no_std via the features=core line. Doing an nm on the files in release/deps/libwasmi-*.rlib shows no standard library symbols. However when linking occurs with this command:
rustc --release --verbose -- -C link-arg=-nostartfiles
it leads to:
Compiling driver v0.1.0 (/home/my_home/wasmi_embed/driver)
Running rustc --edition=2018 --crate-name driver src/main.rs --color always --crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort -C lto -C link-arg=-nostartfiles -C metadata=957eda2e590447ba -C extra-filename=-957eda2e590447ba --out-dir /home/my_home/wasmi_embed/driver/target/release/deps -L dependency=/home/my_home/wasmi_embed/driver/target/release/deps --extern libc=/home/my_home/wasmi_embed/driver/target/release/deps/liblibc-f7fb773c7b059a14.rlib --extern wasmi=/home/my_home/wasmi_embed/driver/target/release/deps/libwasmi-534aef1926b4eb6c.rlib
and an error occurs:
error[E0152]: duplicate lang item found: panic_impl.
--> src/main.rs:31:1
|
31 | / pub extern fn panic(_info: &PanicInfo) -> ! {
32 | | loop {}
33 | | }
| |_^
|
= note: first defined in crate `std`.
It seems Rust is trying to link in standard library support for at least panic handling, but I don't know why.
I would like help to understand why and to understand how to prevent it.
If I remove the panic_impl attribute then my executable compiles, but it includes a lot of standard library symbols that I am trying to prevent.
The example symbols I see are:
my_home#my_puter:~/wasmi_embed/driver/target/release$ nm --demangle -A -a -B -s --line-number test_2018 2>/dev/null | grep std
driver:00000000000264c0 t rust_begin_unwind /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:311
driver:00000000000264a0 t rust_oom /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/alloc.rs:203
driver:000000000001f490 t rust_panic /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:524
driver:0000000000025aa0 t _$LT$std..panicking..continue_panic_fmt..PanicPayload$LT$$u27$a$GT$$u20$as$u20$core..panic..BoxMeUp$GT$::get::he4f810e299a2e0b4 /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:372
driver:00000000000259a0 t _$LT$std..panicking..continue_panic_fmt..PanicPayload$LT$$u27$a$GT$$u20$as$u20$core..panic..BoxMeUp$GT$::box_me_up::hd8430725259668a8 /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:367
driver:0000000000021520 t _$LT$std..sys_common..process..DefaultEnvKey$u20$as$u20$core..borrow..Borrow$LT$std..ffi..os_str..OsStr$GT$$GT$::borrow::hbacd0cd7d7fbf1c1/rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/sys_common/process.rs:27
driver:0000000000021570 t _$LT$std..error..$LT$impl$u20$core..convert..From$LT$alloc..string..String$GT$$u20$for$u20$alloc..boxed..Box$LT$$LP$dyn$u20$std..error..Err
... plus more
The above symbols are not found in any of the rlib files under the dep directory including libwasmi, nor are they found in the driver executable when not calling libwasmi code.
I've read a similar issue (hence my test=false and bench=false in the Cargo.toml) but that did not help. I've tried to build with just rustc with varying commands (excluding Cargo) but the error is the same. I've tried to compile wasmi as a static library (ar) and link it in, but being new to Rust I was spending a lot of time trying to link it in and it just wasn't happening.
I resolved this after seeking some help in the rust forums. enter link description here. Specifically, was not able to determine what was responsible for rust std lib being linked into my executable ... was it an issue with a crate or an issue with cargo or an issue with rustc or an issue with the linker. I did not know where the problem was born, but based on similar bugs filed I figured that somehow a crate was being compiled to bring in std lib unexpected. Turns out bug enter link description here was not related even though the error message was the same. I did not have an issue with unexpected propagations form different type of dependencies (dev-dependencies and build-dependencies). I tried all these techniques to pinpoint what was bringing in std lib:
I tried using cargo tree to list dependencies to list all the crate
dependencies:
wasmi v0.4.3 (/home/jlb6740/github_dev/wasmi)
├── byteorder v1.3.1 (/home/jlb6740/github_dev/byteorder)
├── hashbrown v0.1.8 (/home/jlb6740/github_dev/hashbrown)
│ ├── byteorder v1.3.1 (/home/jlb6740/github_dev/byteorder) ()
│ └── scopeguard v0.3.3 (/home/jlb6740/github_dev/scopeguard)
├── libm v0.1.2
├── memory_units v0.3.0
└── parity-wasm v0.31.0 (/home/jlb6740/github_dev/parity-wasm)
└── byteorder v1.3.1 (/home/jlb6740/github_dev/byteorder) ()
I tried using cargo rustc --verbose … but at this time verbose does
not indicate anything was using default features which may include
using std
I tried using cargo metadata … this generated a long list of
dependencies that was hard to parse, but I did see some instances
where scopeguard and byteorder had default features requiring std
support. I downloaded all of these crates and just hardcoded
attributes so that the crates would only build with no_std support.
I tried looking at the deps/ output and did an nm on all of the
rlibs to see if any of the libraries used symbols found in std. I
could not find that that was the case. I thought rlibs were like
static libraries and that anything they used would be included in
the rlib but apparently not.
I looked at cargo rustc -- -C --print-link-args to check out linker
flags but I could not find anything obvious telling me it was
bringing in std lib.
None of these things helped me to pinpoint what was introducing std lib. Ultimately the suggestion at the rust forums was to use cargo check for a target that does not allow std lib at all. Those with a * listed here: enter link description here have only core support. I tried that, running with --target=thumbv7m-none-eabi and saw:
error[E0463]: can’t find crate for alloc
–> /home/jlb6740/github_dev/hashbrown/src/lib.rs:44:1
|
44 | extern crate std as alloc;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ can’t find crate
Turns out it was hashbrown which was a dependency of a dependency of my executable. It built no_std by default but had an extern std linked under a different name and which was guarded by a feature called “nightly”. The guard was disabled in my efforts to not build anything but no_std. Nothing I’d tried alerted me to the crate which was responsible until this. Seems there should be a better way to get a more comprehensive list of crate dependencies than what cargo tree provided, but changing the wasmi cargo to make sure the nightly feature was set solved my issue.

Resources