Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.4k views
in Technique[技术] by (71.8m points)

rust - How do I use a macro across module files?

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...