Rust wasm module build error (x11-clipboard dependency) - rust

Recently I knew about web assembly and was messing around with it in rust. Eventually I run into build problem. My toml file looks like this
[package]
name = "clipboard-manager"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = ["console_error_panic_hook"]
[dependencies]
x11-clipboard = "0.5.2"
wasm-bindgen = "0.2.63"
js-sys = "0.3.55"
console_error_panic_hook = { version = "0.1.6", optional = true }
#libc = "0.2.105"
# log = "0.4.14"
# x11 = "2.19.1"
[profile.release]
# Tell `rustc` to optimize for small code size.
opt-level = "s"
[lib]
crate-type = ["cdylib", "rlib"]
And when I want to build .wasm file with wasm-pack build --target web command I get bunch of errors like this
error[E0425]: cannot find function `malloc` in crate `libc`
--> /mnt/commondisk/filip/Development/personal/clipboard-manager/target/wasm32-unknown-unknown/release/build/xcb-64883900109c6e35/out/shape.rs:98:29
|
98 | let raw = libc::malloc(32 as usize) as *mut xcb_shape_notify_event_t;
| ^^^^^^ not found in `libc`
error[E0425]: cannot find function `malloc` in crate `libc`
--> /mnt/commondisk/filip/Development/personal/clipboard-manager/target/wasm32-unknown-unknown/release/build/xcb-64883900109c6e35/out/xfixes.rs:238:29
|
238 | let raw = libc::malloc(32 as usize) as *mut xcb_xfixes_selection_notify_event_t;
| ^^^^^^ not found in `libc`
error[E0425]: cannot find function `malloc` in crate `libc`
--> /mnt/commondisk/filip/Development/personal/clipboard-manager/target/wasm32-unknown-unknown/release/build/xcb-64883900109c6e35/out/xfixes.rs:330:29
|
330 | let raw = libc::malloc(32 as usize) as *mut xcb_xfixes_cursor_notify_event_t;
| ^^^^^^ not found in `libc`
I maneged to build wasm module by commenting out x11-clipboard dependency. I tried to build this module with x11-clipboard dependencies and it was also failing until I commented out xcb dependency. It also fails if I add x11 crate. For a while I thought libc could be a problem but I had not problem building module with this dependency.
Does anyone know why some dependencies cause building process failing and how to fix it? If it's impossible to fix can someone explain me why? Thanks in advance!

Related

How do I fix my compatability errors when using plotters::CairoBackend with GTK

I am trying to draw an image on a very basic GUI. I am using GTK for the GUI and want to use the plotters crate for the drawing but am having issues initiating the Backend that plotters uses.
I have successfully managed to use the BitMapBackend to draw to a file - there is no shortage of examples on the internet for this. However, I cannot for the life of me find an example of how to use the CairoBackend to draw onto a gtk DrawingArea.
My issue arises when I try to connect the draw event to the GTK DrawingArea. I use the connect_draw method which works as expected returning a context to pass to the CairoBackEnd. The problem is that the type of context returned by connect_draw is not compatible with the type of context required by the CairoBackend. I receive context of type 'gtk::cairo::Context' (defined in cairo-rs v0.16.7) but the backend requires a context of 'cairo::context:Context' (defined in cairo-rs v0.15.12). Clearly my dependencies are using different versions of the cairo-rs crate. Presumably, the versions of my dependencies are not compatible with each other. How can I fix this? How do I find out what version of each dependency will work with the others? My cargo.toml file contains:
[package]
name = "testing3"
version = "0.1.0"
edition = "2021"
[dependencies]
gtk = "0.16.2"
plotters = "0.3.4"
plotters-cairo = "0.3.2"
My rust code is:
use gtk::prelude::*;
use plotters::prelude::*;
use gtk::{Application, ApplicationWindow};
fn main() {
let app = Application::builder().build();
app.connect_activate(build_gui);
app.run();
}
fn build_gui(app: &Application){
let win = ApplicationWindow::builder().application(app).default_width(320).default_height(200).title("Test").build();
let da: gtk::DrawingArea = gtk::DrawingArea::builder().build();
da.connect_draw(move|_, c|{
let root = plotters_cairo::CairoBackend::new(c, (1024, 768)).unwrap().into_drawing_area();
gtk::Inhibit(false)
});
win.add(&da);
win.show_all();
}
my error message is:
--> src/main.rs:21:49
|
21 | let root = plotters_cairo::CairoBackend::new(c, (1024, 768)).unwrap().into_drawing_area();
| --------------------------------- ^ expected struct `cairo::context::Context`, found struct `gtk::cairo::Context`
| |
| arguments to this function are incorrect
|
= note: struct `gtk::cairo::Context` and struct `cairo::context::Context` have similar names, but are actually distinct types
note: struct `gtk::cairo::Context` is defined in crate `cairo`
--> /home/maindesktop/.cargo/registry/src/github.com-1ecc6299db9ec823/cairo-rs-0.16.7/src/context.rs:72:1
|
72 | pub struct Context(ptr::NonNull<cairo_t>);
| ^^^^^^^^^^^^^^^^^^
note: struct `cairo::context::Context` is defined in crate `cairo`
--> /home/maindesktop/.cargo/registry/src/github.com-1ecc6299db9ec823/cairo-rs-0.15.12/src/context.rs:72:1
|
72 | pub struct Context(ptr::NonNull<cairo_t>);
| ^^^^^^^^^^^^^^^^^^
= note: perhaps two different versions of crate `cairo` are being used?
note: associated function defined here
--> /home/maindesktop/.cargo/registry/src/github.com-1ecc6299db9ec823/plotters-cairo-0.3.2/src/backend.rs:70:12
|
70 | pub fn new(context: &'a CairoContext, (w, h): (u32, u32)) -> Result<Self, CairoError> {
| ^^^
For more information about this error, try `rustc --explain E0308`.
error: could not compile `testing3` due to previous error
------------------
(program exited with code: 101)
So with more digging around I have found the solution.
As I identified from the error message, my code had a compatibility problem. The gtk v0.16.2 dependency in my toml file depended itself on cairo-rs v0.16.7 where as the plotters-cairo v0.3.2 depended on cairo-rs v15.12. Clearly, I had to use an earlier version of the gtk dependency - one that depended on cairo-rs v15.12. But which one.
On the Doc.rs website I could find the gtk crate documents on https://docs.rs/gtk/0.6.0/gtk/. A tab on top left, gtk-0.6.0, on being selected provided both dependency data and versioning options. I could see that the latest version of the gtk crate did indeed depend on cairo-rs 0.6.0. Selecting the various versions I was able to find the latest version that still depended on cairo-rs v15.xx. In this case it was gtk v0.15.5. Once I replaced my gtk dependency with that version, all was good. So my new toml was:
[package]
name = "testing3"
version = "0.1.0"
edition = "2021"
[dependencies]
gtk = "0.15.5"
plotters = "0.3.4"
plotters-cairo = "0.3.2"
Now by adding the code:
c.rectangle(10.0, 10.0, 70.0, 70.0);
c.fill().expect("Drawing failed");
root.fill(&RED).unwrap();
above my gtk::Inhibit(false) statement, I could indeed create a red rectangle

How do I specify that Cargo should build binaries only on a certain target?

I have a Cargo project set up with a library and a binary. The library is meant to be used on many platforms, including Android, while the binary is only meant to be used on Linux. As such, the binary contains a bunch of Linux-specific code that does not compile when I target Android. Is there a way to specify (without using features) that the binary should only be compiled on Linux?
I tried putting #![cfg(target_os = "linux")] in the main.rs of my binary, but then I got this error:
error[E0601]: `main` function not found in crate `server`
--> src/bin/server/main.rs:1:1
|
1 | / #![cfg(target_os = "linux")]
2 | |
3 | | use anyhow::{self, Context};
4 | |
... |
36 | | }
37 | | }
| |_^ consider adding a `main` function to `src/bin/server/main.rs`
I had exactly the same problem. The official Rust docs do not seem to mention how to solve it. But I found a solution.
The trick is to specify two main() functions in the file main.rs. The first one contains the code you want to execute when you are on Linux. The second one remains empty. With the help of conditional compilation, you tell the compiler which of the two main() functions to compile.
// within main.rs
#[cfg(target_os = "linux")]
fn main() {
// Your Linux-specific code goes here...
}
#[cfg(not(target_os = "linux"))]
fn main() {} // remains empty for all other OS
If you have OS-specific imports or other code at the top-level, just wrap it inside a module and use conditional compilation for it as well.
#[cfg(target_os = "linux")]
mod linux {
use anyhow::{self, Context};
// ...
}
The below link has related information that should help you in terms of target selection and selective compilation https://doc.rust-lang.org/cargo/commands/cargo-build.html#target-selection

Clap options with derive macros fails to compile in rust clap 3.0.0-beta.5

I'm trying out the "Using Derive Macros" example on the index page for the latest beta version of clap:
// (Full example with detailed comments in examples/01d_quick_example.rs)
//
// This example demonstrates clap's full 'custom derive' style of creating arguments which is the
// simplest method of use, but sacrifices some flexibility.
use clap::{AppSettings, Parser};
/// This doc string acts as a help message when the user runs '--help'
/// as do all doc strings on fields
#[derive(Parser)]
#[clap(version = "1.0", author = "Kevin K. <kbknapp#gmail.com>")]
struct Opts {
/// Sets a custom config file. Could have been an Option<T> with no default too
#[clap(short, long, default_value = "default.conf")]
config: String,
/// Some input. Because this isn't an Option<T> it's required to be used
input: String,
/// A level of verbosity, and can be used multiple times
#[clap(short, long, parse(from_occurrences))]
verbose: i32,
#[clap(subcommand)]
subcmd: SubCommand,
}
...
Unfortunately it fails to compile:
$ cargo build
Compiling ex v1.0.0-SNAPSHOT (/home/hwalters/git/home/ex)
error: cannot find derive macro `Parser` in this scope
--> src/main.rs:5:10
|
5 | #[derive(Parser)]
| ^^^^^^
|
note: `Parser` is imported here, but it is only a trait, without a derive macro
--> src/main.rs:1:25
|
1 | use clap::{AppSettings, Parser};
| ^^^^^^
error: cannot find attribute `clap` in this scope
--> src/main.rs:6:3
|
6 | #[clap(version = "1.0", author = "Kevin K. <kbknapp#gmail.com>")]
| ^^^^
|
= note: `clap` is in scope, but it is a crate, not an attribute
...
I tried to find the full example file "examples/01d_quick_example.rs" in the tar file for this GitHub tag, but it does not seem exist there.
I appreciate this is a beta version, but is this functionality expected to work, or am I doing something wrong?
Thanks!
In clap, use features = [ "derive" ] in Cargo.toml to enable the ability to derive :)
update
#stein below makes a good point of expanding the answer:
To "use" means: in the [dependencies] section, specify clap with a
line similar to: clap = { version = "3.1.0", features = ["derive"]} – 
Stein Feb 19 at 13:00
Please +1 their comment :-).
This means, in your Cargo.toml
[dependencies]
# ...
clap = { version = "3", features = ["derive"]}

How to build a Rust binary executable

I am trying to build a single Rust binary executable. In the src directory I have four files:
main.rs:
use fasta_multiple_cmp::get_filenames;
fn main() {
get_filenames();
}
mod.rs:
pub mod fasta_multiple_cmp;
pub mod build_sequences_matrix;
fasta_multiple_cmp.rs:
pub mod fasta_multiple_cmp {
...
pub fn get_filenames() {
let args: Vec<String> = env::args().collect();
...
build_sequences_matrix.rs:
pub mod build_sequences_matrix {
use simple_matrix::Matrix;
...
Cargo told me:
src/main.rs:3:5
|
3 | use fasta_multiple_cmp::get_filenames;
| ^^^^^^^^^^^^^^^^^^ use of undeclared crate or module `fasta_multiple_cmp
I believed I understood some little things, but ther I'm lost. What is going on?
Thaks for any hint!
Your original code wasn't working because Rust's use is looking for a crate to import from, not just a file in the same directory.
If you want to separate logic into other files, you will need to break apart your project into both a binary and into a library (aka - a crate that your binary can use for imports).
This can be done in your Cargo.toml as:
[package]
edition = "2018"
name = "my_project"
version = "1.2.3"
... your other settings ...
[[bin]]
edition = "2018"
name = "whatever_name_for_binary"
path = "src/main.rs"
This means that your binary will be compiled into a file called "whatever_name_for_binary" in your target folder. It also means your non-binary files act as a library, and can be imported by your binary by using use my_project::some_module;
Because your project will now contain both a library and binary, you will need to specify when you want to run/compile the binary.
You do this by running: cargo run --bin whatever_name_for_binary
For more information, see the Rust Book's Chapter on Modules.

Cargo rand compilation errors

This is a really basic question so please bear with me.
I have a project that needs to use an old build of Rust (cargo 0.19.0-nightly c995e9e 2017-03-17). It uses rand so I added rand="0.4.3" as a dependency. When the registry updates, rand 0.5.5 (latest) is automatically downloaded and it also runs into "break loop" error which was stabilized a while ago. I am not sure how to suppress this error or make it not install the latest version.
Cargo.toml:
[package]
name = "hello-world"
version = "0.0.0"
authors = [""]
[dependencies]
time = ">=0.1.0"
rand = "=0.4.3"
rustc-serialize ="0.3"
histogram = "*"
I get this error. The repository is not cloned locally so I cannot apply the patch rust-lang/rust#37339.
Compiling rand v0.5.5 error: break with a value is experimental (see
issue #37339)
--> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.5.5/src/distributions/uniform.rs:674:25
| 674 | break d; | ^^^^^^^ |
= help: add #![feature(loop_break_value)] to the crate attributes to enable
error: pub(restricted) syntax is experimental (see issue #32409)
--> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.5.5/src/distributions/float.rs:71:5
| 71 | pub(crate) trait IntoFloat { | ^^^^^ |
= help: add #![feature(pub_restricted)] to the crate attributes to enable
error: pub(restricted) syntax is experimental (see issue #32409)
--> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.5.5/src/rngs/mod.rs:174:27
| 174 | #[cfg(feature="std")] pub(crate) mod thread; | ^^^^^ |
= help: add #![feature(pub_restricted)] to the crate attributes to enable
error: aborting due to 3 previous errors
error: Could not compile rand.
What am i doing wrong? What is the right way to go about it?

Resources