How do I use a macro across module files?

前端 未结 4 1928
隐瞒了意图╮
隐瞒了意图╮ 2020-11-27 13:56

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 m

相关标签:
4条回答
  • 2020-11-27 14:17

    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.

    0 讨论(0)
  • 2020-11-27 14:20

    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.

    0 讨论(0)
  • 2020-11-27 14:24

    Macros within the same crate

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

    Macros can only be used after they have been defined. This means that this does not work:

    bar!();  // ERROR: cannot find macro `bar!` in this scope
    
    #[macro_use]
    mod foo {
        macro_rules! bar {
            () => ()
        }
    }
    

    Macros across crates

    To use your macro_rules! macro from other crates, the macro itself needs the attribute #[macro_export]. The importing crate can then import the macro via use crate_name::macro_name;.

    Crate util

    #[macro_export]
    macro_rules! foo {
        () => ()
    }
    

    Crate user

    use util::foo;
    
    foo!();
    

    Note that 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;.

    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. Alternatively, #[macro_use(cat, dog)] could be used to only import the macros cat and dog. This syntax should not be necessary anymore.

    More information is available in The Rust Programming Language chapter on macros.

    0 讨论(0)
  • 2020-11-27 14:25

    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)
    
    0 讨论(0)
提交回复
热议问题