How to create a dependency bundle? - rust

I want to create a bundle of dependencies to easily include in other cargo projects.
Say I have three different libraries: engine_logger, engine_files, engine_bench.
Is it possible to bundle them together into a dependency called engine_essentials?
#cargo.toml
#So that I can simply do:
[dependencies]
engine_essentials
#instead of:
#engine_logger = {path = "crates/engine_logger"}
#engine_files = {path = "crates/engine_files"}
#engine_bench = {path = "crates/engine_bench:}

You can create a library named engine_essentials which depends on the other three and reexports them; its source code would consist of src/lib.rs:
pub use engine_logger as logger;
pub use engine_files as files;
pub use engine_bench as bench;
Or you could reexport the contents of all three, but this risks running into name conflicts if the 3 libraries have any common module names (common, utils, prelude, that sort of thing):
pub use engine_logger::*;
pub use engine_files::*;
pub use engine_bench::*;

Related

How to get profile from Cargo.toml in build.rs or at runtime

imagine I have a Cargo.toml with this in it:
[profile.performance]
inherits = "release"
opt-level = 3
debug = true
overflow-checks = false
lto = true
codegen-units = 1
[profile.cli]
inherits = "release"
debug = false
opt-level = "z"
lto = true
strip = true
codegen-units = 1
How do I get the profile name, e.g. performance or cli, in either build.rs or at runtime?
I have tried:
The PROFILE env var. This is only ever debug or release.
All of the CARGO_CFG_* env vars in build.rs.
Using something like cfg(profile = "cli").
None of these work. Is this information retrievable in either of these contexts?
I imagine another thing that might work is to add some custom key to each profile section in Cargo.toml, but I'm not sure if you can do that.
Combining the super helpful suggestions in the comments, I was able to get the profile name like this, leveraging this behavior in cargo:
The output for each profile will be placed in a directory of the same name as the profile in the target directory. As in the example above, the output would go into the target/release-lto directory.
Code:
build.rs:
fn main() {}
Note, main can do stuff if you want, all that matters is that it exists.
main.rs:
fn get_build_profile_name() -> String {
// The profile name is always the 3rd last part of the path (with 1 based indexing).
// e.g. /code/core/target/cli/build/my-build-info-9f91ba6f99d7a061/out
std::env!("OUT_DIR")
.split(std::path::MAIN_SEPARATOR)
.nth_back(3)
.unwrap_or_else(|| "unknown")
.to_string()
}
fn main() {
let build_profile_name = get_build_profile_name();
println!("Build profile name: {}", build_profile_name);
}
Run command:
cargo run --profile performance
Output:
Build profile name: performance
Note: This method does not work specifically for the dev, test, and bench pre-included build profiles:
cargo run --profile bench
/code/core/target/release/build/my-build-info-9f91ba6f99d7a061/out
The reason is this, described here:
For historical reasons, the dev and test profiles are stored in the debug directory, and the release and bench profiles are stored in the release directory. User-defined profiles are stored in a directory with the same name as the profile.
I'll leave this question open for now in case there is some other approach we haven't thought of yet.

How to deal with unresolved import 'concrete' issues in RUST

I am new to RUST, and I am trying to use this concrete library: https://github.com/zama-ai/concrete/tree/master/concrete. I am trying to create a simple "Hello World" in RUST to see if concrete imports correctly. I followed the instructions in the aforementioned link.
Specifically, I:
Cloned the GitHub repo.
Cd into concrete folder (/concrete/concrete)
ran "cargo new play_with_fhe"
Updated the "Cargo.toml" file with the new member "play_with_me"
[workspace]
members = [
"concrete",
"concrete-npe",
"concrete-core",
"concrete-csprng",
"concrete-commons",
"concrete-tasks",
"concrete-boolean",
"play_with_fhe",
]
[profile.bench]
opt-level = 3
debug = true
lto="fat"
[patch.crates-io]
concrete = {path="concrete"}
concrete-npe = {path="concrete-npe"}
concrete-core = {path="concrete-core"}
concrete-csprng = {path="concrete-csprng"}
concrete-commons = {path="concrete-commons"}
concrete-boolean = {path= "concrete-boolean"}
play_with_fhe = {path= "play_with_fhe"}
Cd into "/concrete/concrete/play_with_fhe" and updated the "Cargo.toml" file with
[package]
name = "play_with_fhe"
version = "0.1.11"
authors = ["FHE Curious"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
concrete = "^0.1.11"
Cd into /concrete/concrete/play_with_fhe_/src and created a main.rs file running a simple code:
use concrete::*;
fn main() {
println!("Hello, world!");
}
When I try compiling it with rustc main.rs, I get told that:
error[E0432]: unresolved import `concrete`
--> main.rs:2:5
|
2 | use concrete::*;
| ^^^^^^^^ maybe a missing crate `concrete`?
error: aborting due to previous error
For more information about this error, try `rustc --explain E0432`.
How can I address this issue? Any advice would be appreciated.
Since you're trying to create your own hello world project, you don't need to clone the repository. You just need to create a project, include concrete as a dependency, and then import it. Those instructions are on the concrete page (as Stargateur notes):
% cargo new play_with_fhe
% cd play_with_fhe
Add concrete to your dependencies in Cargo.toml:
[package]
name = "play_with_fhe"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
concrete = "^0.1" # <--- This is the only change you make. The rest is template.
Then add use cargo::* to the top of your main.rs, and build it:
% cargo build
This will install everything. For more on Cargo, see Dependencies in Rust By Example.
Note that this package likely won't build correctly unless you're on an x86 architecture. For example, it won't run on an Apple M1 without Rosetta2.

Why can't Rust find the "js_sys" crate?

I'm new to rust. I'm trying to use the crate js_sys which contains a Math::log. I have included js_sys = 0.3.48 as the crate website tells me, and then use js_sys::Math::log; in main.rs. I get an error that rust cannot find the crate.
Steps to replicate:
In Cargo.toml
[package]
name = "sim"
version = "0.1.0"
authors = ["Excluded for privacy"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
js_sys = "0.3.48"
rand = "0.8.3"
In the top of my main.rs
// Luke Anglin and Tobi Solarin
use js_sys::Math::log;
use rand::prelude::*; // For the rng
const n: i32 = 1_000; // The number of trials
Error
error: no matching package named `js_sys` found
location searched: registry `https://github.com/rust-lang/crates.io-index`
perhaps you meant: js-sys
required by package `sim v0.1.0 (/Users/lukeanglin/Desktop/Probability/Project2/simulator/sim)`
Change js_sys to js-sys in your Cargo.toml and it should work. (As stated in the error you posted but easily overlooked)

How to conditionally compile in Rust [duplicate]

I've followed quite a bit of the documentation and tried to reuse an example, but I can't get my code to work.
My Cargo.toml looks like this:
[package]
name = "Blahblah"
version = "0.3.0"
authors = ["ergh <derngummit#ahwell.com"]
[dependencies]
[[bin]]
name = "target"
path = "src/main.rs"
[features]
default=["mmap_enabled"]
no_mmap=[]
mmap_enabled=[]
I'd like to test my code locally with a different buffer origin than mmap based on what feature configuration I pass to the cargo build command. I have this in my code:
if cfg!(mmap_enabled) {
println!("mmap_enabled bro!");
...
}
if cfg!(no_mmap) {
println!("now it's not");
...
}
The compiler doesn't see the code in either of the if statement bodies, so I know that both of the cfg! statements are evaluating to false. Why?
I've read Conditional compilation in Rust 0.10? and I know it's not an exact duplicate because I'm looking for a functioning example.
The correct way to test for a feature is feature = "name", as you can see in the documentation you linked if you scroll a bit:
As for how to enable or disable these switches, if you’re using Cargo,
they get set in the [features] section of your Cargo.toml:
[features]
# no features by default
default = []
# Add feature "foo" here, then you can use it.
# Our "foo" feature depends on nothing else.
foo = []
When you do this, Cargo passes along a flag to rustc:
--cfg feature="${feature_name}"
The sum of these cfg flags will determine which ones get activated,
and therefore, which code gets compiled. Let’s take this code:
#[cfg(feature = "foo")]
mod foo {
}
In your case using the cfg! macro, this would map to cfg!(feature = "foo").

How to make interface and implementation files separately?

I would like to make interface (class, or instance) and implementation files in Haskell separately as follow:
file1: (For interface)
class X where
funcX1 = doFuncX1
funcX2 = doFuncX2
....
instance Y where
funcY1 = doFuncY1
funcY2 = doFuncY2
...
file 2: (For implementation)
doFuncX1 = ...
doFuncX2 = ...
doFuncY1 = ...
...
How can I do that when file1 must be imported in file2 and vice versa ?
You don't need any such cumbersome separation in Haskell. Just mark only what you want to be public in the module export list (module Foo ( X(..) ... ) where ...), build your project with cabal, and if you want to export a library but not release the source code you can simply publish only the dist folder with the binary interface files and the Haddock documentation. That's much more convenient than nasty e.g. .h and .cpp files that need to be kept manually in sync.
But of course, nothing prevents you from putting implementations in a seperate, non-public file. You just don't need to do "vice versa" imports for this, only perhaps a common file with the necessary data type declarations. E.g.
Public.hs:
module Public(module Public.Datatypes) where
import Public.Datatypes
import Private.Implementations
instance X Bar where { funcX1 = implFuncX1; ... }
Public/Datatypes.hs:
module Public.Datatypes where
data Bar = Bar { ... }
class X bar where { funcX1 :: ... }
Private/Implementations.hs:
module Private.Implementations(implFuncX1, ...) where
import Public.Datatypes
implFuncX1 :: ...
implFuncX1 = ...
But usually it would be better to simply put everything in Public.hs.

Resources