I have been learning wgpu over the past few days and I have one point of confusion.
When I browse athe wgpu examples (https://github.com/gfx-rs/wgpu/tree/master/wgpu/examples) they use this syntax for their shaders:
struct VertexOutput {
#location(0) color: vec4<f32>,
#builtin(position) position: vec4<f32>,
}
but I have to write my shaders like this:
struct VertexOutput {
[[location(0)]] color: vec4<f32>;
[[builtin(position)]] position: vec4<f32>;
};
I much prefer the # syntax to the [[]] syntax. My guess is that it is a feature I need to enable in my Cargo.toml but I have not been able to find out what feature this is. So if someone could tell me how to use the # syntax in my wgsl shaders it would be much appreciated.
I guess you currently use wgpu version 0.12.0 from crates.io?
The # syntax is the new updated syntax from the webgpu spec. The latest released version of wgpu however still uses the old syntax.
If you want to use the new syntax now, you can use the master branch from git like so (in your Cargo.toml):
wgpu = { git = "https://github.com/gfx-rs/wgpu" }
Update
wgpu version 0.13 was released in the meantime, so you can now use
wgpu = "0.13"
to get the new wgsl syntax.
Related
I am very new to rust and wanted to work through some examples to get a better understanding.
I learned that cargo executes examples similar to a normal app and if there are additional dependencies which are not covered by the crate the examples are written for, there is a region in the TOML where these dependencies may be defined.
druid gives a lot of nice examples which do run when I start them with e.g.
cargo run --example text
Then I get a little window which shows a text and the display can be modified with some radio buttons.
But when I start a new project on my own with cargo, put druid into dependencies and copy the source from the example into main.rs this does not compile.
So what do have to change to get the example running as main?
Michael
The code can be found under
text.rs
My toml looks like this:
[package] name = "test-text"
version = "0.1.0"
authors = ["michael.heisler"]
edition = "2018"
[dependencies]
druid="0.6"
and the first error from a full bunch is:
error[E0432]: unresolved import druid::piet::TextStorage-->src\main.rs:17:42
17 use druid::piet::{PietTextLayoutBuilder, TextStorage as PietTextStorage};
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no TextStorage in piet
Still I would like to know how I find the differences, but with
druid = { git = "https://github.com/linebender/druid.git" }
in the dependencies instead of
druid = "0.6"
the application is working
I'm using the GTK provided Rust example from https://www.gtk.org, and am wondering how to nail down GTK as a dependency (or other type of prerequisite) so that the Rust program given there will build with cargo.
Here's the code, copied from there without modification:
use gio::prelude::*;
use glib::clone;
use gtk::prelude::*;
// When the application is launched…
fn on_activate(application: >k::Application) {
// … create a new window …
let window = gtk::ApplicationWindow::new(application);
// … with a button in it …
let button = gtk::Button::new_with_label("Hello World!");
// … which closes the window when clicked
button.connect_clicked(clone!(#weak window => move |_| window.close()));
window.add(&button);
window.show_all();
}
fn main() {
// Create a new application
let app = gtk::Application::new(Some("com.github.gtk-rs.examples.basic"), Default::default())
.expect("Initialization failed...");
app.connect_activate(|app| on_activate(app));
// Run the application
app.run(&std::env::args().collect::<Vec<_>>());
}
As is, without any Cargo.toml definitions for gtk, gtk symbols will not resolve when compiling the program.
How would you go about it most idiomatically?
I do have GTK installed on my system of course.
Thanks!
Rust can call code using the C ABI, but as #Herohtar explains, it is not automatic. You need to give the compiler the information about the extern "C" functions to be able to call them.
For commonplace libraries, there may be existing bindings out there. These are Rust library crates that contain all the glue already written for you. They work like any other Rust dependency that you put in your Cargo.toml file.
So indeed I ended up following the suggested approach of using the gtk-rs rust integration project rather than pursue any gtk wrapper of my own. My initial source of confusion has been that the gtk website just gave the gtk-rs sample code without any reference or mention of the gtk-rs project being assumed.
The public crate which that code assumes, even though not explicitly stated in the original code sample page, is called gtk; I guess that's the default naming convention: that the namespace and crate name are typically the same.
Including that crate in the build indeed satisfies the gtk namespace appearing in the code. And the same trivial naming convention applies for the gio and glib namespace requirements appearing in the sample code. They all seem to come from the gtk-rs project, though unlike other programming languages, this is not explicitly evident in the crate specification as only the name of the create, not the project containing it, are specified in cargo.
As to versions, I have chosen the most recent version of the gtk crate (as per suggestion from my VSCode rust plugin) and the newest crate feature providing support for GTK's latest supported API.
And I have also arbitrarily plucked versions of the gio and glib crates off another gtk-rs project hoping for seamless interoperability between the last two and the gtk crate itself, as they seem to need to be separately specified and not brought in by the gtk crate itself.
So with the following dependency definitions in my Cargo.toml, the sample code works:
[dependencies]
gtk = { version = "0.9.2", features = ["v3_22"] }
glib = "0.10"
gio = { version = "0.9", features = ["v2_56"] }
I'm new to rust but I might at present time think some of this is more complicated than it could be or would be in the case of other rust projects, or, that using the sample code assumes familiarity with the compatibility scheme of gtk-rs crates or that of the underlying native compatibility of gtk with glib and gio versions!
The latter aspect might be simple enough but not explicitly discussed where gtk-rs documentation discusses versioning.
An odd sticking point for me was that the following method had to be replaced by me with the one following it, perhaps this code sample is just slightly outdated compared to the latest version of the crate (?!).
provided code sample:
gtk::Button::new_with_label
actual method that is defined:
gtk::Button::with_label
This section of the Rust book seems to imply that it is possible to keep Rust documentation in separate .md files, but it does not say how these .md files can then be included back. How does this work?
The syntax for putting Rust module documentation in separate Markdown files is:
#![doc = include_str!("path/to/some-documentation.md")]
/* content of the module */
This is supported since stable Rust 1.54.0.
On old nightly compilers from 1.50.0-nightly through 1.53.0-nightly, an unstable feature is required in order for the above to be available.
#![feature(extended_key_value_attributes)]
#![doc = include_str!("path/to/some-documentation.md")]
On nightly compilers 1.24.0-nightly through 1.53.0-nightly, the following alternative syntax is available, but has since been removed.
#![feature(external_doc)]
#![doc(include = "path/to/some-documentation.md")]
It doesn't. That section on describing the functionality of rustdoc is saying that it can process individual .md files. The third paragraph touches on this:
Documentation can be generated in two ways: from source code, and from standalone Markdown files.
Insofar as I am aware, there is no extant way to put code documentation in external files. It would be theoretically possible to do so using a procedural derive macro, but I'm not aware of any crate that actually does this.
In stable Rust, you can mimic the unstable external-doc feature through clever macros.
An easy way to do this is to use the doc-comment crate:
#[macro_use]
extern crate doc_comment;
// If you want to test examples in your README file.
doctest!("../README.md");
// If you want to document an item:
doc_comment!(include_str!("another_file.md"), pub struct Foo {});
You can see a complicated version of this in my crate SNAFU, where I use it for the user's guide.
The "by-hand" version involves passing the thing to be documented along with the included markdown:
macro_rules! inner {
($text:expr, $($rest: tt)*) => {
#[doc = $text]
$($rest)*
};
}
inner! {
include_str!("/etc/hosts"),
mod dummy {}
}
See also:
Is it possible to emit Rust attributes from within macros?
How to embed a Rust macro variable into documentation?
Generating documentation in macros
I have a Rust library crate which I only use on Linux, but I don't know of any reason it shouldn't work on Windows; however one of the examples is Unix-specific, so it the crate fails the build on AppVeyor.
The reason is that there's a Unix-only dependency (Termion) used by one of the examples, so when I used an AppVeyor template, it fails to build that dev-dependency.
So I made the dependency conditional:
[target.'cfg(unix)'.dev-dependencies]
termion = "1.0"
So far so good, but of course now that example fails on extern crate termion.
What I need is to just not build that example on non-Unix-like targets. I was hoping something like:
[[target.'cfg(unix)'.example]]
name = "foo"
would work, but I get:
warning: unused manifest key: target.cfg(unix).example
error: no example target named `foo`
Another promising way forward was Cargo's required-features, but as of writing it's apparently not in stable Cargo, which means that doesn't help me checking that it works on stable Rust on Windows.
The last option I can think of is to #[cfg(unix)] away most of the example's source, turning it into a stub on Windows, but I'd really like a cleaner way of doing it.
Is there some existing way of skipping an example on some unsupported targets that works with current stable Rust/Cargo?
I use a method that appeared in Rust 1.10 for my tests but I want my crate to also work with version 1.7.
Is there a way (something like attribute #[cfg(min_version="1.10")]) to specify code that should only run in Rust 1.10 or newer?
I could use a build script, but I don't want a more complicated build just because I wanted to test my crate on an older Rust version.
While there is no way except build scripts (and in the future procedural macros) to check compiler versions, you can use feature flags to manually enable and disable code.
Usually you want to use some new compiler feature to provide new functionality which you could not do with the old compiler. In that case you use the cfg attribute with feature flags which you define to enable code. E.g.
#[cfg(feature = "foo")]
pub fn foo() {
cool_new_compiler_function();
}
And in your Cargo.toml:
[features]
foo = []
Hiding code behind feature flags like this also works in test code. In your specific case you could alternately introduce a legacy feature and disable tests using modern code like this:
#[test]
#[cfg(not(feature = "legacy"))]
fn test_foo() {
Foo::foo();
}
And then to run tests in legacy mode you run:
cargo test --features "legacy"
Note that doing it the latter way means that your tests will not compile by default on older compilers. For normal (non-test) code, adding such a legacy flag would be a very bad, breaking change.