Empty rust file creates massive WASM build - rust

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.

Related

Unable to use rust crates

I'm new to rust. I'm following a getting started tutorial that imports the crate random-number but when running the code I'm getting the error can't find crate for 'random_number'. What am I doing wrong?
~/Cargo.toml:
[package]
name = "test"
version = "0.0.1"
edition = "2021"
[dependencies]
random-number = "0.1.8"
~/src/main.rs:
extern crate random_number;
use random_number::random;
fn main() {
let num: i8 = random!(..);
println!("{}", num);
}
rustc is not meant to be used directly. It is the compiler that can compile a .rs file, but it doesn't have any dependency manager attached to it. So if you decide to use rustc directly, you need to manage your dependencies manually.
cargo is the official tool to compile Rust projects. It internally uses rustc, but additionally manages the project's dependencies that are specified in Cargo.toml.
cargo build --release && ./target/release/<project_name>
or the short form:
cargo run --release

Missing crate when using rustc but not using cargo

I'm using the epub crate on version 1.2.3 and my Cargo.toml is formatted as such
[package]
name = "cl-epub-reader"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
epub = "1.2.22"
and my main.rs is
use epub::doc::EpubDoc;
use epub::doc::NavPoint;
use std::env::args;
fn main() {
let args: Vec<String> = args().collect();
let doc = EpubDoc::new(&args[1]).unwrap();
// assert!(doc.is_ok());
println!("{:?}", doc.mdata("title"));
}
All it does is get the uses the path from the a user input then it gets the title metadata and printing it.
When I run cargo run it outputs an error about an error about going out of range, which is expected however when I run rustc src/main.rs the error is error[E0433]: failed to resolve: maybe a missing crate `epub`?
Does anyone know the cause of this and how to solve this issue?
When you call rustc directly, you need to pass the appropriate options to tell the compiler where the crates are installed on your computer. cargo handles that automatically for you (you can use the -v option to cargo build to see the actual rustc command lines it uses).

Refactoring to workspace structure causes extern crate imports to not work

I need different parts of my project to use different versions of the same extern crate so I'm refactoring my Rust project to be divided into multiple packages via the workspaces system using this as a guide. Doing so is causing all my pub extern crate imports to not work.
This post is very similar to one I created very recently and then deleted - this version contains a minimal, complete, and verifiable example.
Here's my project structure
workspace_test/
root/
src/
main.rs
Cargo.toml
Cargo.toml
workspace_test/Cargo.toml:
[package]
name = "workspace_test"
version = "0.1.0"
authors = ["Phoenix <kahlo.phoenix#gmail.com>"]
[workspace]
members = [
"root"
]
[[bin]]
name = "root"
path = "root/src/main.rs"
workspace_test/root/Cargo.toml:
[package]
name = "root"
version = "0.1.0"
authors = ["Phoenix <kahlo.phoenix#gmail.com>"]
[dependencies]
time = "0.1"
workspace_test/root/src/main.rs:
pub extern crate time;
fn main() {
println!("Hello, world!");
}
This is also on github, so it can easily be cloned and cargo run'd.
This is the error:
error[E0463]: can't find crate for `time`
--> root/src/main.rs:1:1
|
1 | pub extern crate time;
| ^^^^^^^^^^^^^^^^^^^^^^ can't find crate
error: aborting due to previous error
error: Could not compile `workspace_test`.
In workspace_test/Cargo.toml you create a package with the binary root. If you execute cargo run, it runs the main.rs, but since you didn't state the dependencies in this manifest file, the error occurs. The dependency is only specified in workspace_test/root/Cargo.toml, which is not used at this point.
I assume you want to use the workspaces proposed by the RFC. You can create a workspace with virtual manifests, which must neither specify a [package] nor [[bin]], so just remove them. workspace_test/Cargo.toml now looks like this:
[workspace]
members = [
"root"
]
If you only have one executable, you can now pass the package: -p/--package
cargo run -p root
or specify the manifest path manually:
cargo run --manifest-path root/Cargo.toml
If root/Cargo.toml contains multiple targets, you can just append the --lib or --bin flags as usual. E.g. this would execute the abc-binary specified in workspace_test/root/Cargo.toml:
cargo run -p root --bin abc

How to import a crate dependency when the library name is different from the package name?

I have a crate that is imported straight off of GitHub, as per Cargo's documentation:
[dependencies]
libfoo = { git = "ssh://git#github.com/me/libfoo", branch = "dev" }
[lib]
path = "src/rust/lib.rs"
name = "myprj"
crate-type = ["cdylib"]
Running cargo build works fine here, Cargo fetches libfoo and builds it in the ~/.cargo directory. When I try to use (import) it in lib.rs:
extern crate libfoo; //also tried foo
Cargo chokes:
error[E0463]: can't find crate for `libfoo`
--> src/rust/lib.rs:1:1
|
1 | extern crate libfoo;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate
Interestingly, IntelliJ's Rust plugin does find the crate when I click on it in lib.rs – it navigates to the downloaded source in ~/.cargo...
In the dependency libfoo, the lib section of the Cargo.toml file is specified as:
[package]
name = "libfoo"
[lib]
name = "foo"
crate-type = ["cdylib"]
I have tried all permutations of libfoo and foo to see if Cargo is getting confused between the lib name and the package/directory name.
It also fails if I specify a local path to the dependency. (Cargo compiles the dependency but then claims not to find it when it is declared/imported in lib.rs.)
[dependencies]
libfoo = { path = "/Users/me/dev/libfoo" }
If I include a crate from git or the file system that has the same [lib] name as the [package] name, it works fine. So it appears the problem is with crates that have a have a library ([lib]) name that is different from the package ([package]) name.
If I remove the [lib] section from the dependency's Cargo.toml file, it works.
Update: if crate-type = ["cdylib"] is removed from libfoo, this works with foo imported. If that is there, I get the same error with extern crate foo;.
Cargo is interested in package names when it comes to dependencies, while the compiler (rustc) is interested in library names when it comes to loading their metadata and linking with them.
Let's take a look again at this Cargo.toml excerpt:
[package]
name = "libfoo"
[lib]
name = "foo"
Here, the package name is libfoo and the library name is foo.
When you want to declare a dependency on libfoo in your project, you need to write the package name (libfoo) in the [dependencies] table. For example:
[dependencies]
libfoo = { git = "ssh://git#github.com/me/libfoo", branch = "dev" }
This is what you already have, and it's correct.
However, when you want to import the library in your crate, you need to write the library name in the extern crate item, i.e.
extern crate foo;
How did I figure this out? First, I wrote libfoo in both Cargo.toml and the extern crate item, as you described. When I ran cargo build, I noticed that libfoo was built successfully, indicating that Cargo correctly resolved the dependency. But I also noticed that the compiler couldn't find libfoo, as you experienced.
I then inspected the command line passed to rustc by running cargo build --verbose. This is what I saw (irrelevant parts omitted):
Running `rustc [...] --extern foo=/[path]/target/debug/deps/libfoo-5cf876c5c8ac1bfb.rlib`
The --extern name=path argument tells rustc that the crate named name is located in path. The name here is foo, so we must write extern crate foo; in the code to reference it.

Unable to find crate that is listed in [build-dependencies] section

I try to compile my project with the command cargo build.
build.rs
extern crate csv;
use std::path::Path;
use std::fs::OpenOptions;
use std::io::BufWriter;
use std::io::Write;
#[allow(non_snake_case)]
fn processCSV(filename: &str, sourcePath: &str, enumName: &str) {
println!("Generate rust source code from schema {}",filename);
let mut ret: Vec<String> = Vec::new();
let mut rdr = csv::Reader::from_file(filename).unwrap().flexible(true);
for record in rdr.records().map(|r| r.unwrap()) {
}
let path = Path::new(sourcePath);
let file = match OpenOptions::new().write(true).create(true).open(&path) {
Ok(file) => file,
Err(..) => panic!("Cannot create file {}",path.display()),
};
let mut writer = BufWriter::new(file);
writer.write_all(b"test\n");
}
fn main() {
processCSV("../schemas/Test.csv", "./src/mod/common/StatusCode.rs", "StatusCode");
}
and Cargo.toml
[package]
name = "rust-test"
version = "0.0.1"
build = "build.rs"
[lib]
path = "src/lib.rs"
[dependencies]
[build-dependencies]
csv = "*"
I can see this error :
src/lib.rs:1:1: 1:18 error: can't find crate for csv
src/lib.rs:1 extern crate csv;
but when I change flexible(true) to flexible(false) it compiles just fine without any errors. What do I need to do to fix this?
I am using Rust 1.2.0 on Windows 7 64-bit.
Changing flexible(false) for flexible(true) makes no difference for me; both fail. The problem is that you've chosen build-dependencies for some reason, instead of just dependencies.
Using the src/lib.rs file that you provided in your answer, and this Cargo.toml file:
[package]
name = "stack-overflow"
version = "0.1.0"
authors = ["A. Developer <a.developer#example.com>"]
[dependencies]
csv = "*"
It compiles fine.
If you need to access a dependency both in your build.rs and in your project, you need to include the dependency in both sections.
A build dependency is a dependency for a build script, which is a helper binary compiled and run before your main crate is built (designed to be used for code-generation, and building/finding native C libraries, etc.).
Normal dependencies used by the main code should just fall into the "dependencies" section, e.g.
[dependencies]
csv = "0.14"
There's also a "dev-dependencies" section, which are dependencies that are only needed for testing, i.e. they are compiled and used only for cargo test. This allows crates to depend on, for example, quickcheck for running tests without contaminating the main artifact.
In summary, running cargo build will do something like:
build any build-dependencies
build the build script (pointing the compiler to the built build-dependencies), and run it
build any dependencies
build the main crate (pointing the compiler to the built dependencies)
Running cargo test adds:
build any dev-dependencies
build the main crate with --test to create a test runner for any in-source #[test]s (pointing the compiler to both the dependencies and dev-dependencies)
build any external examples or tests, also pointing to both the dependencies and dev-dependencies

Resources