21

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!'
mfussenegger
  • 3,931
  • 23
  • 18
Adityo Pratomo
  • 253
  • 1
  • 2
  • 7
  • I'm having trouble with the same problem, also with glium, but trying to apply the solution below doesn't work. I keep getting the macro undefined error. My directory structure is [main.rs, lib.rs, tutorial: [ mod.rs, draw_triangle.rs ]] where the implement_vertex! is being used in draw_triangle.rs – jz87 Aug 26 '16 at 22:25

3 Answers3

23

#[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).

DK.
  • 55,277
  • 5
  • 189
  • 162
  • but then I got errors like this `failed to resolve. Use of undeclared type or module `glium::glutin::WindowBuilder` is that namespace related? I've also added `use glium::*;` but still doesn't work – Adityo Pratomo Jul 27 '16 at 12:49
  • Sounds like a brittle macro. Try adding `use glium;` to the top of `part01drawtriangle.rs`. – DK. Jul 27 '16 at 12:50
  • 2
    You might want to open an issue with the crate; the solution is to use `$crate::` instead of `glium::` in the macro definition. – DK. Jul 27 '16 at 12:51
18

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.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Nickolay
  • 31,095
  • 13
  • 107
  • 185
0

If using a macro exported by a library and imported by a binary within the same project then use the following pattern.

From lib.rs that is part of the [lib] definition within Cargo.toml

// src/lib/lib.rs

#[macro_export]
macro_rules! my_macro {
    // ...
}
pub use my_macro;

From the client file bin.rs that is part of the [[bin]] definition within Cargo.toml

// src/bin/bin.rs

use crate::my_macro;

Each imported macro needs it's own single use statement. Multiple items cannot be imported along with the macro (those need a separate use statement).

JamesThomasMoon
  • 6,169
  • 7
  • 37
  • 63