I want to use SBE codecs in Rust. I have a polyglot project which uses java and rust. Java is built by gradle, rust is built by cargo. I have a gradle task generateMessagesRust which generates a directory with src/lib.rs and the codec files. Generated crate is imported in Cargo.toml like this.
[dependencies]
ipc_connectivity = { path = "aeron-connectivity/build/generator/ipc_connectivity" }
Import works just fine if I manually call generateMessagesRust. But I want to automate it, and force Cargo call ./gradlew generateMessagesRust before it builds a project. In order to do this I created the following build.rs file:
use std::process::Command;
fn main() {
let command = Command::new("./gradlew")
.arg("generateMessagesRust")
.spawn()
.expect("Failed to run command");
let output = command.wait_with_output().unwrap();
println!("{}", output.status);
println!("{}", String::from_utf8(output.stdout).unwrap());
}
However, it doesn't work.
Execution failed (exit code 101).
/home/vadim/.cargo/bin/cargo metadata --verbose --format-version 1 --all-features
stdout : error: failed to get `ipc_connectivity` as a dependency of package `dijkstra v0.1.0 (/home/vadim/IdeaProjects/myproj)`
Caused by:
failed to load source for dependency `ipc_connectivity`
Caused by:
Unable to update /home/vadim/IdeaProjects/myproj/aeron-connectivity/build/generator/ipc_connectivity
Caused by:
failed to read `/home/vadim/IdeaProjects/myproj/aeron-connectivity/build/generator/ipc_connectivity/Cargo.toml`
Caused by:
No such file or directory (os error 2)
stderr :
I assume that Cargo tries to process Cargo.toml and only then evaluates build.rs. So it fails before generating the codecs.
My question is: how to generate codecs automatically before Cargo build?
Related
When we compile a c file using gcc test.c -o test.
We can get the binary file as test.
But while running a file using cargo run test.rs in rust.
can we get the binary like we got in the C program?
The original hello.c file:
void main() {
// printf() displays the string inside quotation
printf("Hello, World!");
}
The rust program:
extern "C" {
fn printf(_: *const libc::c_char, _: ...) -> libc::c_int;
}
unsafe fn main_0() {
// printf() displays the string inside quotation
printf(b"Hello, World!\x00" as *const u8 as *const libc::c_char);
}
pub fn main() { unsafe { main_0() } ::std::process::exit(0i32); }
When using cargo it compiles and runs perfectly.
└─$ cargo run hello.rs
Compiling Rust_testing v0.1.0 (/home/pegasus/Documents/Rust_testing)
warning: crate `Rust_testing` should have a snake case name
|
= note: `#[warn(non_snake_case)]` on by default
= help: convert the identifier to snake case: `rust_testing`
warning: `Rust_testing` (bin "Rust_testing") generated 1 warning
Finished dev [unoptimized + debuginfo] target(s) in 0.17s
Running `target/debug/Rust_testing hello.rs`
Hello, world!
Here's my Cargo.toml file:
[package]
name = "Rust_testing"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
libc = "0.2"
I have a rust program named hello.rs.
The program is I'm unable to compile it using rustc. I generated the hello.rs using c2rust online transpiler. But if I use cargo run hello.rs the program runs smoothly.
while using rustc new.rs -o test,
I can get the x86 test binary.
How to get similar kind of file while using the cargo run new.rs?
I looked into the target/debug directory.
But there are so many directories and so many files there. How to know which on is created for which .rs file?
┌──(pegasus㉿pegasus)-[~/Documents/Rust_testing/target/debug]
└─$ ls
build deps examples incremental Rust_testing Rust_testing.d
If you do cargo build, you will find the binary in target/debug/. If you build in release via cargo build --release, you will find it in target/release/.
Be aware that cargo run hello.rs does not compile hello.rs. It will always compile src/main.rs. hello.rs will be passed to the compiled program as a command line argument.
How to know which on is created for which .rs file?
There isn't one file for one .rs file. If your crate is a binary crate, then there will be exactly one executable with the name of your crate. In your case it's Rust_testing. You can run it with ./target/debug/Rust_testing, or copy it somewhere else and execute it directly.
You can add multiple binaries per crate by putting them in the src/bin folder. For example, if you put your hello.rs file in src/bin and then execute cargo build --all, it will create a target/debug/hello executable that you can run.
For more information about cargo's folder layout, read the cargo documentation.
If you are new to Rust, I highly recommend reading the Rust book. It will guide you through how to use rustup, rustc and cargo step by step.
I have a project where a dependency requires libclang on the system to build, I want to avoid needing to manually install this on the system and instead use build.rs to automatically download this. Is there a way to run build.rs before dependencies to effectively setup the required environment?
My attempt project:
Cargo.toml:
[package]
name = "testing-lib"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
userfaultfd-sys = "0.4.1"
lib.rs:
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!(result, 4);
}
}
build.rs
fn main() {
std::process::Command::new("sudo").args(["apt","install","clang"]).output().unwrap();
}
cargo build leads to:
error: failed to run custom build command for `userfaultfd-sys v0.4.1`
Caused by:
process didn't exit successfully: `/home/admin/testing-lib/target/debug/build/userfaultfd-sys-dd02a368283723d2/build-script-build` (exit status: 101)
--- stderr
thread 'main' panicked at 'Unable to find libclang: "couldn't find any valid shared libraries matching: ['libclang.so', 'libclang-*.so', 'libclang.so.*', 'libclang-*.so.*'], set the `LIBCLANG_PATH` environment variable to a path where one of these files can be found (invalid: [])"', /home/admin/.cargo/registry/src/github.com-1ecc6299db9ec823/bindgen-0.59.2/src/lib.rs:2144:31
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
error: build failed
Is this something that would need to be addressed within the dependency crate? (requiring a change to userfaultfd-sys where if libclang is not found on a system it builds via another approach)
I’m trying to track which keys are typed in WSL using the device_query crate. I’ve read the crate’s documentation, added device_query = "0.2.4" to my Cargo.toml file and installed the X11 dependency (sudo apt install libx11-dev).
In my src/main.rs file, I use the crate as intended:
use device_query::{DeviceQuery, DeviceState, MouseState, Keycode};
fn main() {
let device_state = DeviceState::new();
let mouse: MouseState = device_state.get_mouse();
println!("Current Mouse Coordinates: {:?}", mouse.coords);
let keys: Vec<Keycode> = device_state.get_keys();
println!("Is A pressed? {}", keys.contains(&Keycode::A));
}
However, when I run cargo build, I get a 101 exit error:
Updating crates.io index
Compiling x11 v2.18.2
error: failed to run custom build command for `x11 v2.18.2`
Caused by:
process didn't exit successfully: `/home/egerou/Coding/Rust/Wow/target/debug/build/x11-5b031a8b4760d83b/build-script-build` (exit code: 101)
--- stderr
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Command { command: "\"pkg-config\" \"--libs\" \"--cflags\" \"x11\" \"x11 >= 1.4.99.1\"", cause: Os { code: 2, kind: NotFound, message: "No such file or directory" } }', /home/egerou/.cargo/registry/src/github.com-1ecc6299db9ec823/x11-2.18.2/build.rs:36:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
When I read the error, I feel like X11 might not be installed correctly, but if I compile without the device_query = "0.2.4" crate but still the X11 crate (x11 = "2.18.2"), cargo build works.
The error also says a file is missing. Maybe since I’m on WSL, the file isn’t at the correct/expected location.
I’m also using the indexmap = "1.3.2" and rand = "0.5.5" crates. I don’t think they would interfere with the device_query = "0.2.4" crate.
How to build a project that uses the device_query = "0.2.4" crate?
Your error message states (reformatted to make it more readable):
Command {
command: "pkg-config" "--libs" "--cflags" "x11" "x11 >= 1.4.99.1",
cause: Os {
code: 2,
kind: NotFound,
message: "No such file or directory",
}
}
This means that it tried to run the command "pkg-config" "--libs" "--cflags" "x11" "x11 >= 1.4.99.1" but it failed. It failed because the binary pkg-config could not be found.
If you were to run this command in the terminal, presumably you'd see the same error. If so, you need to install pkg-config. If not, then pkg-config might not be in your PATH or is otherwise unavailable to your Rust program. You'll need to investigate where it's installed and why that installation path isn't available to the program.
I have a Rust crate which is a wrapper for a large C API and takes several minutes to compile. Running cargo build in the directory without making any changes always results in a recompile. It seems that Cargo should not be recompiling this crate unless I make a change, which I have not done.
I would like to compile the crate once and avoid re-compiling the crate unless I make a change. Is there any way for me to avoid constantly recompiling this scrate?
It seems that something is likely incorrect in my crate's build script. I will try to create a minimal reproducible example, but in the meantime I have provided the build script below:
use std::env;
use std::fs::copy;
use std::path::Path;
use std::process::Command;
fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let c_src_path = Path::new("parasail_c");
// configure the build
Command::new("cmake")
.arg(".")
.current_dir(&c_src_path)
.output()
.expect("Failed to configure parasail.");
// build the library
Command::new("make")
.current_dir(&c_src_path)
.output()
.expect("Failed to build parasail.");
// put the static library in the right directory so we can clean up
let target_file = format!("{}/libparasail.so", out_dir);
copy("parasail_c/libparasail.so", target_file)
.expect("Problem copying library to target directoy.");
let target_file = format!("{}/parasail.h", out_dir);
copy("parasail_c/parasail.h", target_file)
.expect("Problem copying header to target directoy.");
// clean up the temporary build files
Command::new("make")
.current_dir(&c_src_path)
.arg("clean")
.output()
.expect("Failed to clean up build files.");
// clean up the configuration files
Command::new("make")
.arg("distclean")
.current_dir(&c_src_path)
.output()
.expect("Failed to clean up configuration files.");
// let cargo know that it can find the file in the out directory
println!("cargo:rustc-link-search=native={}", out_dir);
println!("cargo:rustc-link-lib=dylib=parasail");
}
Here is the output from cargo build --verbose
cargo build --verbose
Compiling parasail-sys v0.1.0 (/home/fortier/testcode/rust/pairhmm/parasail-sys)
Fresh libc v0.2.51
Running `/home/fortier/testcode/rust/pairhmm/parasail-sys/target/debug/build/parasail-sys-f2d2d1f27a70b4d4/build-script-build`
Running `rustc --edition=2018 --crate-name parasail_sys src/lib.rs --color always --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=8879665b3d9bf7e1 -C extra-filename=-8879665b3d9bf7e1 --out-dir /home/fortier/testcode/rust/pairhmm/parasail-sys/target/debug/deps -C incremental=/home/fortier/testcode/rust/pairhmm/parasail-sys/target/debug/incremental -L dependency=/home/fortier/testcode/rust/pairhmm/parasail-sys/target/debug/deps --extern libc=/home/fortier/testcode/rust/pairhmm/parasail-sys/target/debug/deps/liblibc-bc949bf21f4fe772.rlib -L native=/home/fortier/testcode/rust/pairhmm/parasail-sys/target/debug/build/parasail-sys-2ac393455c1f3545/out -l dylib=parasail`
Finished dev [unoptimized + debuginfo] target(s) in 1m 58s
After further inspection I have discovered that the issue is somewhere in the C code that the sub-crate is wrapping. I replaced the current C code with an older version, while changing none of the Rust code and the issue has disappeared. I'll continue doing some further investigation to see exactly what was causing the problem and I'll update this post once I narrow it down.
Add to the build script println!("cargo:rerun-if-changed={}", &file); lines for each file and for each directory.
I want to make a GUI application using Rust on Windows 10 and I found the qml crate which looks nice.
I added in my Cargo.toml file this dependency: qml = "0.0.9", but when I run cargo build, I get this error:
> cargo build
Compiling qml v0.0.9
error: failed to run custom build command for `qml v0.0.9`
process didn't exit successfully: `project\target\debug\build\qml-018515e4bf91189d\build-script-build` (exit code: 101)
--- stderr
thread 'main' panicked at 'failed to execute process: The specified file cannot be found. (os error 2)', user\.cargo\registry\src\github.com-1ecc6299db9ec823\qml-0.0.9\build.rs:28:33
note: Run with `RUST_BACKTRACE=1` for a backtrace.
I looked at the build.rs file and I saw this line:
fs::copy(Path::new(&manifest_dir).join("build_lib.sh"), Path::new(&out_dir).join("build_lib.sh")).unwrap();
Maybe I don't have the rights to do that on my account, so I tried to run it as admin, but cargo and rustc are installed in my user folder.
When I change the path, I get the error error: no default toolchain configured.
QML 0.0.9's build script doesn't support Windows.
It appears that support for Windows was added in 80ccad26, which seemingly hasn't been released yet.
You will need to use the version from the git repository instead:
[dependencies]
qml = { git = "https://github.com/White-Oak/qml-rust" }