How do I properly register a Rust compiler plugin? - plugins

I've been pulling my hair out over trying to get a Rust compiler plugin to register properly.
I have a separate crate called rust_to_glsl that is in a subdirectory of my main code.
Inside the rust_to_glsl/src/lib.rs file I have the following
#![feature(plugin_registrar)]
#![feature(rustc_private)]
#![crate_type="dylib"]
extern crate rustc;
extern crate syntax;
#[doc(hidden)]
#[plugin_registrar]
pub fn registrar(registry: &mut rustc::plugin::Registry) {
println!("Test");
registry.register_macro("to_glsl", expand);
}
Plus I have defined the actual expand function.
In src/main.rs I'm trying to pull in that plugin/crate.
#![feature(plugin)]
#![plugin(rust_to_glsl)]
And then I'm trying to use that macro here:
fn main() {
let glsl = to_glsl!(
const x: uint = 5;
static texture: &Texture2d = 1;
fn hello() {
min(5, 3 * 1 + 5)
}
);
println!("{}", glsl);
}
If I compile that, I get this error:
Compiling opal v0.1.0 (file:///Users/chris/Code/Rust/gl)
src/main.rs:2:11: 2:23 error: can't find crate for `rust_to_glsl`
src/main.rs:2 #![plugin(rust_to_glsl)]
During the build process I notice that rust_to_glsl isn't being compiled (with cargo build).
If I add in extern crate rust_to_glsl, then it compiles rust_to_glsl.
But then squarks by saying
49:23 error: macro undefined: 'to_glsl!'
src/main.rs:49 let glsl = to_glsl!(
I'm not sure if I need to use the macro or if all macros are global.

Turns out i need to add this to rust_to_glsl/Cargo.toml
[lib]
name = "rust_to_glsl"
crate-type = ["dylib"]
And then include it not as a build-dependency but normal dependency

Related

undefined reference error in VScode Version 1.69.1

Below is simple program where i have configured VSCode on Azure VM with all applicable extensions to run c program
But when i try to compile i am getting below error
Any hints or missing extensions will assist... if i define func() at top prior main() it works but would be interested to know how do i make it work the way i am trying too ..any hints will be appreciated..
Place your entire void meow(void) function definition:
void meow(void) {
printf("meow\n");
}
outside of the main() function definition brackets { } like so:
int main(void) {
...
...
}
void meow(void) {
printf("meow\n");
}

Cannot find macro in this scope [duplicate]

I have two modules in separate files within the same crate, where the crate has macro_rules enabled. I want to use the macros defined in one module in another module.
// macros.rs
#[macro_export] // or not? is ineffectual for this, afaik
macro_rules! my_macro(...)
// something.rs
use macros;
// use macros::my_macro; <-- unresolved import (for obvious reasons)
my_macro!() // <-- how?
I currently hit the compiler error "macro undefined: 'my_macro'"... which makes sense; the macro system runs before the module system. How do I work around that?
Macros within the same crate
New method (since Rust 1.32, 2019-01-17)
foo::bar!(); // works
mod foo {
macro_rules! bar {
() => ()
}
pub(crate) use bar; // <-- the trick
}
foo::bar!(); // works
With the pub use, the macro can be used and imported like any other item. And unlike the older method, this does not rely on source code order, so you can use the macro before (source code order) it has been defined.
Old method
bar!(); // Does not work! Relies on source code order!
#[macro_use]
mod foo {
macro_rules! bar {
() => ()
}
}
bar!(); // works
If you want to use the macro in the same crate, the module your macro is defined in needs the attribute #[macro_use]. Note that macros can only be used after they have been defined!
Macros across crates
Crate util
#[macro_export]
macro_rules! foo {
() => ()
}
Crate user
use util::foo;
foo!();
Note that with this method, macros always live at the top-level of a crate! So even if foo would be inside a mod bar {}, the user crate would still have to write use util::foo; and not use util::bar::foo;. By using pub use, you can export a macro from a module of your crate (in addition to it being exported at the root).
Before Rust 2018, you had to import macro from other crates by adding the attribute #[macro_use] to the extern crate util; statement. That would import all macros from util. This syntax should not be necessary anymore.
Alternative approach as of 1.32.0 (2018 edition)
Note that while the instructions from #lukas-kalbertodt are still up to date and work well, the idea of having to remember special namespacing rules for macros can be annoying for some people.
EDIT: it turns out their answer has been updated to include my suggestion, with no credit mention whatsoever ๐Ÿ˜•
On the 2018 edition and onwards, since the version 1.32.0 of Rust, there is another approach which works as well, and which has the benefit, imho, of making it easier to teach (e.g., it renders #[macro_use] obsolete). The key idea is the following:
A re-exported macro behaves as any other item (function, type, constant, etc.): it is namespaced within the module where the re-export occurs.
It can then be referred to with a fully qualified path.
It can also be locally used / brought into scope so as to refer to it in an unqualified fashion.
Example
macro_rules! macro_name { ... }
pub(crate) use macro_name; // Now classic paths Just Workโ„ข
And that's it. Quite simple, huh?
Feel free to keep reading, but only if you are not scared of information overload ;) I'll try to detail why, how and when exactly does this work.
More detailed explanation
In order to re-export (pub(...) use ...) a macro, we need to refer to it! That's where the rules from the original answer are useful: a macro can always be named within the very module where the macro definition occurs, but only after that definition.
macro_rules! my_macro { ... }
my_macro!(...); // OK
// Not OK
my_macro!(...); /* Error, no `my_macro` in scope! */
macro_rules! my_macro { ... }
Based on that, we can re-export a macro after the definition; the re-exported name, then, in and of itself, is location agnostic, as all the other global items in Rust ๐Ÿ™‚
In the same fashion that we can do:
struct Foo {}
fn main() {
let _: Foo;
}
We can also do:
fn main() {
let _: A;
}
struct Foo {}
use Foo as A;
The same applies to other items, such as functions, but also to macros!
fn main() {
a!();
}
macro_rules! foo { ... } // foo is only nameable *from now on*
use foo as a; // but `a` is now visible all around the module scope!
And it turns out that we can write use foo as foo;, or the common use foo; shorthand, and it still works.
The only question remaining is: pub(crate) or pub?
For #[macro_export]-ed macros, you can use whatever privacy you want; usually pub.
For the other macro_rules! macros, you cannot go above pub(crate).
Detailed examples
For a non-#[macro_export]ed macro
mod foo {
use super::example::my_macro;
my_macro!(...); // OK
}
mod example {
macro_rules! my_macro { ... }
pub(crate) use my_macro;
}
example::my_macro!(...); // OK
For a #[macro_export]-ed macro
Applying #[macro_export] on a macro definition makes it visible after the very module where it is defined (so as to be consistent with the behavior of non-#[macro_export]ed macros), but it also puts the macro at the root of the crate (where the macro is defined), in an absolute path fashion.
This means that a pub use macro_name; right after the macro definition, or a pub use crate::macro_name; in any module of that crate will work.
Note: in order for the re-export not to collide with the "exported at the root of the crate" mechanic, it cannot be done at the root of the crate itself.
pub mod example {
#[macro_export] // macro nameable at `crate::my_macro`
macro_rules! my_macro { ... }
pub use my_macro; // macro nameable at `crate::example::my_macro`
}
pub mod foo {
pub use crate::my_macro; // macro nameable at `crate::foo::my_macro`
}
When using the pub / pub(crate) use macro_name;, be aware that given how namespaces work in Rust, you may also be re-exporting constants / functions or types / modules. This also causes problems with globally available macros such as #[test], #[allow(...)], #[warn(...)], etc.
In order to solve these issues, remember you can rename an item when re-exporting it:
macro_rules! __test__ { ... }
pub(crate) use __test__ as test; // OK
macro_rules! __warn__ { ... }
pub(crate) use __warn__ as warn; // OK
Also, some false positive lints may fire:
from the trigger-happy clippy tool, when this trick is done in any fashion;
from rustc itself, when this is done on a macro_rules! definition that happens inside a function's body: https://github.com/rust-lang/rust/issues/78894
This answer is outdated as of Rust 1.1.0-stable.
You need to add #![macro_escape] at the top of macros.rs and include it using mod macros; as mentioned in the Macros Guide.
$ cat macros.rs
#![macro_escape]
#[macro_export]
macro_rules! my_macro {
() => { println!("hi"); }
}
$ cat something.rs
#![feature(macro_rules)]
mod macros;
fn main() {
my_macro!();
}
$ rustc something.rs
$ ./something
hi
For future reference,
$ rustc -v
rustc 0.13.0-dev (2790505c1 2014-11-03 14:17:26 +0000)
Adding #![macro_use] to the top of your file containing macros will cause all macros to be pulled into main.rs.
For example, let's assume this file is called node.rs:
#![macro_use]
macro_rules! test {
() => { println!("Nuts"); }
}
macro_rules! best {
() => { println!("Run"); }
}
pub fn fun_times() {
println!("Is it really?");
}
Your main.rs would look sometime like the following:
mod node; //We're using node.rs
mod toad; //Also using toad.rs
fn main() {
test!();
best!();
toad::a_thing();
}
Finally let's say you have a file called toad.rs that also requires these macros:
use node; //Notice this is 'use' not 'mod'
pub fn a_thing() {
test!();
node::fun_times();
}
Notice that once files are pulled into main.rs with mod, the rest of your files have access to them through the use keyword.
I have came across the same problem in Rust 1.44.1, and this solution works for later versions (known working for Rust 1.7).
Say you have a new project as:
src/
main.rs
memory.rs
chunk.rs
In main.rs, you need to annotate that you are importing macros from the source, otherwise, it will not do for you.
#[macro_use]
mod memory;
mod chunk;
fn main() {
println!("Hello, world!");
}
So in memory.rs you can define the macros, and you don't need annotations:
macro_rules! grow_capacity {
( $x:expr ) => {
{
if $x < 8 { 8 } else { $x * 2 }
}
};
}
Finally you can use it in chunk.rs, and you don't need to include the macro here, because it's done in main.rs:
grow_capacity!(8);
The upvoted answer caused confusion for me, with this doc by example, it would be helpful too.
Note: This solution does work, but do note as #ineiti highlighted in the comments, the order u declare the mods in the main.rs/lib.rs matters, all mods declared after the macros mod declaration try to invoke the macro will fail.

Using another macro in a macro_rules without requiring `extern crate` in rust

Is there a way to "re-export" #[macro_use] extern crate similar to pub use so that users of a macro using macros do not have to manually add these dependent extern crates?
The rest of the question is an example to illustrate.
In src/lib.rs, note that the id macro is using the lazy_static macro:
#[macro_export]
macro_rules! id {
() => {
lazy_static! {
static ref NUMBER : std::sync::atomic::AtomicUsize =
std::sync::atomic::AtomicUsize::new(0);
}
return NUMBER.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
}
}
In examples/example.rs, we need an extern crate line for each macro, even though we're just using the id macro directly:
#[macro_use]
extern crate id_macro;
#[macro_use]
extern crate lazy_static;
fn new_id() -> usize {
id!();
}
fn main() {
println!("id {}", new_id()); // prints "id 0"
println!("id {}", new_id()); // prints "id 1"
}
In the example, it would be great if the user of id_macro could use id! without knowing about lazy_static. Is there a way to "re-export" extern crate similar to pub use to make the following lines go away from the example?
#[macro_use]
extern crate lazy_static;
There is an unstable macro_reexport attribute.
However, Rust is working on making macros (2.0) behave like normal items that support pub use, so this attribute won't be stable and will become obsolete.

How to import macros in Rust?

I'm struggling with how to import macros from an external crate. In my main.rs I'm importing the Glium crate:
#![macro_use]
extern crate glium;
pub use glium::*;
// where my actual main function will be done from
mod part01drawtriangle;
fn main() {
part01drawtriangle::main();
}
In my other file, where my main function is coming from, I call one of the macros from that crate:
pub fn main() {
implement_vertex!(Vertex, position);
}
When building, I get the error message:
error: macro undefined: 'implement_vertex!'
#[macro_use], not #![macro_use].
#[..] applies an attribute to the thing after it (in this case, the extern crate). #![..] applies an attribute to the containing thing (in this case, the root module).
According to the Rust Edition Guide:
In Rust 2018, you can import specific macros from external crates via use statements, rather than the old #[macro_use] attribute.
// in a `bar` crate's lib.rs:
#[macro_export]
macro_rules! baz {
() => ()
}
// in your crate:
use bar::baz;
// Rather than:
//
// #[macro_use]
// extern crate bar;
This only works for macros defined in external crates. For macros defined locally, #[macro_use] mod foo; is still required, as it was in Rust 2015.

Using a Function pointer inside a class crashes the compiler (but works inside a function)

Reference class
class commandsListClass
{
public:
std::string name;
std::string description;
std::vector<std::string> commands;
columnHeaders headersRequired;
void (*function)(System::Object ^ );
std::string recoveryFileHeader;
void reset()
{
name = "";
description = "";
commands.clear();
headersRequired.reset();
recoveryFileHeader = "";
function = dummyFunc; // dummyFunc uses the same members as the intended - this is to ensure it is defined. DummyFunc is empty, returns void etc
}
commandsListClass()
{
reset();
}
};
Currently, if I run the below code, the compiler crashes
// This crashes the compiler
System::Threading::ThreadPool::QueueUserWorkItem(gcnew System::Threading::WaitCallback(global::commandsList[index].function ), ti);
1>------ Build started: Project: MyProject, Configuration: Release x64 ------
1> project.cpp
1>c:\users\guy\documents\visual studio 2012\projects\MyProject\MyProject\Form1.h(807): fatal error C1001: An internal error has occurred in the compiler.
1> (compiler file 'msc1.cpp', line 1443)
1> To work around this problem, try simplifying or changing the program near the locations listed above.
1> Please choose the Technical Support command on the Visual C++
1> Help menu, or open the Technical Support help file for more information
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
If I declare a member inside the same function as I am making the call, and set it to the global::commandsList[index].function, it compiles and runs correctly
// This runs correctly
void (*func)(System::Object ^);
func = global::commandsList[index].function;
System::Threading::ThreadPool::QueueUserWorkItem(gcnew System::Threading::WaitCallback(func ), ti);
global::commandsList is a vector of type commandsListClass
Any ideas? Browsing Google and SO suggest changing the compiler to not optimize, which I've tried with no success. The code is written in such a way that:
That point in the code cannot be reached if index does not point to a valid member of the global::commandsList vector
The function variable is guaranteed to be set, either to the dummyFunc on creation, or the correct (requested) function as set elsewhere in the code.
Any help would be greatly appreciated.
Edit 1: This is using Visual Studio 2012, Windows 7 x64
Here's a simplified repo:
public delegate void MyDel(Object^);
void g(Object^) {}
struct A {
static void(*fs)(Object^);
void(*f)(Object^);
gcroot<MyDel^> del;
};
void(*fg)(Object^);
void h()
{
void (*f)(Object^);
A a;
gcnew MyDel(f);
gcnew MyDel(fg);
gcnew MyDel(a.fs);
a.del = gcnew MyDel(g);
//gcnew MyDel(a.f); // this line fails
// work around
f = a.f;
gcnew MyDel(f);
}
Only the non-static member variable fails. Seems like a compiler bug. Work around it by using a local intermediate.
Or better is Lucas's suggestion to use gcroot.