How to use ext4 Rust Crate [duplicate] - rust

I'm trying to work with the rust-http library, and I'd like to use it as the basis for a small project.
I have no idea how to use something that I can't install via rustpkg install <remote_url>. In fact, I found out today that rustpkg is now deprecated.
If I git clone the library and run the appropriate make commands to get it built, how do I use it elsewhere? I.e. how do I actually use extern crate http?

Since Rust 1.0, 99% of all users will use Cargo to manage the dependencies of a project. The TL;DR of the documentation is:
Create a project using cargo new
Edit the generated Cargo.toml file to add dependencies:
[dependencies]
old-http = "0.1.0-pre"
Access the crate in your code:
Rust 2021 and 2018
use old_http::SomeType;
Rust 2015
extern crate old_http;
use old_http::SomeType;
Build the project with cargo build
Cargo will take care of managing the versions, building the dependencies when needed, and passing the correct arguments to the compiler to link together all of the dependencies.
Read The Rust Programming Language for further details on getting started with Cargo. Specifying Dependencies in the Cargo book has details about what kinds of dependencies you can add.

Update
For modern Rust, see this answer.
Original answer
You need to pass the -L flag to rustc to add the directory which contains the compiled http library to the search path. Something like rustc -L path-to-cloned-rust-http-repo/build your-source-file.rs should do.
Tutorial reference

Not related to your post, but it is to your title. Also, cargo based.
Best practice:
external crate named foo
use ::foo;
module (which is part of your code/crate) named foo
use crate::foo;
In both the cases, you can use use foo; instead, but it can lead to confusion.

Once you've built it, you can use the normal extern crate http; in your code. The only trick is that you need to pass the appropriate -L flag to rustc to tell it where to find libhttp.
If you have a submodule in your project in the rust-http directory, and if it builds into its root (I don't actually know where make in rust-http deposits the resulting library), then you can build your own project with rustc -L rust-http pkg.rs. With that -L flag, the extern crate http; line in your pkg.rs will be able to find libhttp in the rust-http subfolder.

I ran into a similar issue. I ended up doing this in my Cargo.toml
[dependencies]
shell = { git = "https://github.com/google/rust-shell" }
Then in my main.rs I was able to add this and compile with success. Note that this cargo package is a macro in my case. Often you will not want to have the #[macro_use] before the extern call.
#[macro_use] extern crate shell;

Related

rust libraries with cargo (rlib)

I am trying to create a library in rust to be used with rust executables. In C you can just create your .a or .so (or .lib or .dll on windows) and use tools like CMake to link everything, however rust does not seem to have this kind of infrastructure?
It is possible to make an executable with cargo (cargo new ) and create a library by adding the --lib flag (cargo new --lib), but then how would you use the resulting .rlib file (from the library cargo project)? I managed to link the .rlib file as follows:
rustc main.rs --extern foo=libfoo.rlib
and that works beautifully, though, I am not interested in writing a thousand rustc commands to build the final executable (which depends on the .rlib) if there is cargo that can do that for you. I tried working with a build script (which works perfectly for any C library, static or dynamic), but if I try it with the .rlib file, cargo says that it cannot find "foo" (-lfoo), the build script:
fn main() {
println!("cargo:rustc-link-search=.");
println!("cargo:rustc-link-lib=foo");
}
I tried replacing the path (search) to different directories (whilst also moving the .rlib file to the correct directory), also tried different combinations of libfoo, libfoo.rlib, ... (note that for the C libaries, foo is sufficient).
So my question really is: How can you create a rust library for private use, and how do you use it with a rust executable in a proper way, avoiding manual rustc commands? Are there tools that do this? Am I missing something in the build script? Perhaps there exists something like CMake for rust?
I suppose it is possible to just create a C interface over the rust code and compile another C project as that does work with cargo.
I do NOT want to publish the code to crates.io as I want this library strictly for private use.
Cargo does not support using pre-compiled .rlibs. Cargo is designed to compile programs fully from source (not counting native libraries).
How can you create a rust library for private use … I do NOT want to publish the code to crates.io as I want this library strictly for private use.
To use a private library, you write a dependency using a path or git dependency (or use a private package registry, but that's more work to set up).
[dependencies]
my-lib-a = { path = "../my-lib-a/" }
my-lib-b = { git = "https://my-git-host.example/my-lib-b", branch = "stable" }
Your private library is now compiled exactly like a “public” one.

How to compile to both wasm and binary in a Rust crate?

I'm writing the back-end for a web application and would like to reuse some logic for client-side. I want to use wasm to generate a library which Javascript can use. Suppose the logic is in lib.rs. What should I do, so that:
The back-end can import and use the code in lib.rs as normal, also cargo build generates a binary as expected.
Rust generates a wasm library for lib.rs
I tried adding these to my cargo file (by following this: Rust package with both a library and a binary?):
[lib]
crate-type = ["cdylib", "rlib"]
[[bin]]
name = "mybin"
path = "src/main.rs"
But it seems like cargo is building my binary for the browser, so it is missing all the sys crate.
You can ask for only your library to be built using the --lib option.
cargo build --lib --target wasm32-unknown-unknown
So my current approach is to create a separate package for lib.rs and use it as a dependency for the back-end, as outlined in here:
What is an idiomatic way to have shared utility functions for integration tests and benchmarks?
It seems to work well enough.

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.

Is it possible to run a single rust file as a script while linking to other libraries without generating cargo projects

I'd like to run a one off rust "script" without going through creating a cargo project for a single run (since I am providing this script to colleagues).
Ideally I could build directly with the command line avoiding creating cargo projects etc.
for instance:
use serde_json::Value;
use some_private_packege_i_own_locally_in_another_directory;
fn main() {
// do some stuff with these packages and die
}
I would need to depend on the serde_json and my some_private_packege_i_own_locally_in_another_directory.
(A bit similar to rust playground I suppose for a single time use)
Something similar to this from the command line would be great:
rustc /path/to/main.rs --dependency serde_json, my_package ...
You can specify a dependency with with extern flag, and you can specify the location of transitive dependencies, with -L dependency. You will have to compile each dependency, and all of it's dependencies manually:
// compile all of serde's dependencies
// compile all of hyper's dependencies
// compile serde
// compile hyper
rustc script.rs --crate-type bin -L dependency=~/tmp/deps --extern serde_json=~/tmp/deps/serde_json.rlib --extern hyper=~/tmp/deps/hyper.rlib
As you can tell, this would get very difficult, even with two direct dependencies. Instead, you can use cargo-script, which handles all of this for you:
cargo install cargo-script
cargo script -D hyper -D serde_json script.rs

Why do I get "can't find crate" that is listed as a dependency in Cargo.toml when I compile with rustc?

My Cargo.toml includes this:
[dependencies]
chrono = "0.4"
And my code includes this:
extern crate chrono;
use chrono::{Duration, DateTime, Utc};
yet when I run my code, I get this error:
error[E0463]: can't find crate for `chrono`
--> src/lib.rs:1:1
|
1 | extern crate chrono;
| ^^^^^^^^^^^^^^^^^^^^ can't find crate
I am working on an Exercism exercise, so the way I am building/running the program is rustc src/lib.rs to test my solution. Is the problem because I'm not running rustc src/main.rs?
When you're directly running rustc, all that compiler knows is the command line arguments. It doesn't know anything about Cargo.toml, in particular, and so it doesn't know where to look for chrono library.
To use dependency management, you have to compile your project with Cargo - just use cargo build/cargo run/cargo test, and everything should be fine. See the Book for details.
If, however, you want (for some reason) use rustc directly, I'd advise to check first cargo anyway, by using cargo build --verbose. It will show all the commands that are invoked, allowing you to inspect the possible arguments to be defined manually.

Resources