capnpc::compile not writing files - rust

I'm having difficulty working with the capnpc crate. I'm running Arch Linux and have installed capnp from the AUR and compiled capnpc-rust from the github project and put it in /usr/local/bin. I can manually compile the .capnp file easily with the command
capnp compile -orust --src-prefix=capnp capnp/message.capnp
I tried cloning the capnpc project and compiling the .capnp test file in the test directory and that didn't work either. I'm not getting any errors (whereas earlier I was getting "File not found") so it seems like capnpc is working, but I can't find files anywhere.
build.rs
extern crate capnpc;
fn main() {
::capnpc::compile("capnp", &["capnp/message.capnp"]).unwrap();
}
Cargo.toml
...
build = "build.rs"
[lib]
name = "rustp2p"
path = "src/lib.rs"
[build-dependencies]
capnpc = "*"
[dependencies]
capnp = "0.5.0"
Edit: .rs file builds out into /target/debug/build/.../out.

When you invoke capnpc::compile from a Cargo build script, the generated code goes in a subdirectory of target/ that can be found at main compile time through the OUT_DIR environment variable. This strategy is described in the Cargo documentation.
You shouldn't need to install the capnpc-rust binary in /usr/local/bin or anywhere else for this to work.
Your build.rs and Cargo.toml files look fine to me.
You might find it helpful to consult the addressbook example.

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.

Why Rust build.rs is unable to find C headers?

Basically I am trying to cargo build a crate which has a build.rs file.
This crate is located inside a bigger project and it's supposed to be a lib crate.
And inside this build.rs file, I am trying to compile a .C file which includes a couple of headers.
Fun fact: I got this build.rs file and crate structure from another little demo crate, and in that demo crate I had no problem to compile this exact C file with these headers.
FULL ERROR HERE:
Here is a link to github: https://github.com/mihaidogaru2537/FirecrackerPlayground/tree/dpdk_component/firecracker/src/dpdk_component
There is the crate I am talking about and you can also see the bigger project in which it resides. In the README file you can see the full error.
Either I do cargo build from the root of the big project or from the root of this problematic crate, the error is the same.
"cargo:warning=/usr/include/asm-generic/errno.h:5:10: fatal error: asm-generic/errno-base.h: No such file or directory
cargo:warning= 5 | #include <asm-generic/errno-base.h>"
The missing file might change depending on the .flag("-I/path/..") calls I am doing inside the build.rs
As you can see, right now it's unable to find errno-base.h, but I am including the path to asm-generic.
Here is the code of the build.rs file from the crate where the compilation of this C file works, as you can see, I did not have to add any include flags before calling compile.
fn main() {
// Tell cargo to tell rustc to link the system bzip2
// shared library.
// println!("cargo:rustc-link-lib=rte_ring");
// println!("cargo:rustc-link-lib=rte_mempool");
// Tell cargo to invalidate the built crate whenever the wrapper changes
// println!("cargo:rerun-if-changed=wrapper.h");
let _src = ["src/static-functions.c"];
println!("cargo:rerun-if-changed=build.rs");
let mut builder = cc::Build::new();
let build = builder
.file("src/static-functions.c")
.flag("-Wno-unused-parameter");
build.compile("foo");
}
Additional info:
The problematic crate is pretty small, see the link above. There is the build.rs file, C file and header file is inside the include directory.
One thing that I suspect, is that the target of the bigger project:
TARGET = Some("x86_64-unknown-linux-musl")
might affect the way the C file is compiled.
In the project where the compilation is working, I am not using that linux-musl stuff.
I am a total noob when it comes to Rust, but I do have a decent understanding of how C/C++ works.
I am running the project on Ubuntu 20.04
Those missing headers are a result of importing DPDK headers, I have DPDK libraries installed on the machine in question.
Let me know if you have any questions, sorry for the long read and thank you.
I somehow managed to fix it by adjusting the cargo build command to use x86_64-unknown-linux-gnu as target instead of x86_64-unknown-linux-musl (By default cargo build was doing the musl target somehow)
So if you are trying to build a rust app which is using DPDK libraries and you are getting missing headers, make sure to try the following:
cargo build --target=x86_64-unknown-linux-gnu
Well if you have to use musl and there is no alternative, I don't have an answer. But to me this was enough.
If someone has an explanation why musl is not working in this scenario, please let us know.
Reddit Rust community helped me as well, check this link out if you are interested:
https://www.reddit.com/r/rust/comments/mo3i08/unable_to_compile_c_file_inside_buildrs_headers/
So Why build.rs was unable to find .C headers?
ANSWER
Because I was using x86_64-unknown-linux-musl as target.

How to list a project's source files using the cargo crate?

I'm trying to list the source files of a Rust project using the cargo crate. I can not just simply list all the .rs files present in a directory as I want to retrieve exactly the files that the compiler sees during the compilation, which may not be all the .rs files.
I'm conducting my experiments on the the Alacritty repository, which has a cargo workspace of 3 projects. Here is my code so far:
extern crate cargo;
use std::path::Path;
use cargo::core::Source;
fn main() {
let path = Path::new("/tmp/alacritty/Cargo.toml");
let config = cargo::util::config::Config::default().unwrap();
let ws = cargo::core::Workspace::new(&path, &config).unwrap();
for pkg in ws.members() {
println!("found package {}", pkg);
let config = ws.config();
let mut src = cargo::sources::PathSource::new(pkg.root(), pkg.package_id().source_id(), config);
src.update().unwrap();
let src_files = src.list_files(pkg).unwrap();
println!("found {} source files", src_files.len());
}
}
Here is the output:
found package alacritty v0.5.0-dev (/tmp/alacritty/alacritty)
found 0 source files
found package alacritty_terminal v0.5.0-dev (/tmp/alacritty/alacritty_terminal)
found 0 source files
found package font v0.1.0 (/tmp/alacritty/font)
found 0 source files
The members of the workspace are correctly found but I fail to retrieve the source files for each of these members. What am I missing?
Your code works!
If you run 'cargo vendor' in the alacritty tree, this should solve your issue. Study the 'cargo vendor' command Also, study the --offline switch for the cargo build command. I did not need to use this, but it is very helpful reading.
Basically, cargo vendor pulls in all the source.
I am not sure exactly why your code is not working. I had difficulty recreating this using the /tmp directory. I then used a normal directory combined with a call to 'cargo vendor', and it worked. Before cutting and pasting my code below, be sure to change '/Users/[username]' with your own path to your home directory.
Here is my procedure:
cd ~
git clone https://github.com/jwilm/alacritty
cargo vendor
This next part is probably not necessary:
mkdir /Users/[username]/alacritty/.cargo
Create a file at /Users/[username]/alacritty/.cargo/config
and, insert the following:
[source.crates-io]
replace-with = "vendored-sources"
[source.vendored-sources]
directory = "vendor"
Continuation of necessary part:
Modify the path statement to point to the newly created alacritty path:
let path = Path::new("/Users/[username]/alacritty/Cargo.toml");
Now, run your code
cargo run
Here is my output:
cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.27s
Running `target/debug/test3`
found package alacritty v0.5.0-dev (/Users/jmurray/alacritty/alacritty)
found 18 source files
found package alacritty_terminal v0.5.0-dev
(/Users/[username]/alacritty/alacritty_terminal)
found 172 source files
found package font v0.1.0 (/Users/jmurray/alacritty/font)
found 12 source files
Search for each element of the needle in the haystack in order. Each time you find a matching element, only continue the search in the remaining portion of the haystack. You can express this nicely by taking a new subslice of of the haystack each time you match an element.

Build only `lib` target

I want to build a dynamic link library (dll).
My Cargo.toml currently looks like this:
[package]
name = "sample"
version = "0.1.0"
authors = ["author"]
[lib]
name = "main"
crate-type = ["dylib"]
[dependencies]
I use VS Code with the RustyCode plugin as my IDE on windows.
When I run the build command this builds into a sample.exe and main.dll.
I know I can run cargo build --lib to only build my lib target but I dont have access to this command inside VS Code (afaik).
Is there anyway to specify that I only want to build the lib target in my Cargo.toml file so I can use the VS Code build command which runs cargo build/cargo run?
Cargo builds files using convention over configuration approach. When it finds a main.rs it builds an executable, and when it encounters lib.rs it expects to build a library.
Calling your lib main managed to confuse Cargo. The only solution I managed to find is to either change name of your crate from name = "main" to name = "foo" (and then rename your main.rs into foo.rs) or to change its name to lib.rs, as you did.
Just figured it: Rename the src/main.rs to src/lib.rs and it only builds the lib target!

failed to parse manifest - no targets specified

I am new to Rust and attempting to build a test project with Cargo. My Cargo.toml looks like:
[package]
name = "rust-play"
version = "0.0.1"
authors = [ "Bradley Wogsland <omitted>" ]
(but the actual TOML file doesn't omit my email). When I cargo build I am getting the following error:
error: failed to parse manifest at /Users/wogsland/Projects/rust-play/Cargo.toml
Caused by:
no targets specified in the manifest
either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present
My main function is in a src/test.rs file. Do I need to specify that in the TOML file? If so, how? I tried adding
target = "src/test.rs"
to no avail.
As the error says:
either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present
So the direct answer is to add a [[bin]] section:
[[bin]]
name = "test"
path = "src/test.rs"
However, it's far more usual to just place the file in the expected location: src/main.rs. You could also place it in src/bin/test.rs if you plan on having multiple binaries.
If it's actually for testing your code, then unit tests go in the same file as the code they are testing and integration tests go in tests/foo.rs.
Alternative issue and solution: You can also be faced with this error if you have copied Cargo.toml file to a parent folder of the crate.
I ran into this issue on Ubuntu 20.04 after having inadvertently copied Cargo.toml to my home folder. Even though my working directory had a properly defined Cargo.toml, the copy in $HOME was taking precedence and causing builds to fail.
In my case and probably in your case as well, the rs file was not named main.rs while Cargo assumes that src/main.rs is the crate root of a binary crate. So, the rule is that If project is an executable, name the main source file src/main.rs. If it is a library, name the main source file src/lib.rs.
Additionally, Cargo will also treat any files located in src/bin/*.rs as executables like mentioned in the previous answer.
As a summary:
If you use cargo new xxx --bin, you will find the file in the src directory is named main.rs. And when you check the file Cargo.toml. It is the same as you written. So the first way is to change the file in src to main.rs
As the cargo report, we can use the [[bin]] to set the file. #Shepmaster has solved it.
Both two ways can work.
I also had this issue and it was because the parent directory also contained a Cargo.toml file and it was prioritising that over the one in the current directory

Resources