Import rust package with alias in toml - rust

I'm trying to make a simple program checking execution times on two different branches of the same rust project.
I wanted to have my .toml look something like this
[dependencies]
cron_original = { git = "https://github.com/zslayton/cron" }
cron_fork = { git = "https://github.com/koenichiwa/cron", branch = "feature/reimplement-queries"}
And my program look something like this:
fn main() {
let expression = String::from("0-59 * 0-23 ?/2 1,2-4 ? *");
let schedule_orig = cron_original::Schedule::from_str(expression);
let schedule_fork = cron_fork::Schedule::from_str(expression);
// Check difference in execution times on these structs
}
but I'm getting no matching package named 'cron_fork' found. Is there anyway to import a package with a specific alias? I was thinking about creating something that would automate checks like this.

You need to specify package keys for those dependencies so cargo knows that you really want those packages even though you specify a different name:
[dependencies]
cron_original = { git = "https://github.com/zslayton/cron", package="cron" }
cron_fork = { git = "https://github.com/koenichiwa/cron", branch = "feature/reimplement-queries", package="cron" }
See the Renaming dependencies in Cargo.toml section in Specifying Dependencies documentation for details.

Related

Patch.crates-io is not applied

I am using serde-xml-rs crate in our project and I need to modify some code from that crate, so what I did is to generate a patch file, and apply it by calling cargo patch. In my Cargo.toml has stuff like following:
serde-xml-rs = "0.6.0"
[package.metadata.patch.serde-xml-rs]
version = "0.6.0"
patches = [
"patches/0001.patch"
]
[patch.crates-io]
serde-xml-rs = { path = "./target/patch/serde-xml-rs-0.6.0" }
When I called cargo run, project still use original version of serde-xml-rs instead of using values in patch.crates-io tag
But I could see that my patch is applied correctly to the target folder "./target/patch/serde-xml-rs-0.6.0", because if I modify toml file to following, it worked.
{ path = "./target/patch/serde-xml-rs-0.6.0" }

How to create a target specific profile in Cargo.toml?

I would like to specify a separate [profile.release] for my library when cfg(target_os = "ios") is active. I tried this:
[profile.'cfg(not(target_os = "ios"))'.release]
lto = true # Use link-time optimization.
[profile.'cfg(target_os = "ios")'.release]
lto = true # Use link-time optimization.
opt-level = "z" # Mobile devices are fast enough. Optimize for size instead.
strip = "symbols" # Not relevant for windows.
However when I now try to build my project / workspace I get the following error:
error: failed to parse manifest at `/path/to/Cargo.toml`
Caused by:
invalid character `(` in profile name `cfg(not(target_os = "ios"))`
Allowed characters are letters, numbers, underscore, and hyphen.
which is to be expected, because according to the documentation only [profile.<name>] is allowed.
Is there any method to achieve the desired behaviour?
P.S. The full target name would be aarch64-apple-ios in case this is needed.
This was requested in issue #4897, Per-target profiles?, but not yet implemented.
In the meantime, you can use a script that checks the target and set environment variables to override config (for example, set CARGO_PROFILE_RELEASE_LTO or CARGO_PROFILE_RELEASE_OPT_LEVEL) then invokes Cargo with them.
Here is an example, from users.rust-lang.org - How to modify profile.release only for a target?
Create a binary in the workspace named e.g. custom_build. In custom_build/src/main.rs put:
use std::env;
use std::process::Command;
fn main() {
let mut cargo = Command::new(env::var_os("CARGO").unwrap());
cargo.env("CARGO_CUSTOM_BUILD", "1"); // So we can disallow regular builds, to prevent mistakes
cargo.args(env::args_os().skip(1));
// You can determine the target OS by various way, but providing it manually to the build script is the simplest.
let for_ios = env::var("build_ios").is_ok();
if for_ios {
cargo.env("CARGO_PROFILE_RELEASE_LTO", "true");
cargo.env("CARGO_PROFILE_RELEASE_OPT_LEVEL", "z");
cargo.env("CARGO_PROFILE_RELEASE_STRIP", "symbols");
} else {
cargo.env("CARGO_PROFILE_RELEASE_LTO", "true");
}
let cargo_succeeded = cargo.status().ok().map_or(false, |status| status.success());
if !cargo_succeeded {
std::process::exit(1);
}
}
Then you can create a build.rs file to prevent manually running cargo:
use std::env;
fn main() {
if !env::var("CARGO_CUSTOM_BUILD").ok().map_or(false, |s| s == "1") {
panic!("Do not run `cargo ...`, run `cargo custom_build ...` instead")
}
}

How can I disable testing for a Haskell package in Nix?

I'm trying to get a development environment going for Haskell, using Nix. I have a default.nix that just refers to my .cabal file for the list of packages. But one package I want to use, numhask-space, won't build, because the tests are failing. So I'm trying to override it and skip the tests.
Here's my default.nix:
# default.nix
let
pkgs = import <nixpkgs> { };
in
pkgs.haskellPackages.developPackage {
root = ./.;
modifier = drv:
pkgs.haskell.lib.addBuildTools drv (with pkgs.haskellPackages;
[ cabal-install
ghcid
]);
source-overrides = {
numhask-space = pkgs.haskell.lib.dontCheck pkgs.haskellPackages.numhask-space;
};
}
But I must not be doing this right, because I get the error:
cabal2nix: user error (Failed to fetch source. Does this source exist? Source {sourceUrl = "/nix/store/w3pcvlj7b0k44v629k00kw2b0k86fcyj-numhask-space-0.3.0", sourceRevision = "", sourceHash = Guess "", sourceCabalDir = ""})
In short, how can I override this haskell package so that it doesn't run the tests, and I can install it in my development environment?
source-overrides overrides sources of the packages, that is, literally, the src attributes, rather than packages as a whole. You should use the overrides argument instead:
overrides = self: super: {
numhask-space = pkgs.haskell.lib.dontCheck super.numhask-space;
};

How to import substrate_primitives in order to use sr25519?

I have the following dependencies in my Cargo.toml file:
[package]
name = "api-client-tutorial"
version = "0.1.0"
authors = ["Supercomputing Systems AG <info#scs.ch>"]
edition = "2018"
[dependencies]
substrate-api-client = { git = "https://github.com/scs/substrate-api-client.git" }
codec = { package = "parity-scale-codec", features = ["derive"], version = "1.0.0", default-features = false }
[dependencies.primitives]
git = "https://github.com/paritytech/substrate"
rev = "3bf9540e72df5ecb3955845764dfee7dcdbb26b5"
package = "substrate-primitives"
[dependencies.keyring]
git = "https://github.com/paritytech/substrate"
rev = "3bf9540e72df5ecb3955845764dfee7dcdbb26b5"
package = "substrate-keyring"
I am unsure of the difference between dependencies section and dependencies.primitives section, but the package substrate-primitives is included in the primitives section.
I have seen that substrate_primitives has the module sr25519 I need to use, but when I try to import it in my code:
use substrate_api_client::{Api, node_metadata};
use substrate_primitives::sr25519;
fn main() {
// instantiate an Api that connects to the given address
let url = "127.0.0.1:9944";
// if no signer is set in the whole program, we need to give to Api a specific type instead of an associated type
// as during compilation the type needs to be defined.
let api = Api::<sr25519::Pair>::new(format!("ws://{}", url));
let meta = api.get_metadata();
println!("Metadata:\n {}", node_metadata::pretty_format(&meta).unwrap());
}
I get the following error:
unresolved import `substrate_primitives`
use of undeclared type or module `substrate_primitives`rustc(E0432)
main.rs(2, 5): use of undeclared type or module `substrate_primitives`
How do I import sr25519 so that I can use the following line in my code?
let api = Api::<sr25519::Pair>::new(format!("ws://{}", url));
The difference between tables under [dependencies] and the [dependencies.primitives] table is that the table for the primitives dependency is not inlined. You could also just inline the primitives dependency and put it under [dependencies] like that:
primitives = { git = "https://github.com/paritytech/substrate", rev = "3bf9540e72df5ecb3955845764dfee7dcdbb26b5", package = "substrate-primitives" }
The toml documentation can give you more details on tables and inline tables.
Regarding your problem. You cannot import the crate like that, because it is renamed to primitives. The package field specifies the real name of the dependency and the table name defines the new name which is used to import it inside your project. For details have a look at the cargo documentation.
Your import should therefore look like this: use primitives::sr25519;

Gradle - Can I manage task dependencies using convention properties?

I'm using Gradle as a build system for my project.
What I want is to make task A depend on task B if a given property is set to "true". Is this doable, and if the answer is yes, how can I do that?
Currently, I'm using conventionMapping but this doesn't seem to work. My code looks like this:
MyTask.conventionMapping.propertyName = { MyPluginConvention.propertyName }
if (MyTask.propertyName.equals("true")) {
MyTask.dependsOn ...
}
Thanks in advance,
Marin
Instead of working with task/convention classes, you'll have to work with their instances. Also, you'll have to defer the decision whether to add a task dependency. For example:
def myTask = project.tasks.create("myTask", MyTask)
def otherTask = ...
def myConvention = new MyConvention()
...
myTask.conventionMapping.propertyName = { myConvention.propertyName }
// defer decision whether to depend on 'otherTask'
myTask.dependsOn { myTask.propertyName == "true" ? otherTask : [] }
If there's no task variable in scope, you can also reference existing tasks via project.myTask or project.tasks["myTask"].
PS: Convention objects have been largely replaced by extension objects.

Resources