How to use Rust's async/await syntax in WASI - rust

I would like to compile the following code with cargo-wasi.
// reqwest = { version = "0.11", features = ["json"] }
// tokio = { version = "1", features = ["full"] }
use std::collections::HashMap;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::get("https://httpbin.org/ip")
.await?
.json::<HashMap<String, String>>()
.await?;
println!("{:#?}", resp);
Ok(())
}
After trying to compile it, I got the following error because mio doesn't currently support WASI
$ cargo wasi run
Compiling mio v0.7.9
Compiling parking_lot v0.11.1
Compiling serde_json v1.0.64
Compiling idna v0.2.2
error[E0432]: unresolved import `crate::sys::IoSourceState`
--> /home/ducaale/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.7.9/src/io_source.rs:12:5
|
12 | use crate::sys::IoSourceState;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ no `IoSourceState` in `sys`
... errors omitted
I did some research and none of the examples I found so far were utilizing async/await. Is there something I could replace tokio with so my code compiles in WASI?

I tried running this and it seems the reqwests crate doesn't build correctly with cargo wasi or wasm-pack because it's unable to compile mio (which is used by tokio when compiling natively). There is some mention on github that reqwests can be used with wasm, but it's not yet fully supported, and I couldn't find much on how to make it work. It sounds like there isn't much solution yet for HTTP requests on WASI at this time, but web-sys can be used to make requests through Node.js or a browser.
It appears that tokio requires specific features flags in order to be used with web assembly. This issue mentions the sync and rt flags at the bottom: https://github.com/tokio-rs/tokio/issues/1597 but in order to also use #[tokio:main], you will need the "rt-multi-thread" and "macros" feature flags as well.
It might also be possible to use wasm bindgen to convert the future into a promise, but that might not work with WASI: https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen_futures/

Try removing networking from tokio:
tokio = { version="1.21.1", features=["rt","sync","time"] }

Related

Unable to use rust crates

I'm new to rust. I'm following a getting started tutorial that imports the crate random-number but when running the code I'm getting the error can't find crate for 'random_number'. What am I doing wrong?
~/Cargo.toml:
[package]
name = "test"
version = "0.0.1"
edition = "2021"
[dependencies]
random-number = "0.1.8"
~/src/main.rs:
extern crate random_number;
use random_number::random;
fn main() {
let num: i8 = random!(..);
println!("{}", num);
}
rustc is not meant to be used directly. It is the compiler that can compile a .rs file, but it doesn't have any dependency manager attached to it. So if you decide to use rustc directly, you need to manage your dependencies manually.
cargo is the official tool to compile Rust projects. It internally uses rustc, but additionally manages the project's dependencies that are specified in Cargo.toml.
cargo build --release && ./target/release/<project_name>
or the short form:
cargo run --release

Conditional compilation for 'nightly' vs 'stable' Rust or compiler version

I am using some Rust unstable features, but I still want to be able to compile a reduced version of my library with stable Rust. I am happy to only include those unstable features when the compiler supports them, and exclude them when they are not supported.
I thought it would be easy to achieve this goal using conditional compilation like #[cfg(rust_version = "nightly")], but it seems like 'stable' vs 'nightly' are not cfg options.
How do you guys perform conditional compilation based on 'stable' vs 'nightly', or based on the compiler version?
I recommend creating a feature for your nightly-only code that is disabled by default, for example
Cargo.toml
[features]
default = []
nightly-features = []
Since the nightly-features feature is not default, compilation with the stable toolchain works out of the box. You can use attributes #[cfg(feature = "nightly-features")] and #[cfg(not(feature = "nightly-features"))] to include or exclude code from nightly-specialized versions. This method has the added benefit of allowing testing of the nightly features independently of the compiler (i.e. answer the question: did the compiler break my code, or does code enabled by nightly-features contain bugs?).
Despite the risks, I want to enable nightly features automatically
Use build scripts, sometimes called build.rs in addition to the nightly feature described above. (note: the following should NEVER be used in a library, otherwise switching compilers could become a breaking change. prefer the solution explained above)
build.rs (goes in package root)
use std::env;
fn main() {
let rust_toolchain = env::var("RUSTUP_TOOLCHAIN").unwrap();
if rust_toolchain.starts_with("stable") {
// do nothing
} else if rust_toolchain.starts_with("nightly") {
//enable the 'nightly-features' feature flag
println!("cargo:rustc-cfg=feature=\"nightly-features\"");
} else {
panic!("Unexpected value for rustc toolchain")
}
}
this build script checks the toolchain environment variable set by rustup (some rust installations do not use rustup) and enables the nightly feature flag if the compiler is nightly.
src/main.rs
fn main() {
#[cfg(feature = "nightly-features")]
println!("Hello, nightly!");
#[cfg(not(feature = "nightly-features"))]
println!("Hello, stable!");
}
now, running
➜ cargo +stable run
Hello, stable!
➜ cargo +nightly run
Hello, nightly!
Is it possible to turn this feature off when build.rs turns it on?
As far as I can tell, no. Running cargo +nightly run --no-default-features leaves the feature on, due to how cargo passes flags to rustc. A programmer could create a specific environmental variable that build.rs checks for to skip the automatic version detection, but that is more complicated than the alternative with no build script - cargo build --features=nightly-features
Crate alternative
Instead of the proposed solution, you can use the rustversion crate, which works in a very similar way (but parses the output of rustc --version).
fn main() {
#[rustversion(nightly)]
println!("Hello, nightly!");
#[rustversion::not(nightly)]
println!("Hello, stable! (or beta)");
}

cannot find function `get_platform` in sdl2 0.31.0

I'm using the latest version of sdl2 (0.31.0) but cannot access get_platform:
extern crate sdl2;
pub fn main() {
println!("{}", sdl2::get_platform());
}
$ cargo run
Compiling repro v0.1.0 (file:///private/tmp/repro)
error[E0425]: cannot find function `get_platform` in module `sdl2`
--> src/main.rs:4:30
|
4 | println!("{}", sdl2::get_platform());
| ^^^^^^^^^^^^ not found in `sdl2`
I tried with use sdl2::*; and with cargo +nightly run, but neither removed the error.
The documentation you are reading is is not for the version you are using. Build it yourself (cargo doc --open) or view it on docs.rs.
That function was added recently and has not been released yet. Perhaps you should file an issue for the authors of the crate to let them know that having documentation that doesn't correspond to any released code is confusing.
In the meantime, you can use a git dependency if you really need it.

Unable to find crate that is listed in [build-dependencies] section

I try to compile my project with the command cargo build.
build.rs
extern crate csv;
use std::path::Path;
use std::fs::OpenOptions;
use std::io::BufWriter;
use std::io::Write;
#[allow(non_snake_case)]
fn processCSV(filename: &str, sourcePath: &str, enumName: &str) {
println!("Generate rust source code from schema {}",filename);
let mut ret: Vec<String> = Vec::new();
let mut rdr = csv::Reader::from_file(filename).unwrap().flexible(true);
for record in rdr.records().map(|r| r.unwrap()) {
}
let path = Path::new(sourcePath);
let file = match OpenOptions::new().write(true).create(true).open(&path) {
Ok(file) => file,
Err(..) => panic!("Cannot create file {}",path.display()),
};
let mut writer = BufWriter::new(file);
writer.write_all(b"test\n");
}
fn main() {
processCSV("../schemas/Test.csv", "./src/mod/common/StatusCode.rs", "StatusCode");
}
and Cargo.toml
[package]
name = "rust-test"
version = "0.0.1"
build = "build.rs"
[lib]
path = "src/lib.rs"
[dependencies]
[build-dependencies]
csv = "*"
I can see this error :
src/lib.rs:1:1: 1:18 error: can't find crate for csv
src/lib.rs:1 extern crate csv;
but when I change flexible(true) to flexible(false) it compiles just fine without any errors. What do I need to do to fix this?
I am using Rust 1.2.0 on Windows 7 64-bit.
Changing flexible(false) for flexible(true) makes no difference for me; both fail. The problem is that you've chosen build-dependencies for some reason, instead of just dependencies.
Using the src/lib.rs file that you provided in your answer, and this Cargo.toml file:
[package]
name = "stack-overflow"
version = "0.1.0"
authors = ["A. Developer <a.developer#example.com>"]
[dependencies]
csv = "*"
It compiles fine.
If you need to access a dependency both in your build.rs and in your project, you need to include the dependency in both sections.
A build dependency is a dependency for a build script, which is a helper binary compiled and run before your main crate is built (designed to be used for code-generation, and building/finding native C libraries, etc.).
Normal dependencies used by the main code should just fall into the "dependencies" section, e.g.
[dependencies]
csv = "0.14"
There's also a "dev-dependencies" section, which are dependencies that are only needed for testing, i.e. they are compiled and used only for cargo test. This allows crates to depend on, for example, quickcheck for running tests without contaminating the main artifact.
In summary, running cargo build will do something like:
build any build-dependencies
build the build script (pointing the compiler to the built build-dependencies), and run it
build any dependencies
build the main crate (pointing the compiler to the built dependencies)
Running cargo test adds:
build any dev-dependencies
build the main crate with --test to create a test runner for any in-source #[test]s (pointing the compiler to both the dependencies and dev-dependencies)
build any external examples or tests, also pointing to both the dependencies and dev-dependencies

"expected crate directive" error about rust

Editor's note: This question was asked before Rust 1.0 was released and the syntax, error messages, and even how crates are bundled have changed since then.
i wrote a rust example program.
code is this:
use std;
import std::io;
fn main() {
io::println("hello world");
}
i try to compile it, but the rustc compile tell me some error message .
hello.rc:4:0: 4:2 error: expected crate directive
hello.rc:4 fn main() {
^~
my rustc version is
macmatoMacBook-Air:test kula$ rustc -v
rustc 0.1.1 (a0f0a70 2012-03-10 00:35:02 -0800)
host: x86_64-apple-darwin
and my os is mac osx 10.7
anyone know what happened? i think my rust code has no problem on it.
The compiler is trying to be smart and behaves differently for .rs (source) and .rc (crate) files.
Try again with a .rs file extension! :)

Resources