Как вы используете макрос внутри своего ящика?

Я уверен, что это тривиально, но я не могу заставить его работать.

Я просмотрел http://doc.rust-lang.org/book/advanced-macros.html#scoping-and-macro-import/export, и я ценю, что в общем, способ использования макросов состоит в том, чтобы определить их, используя:

#[macro_export]
macro_rules! background(($token:expr) => (($token >> (32 + 8)) & $crate::graphics::mask::Color));

... и затем импортировать их в другой контекст, который использует их, используя:

#[macro_use]
extern crate terminal;
...

Однако я хочу, чтобы использовать макросы из ящика, где они определены.

Если моя файловая структура:

- lib.rs
- macros.rs
- foo
- foo/mod.rs
- foo/junk.rs

Как использовать макросы в macros.rs из junk.rs?

Я пробовал различные комбинации #[macro_use] mod macros и т.д. без везения. Документация предполагает, что если макрос определен в некоторой области, то он доступен во всех дочерних модулях... означает ли это, что я должен определить свои макросы в lib.rs?

Ответ 1

Вам нужно отметить свой макрос #[macro_export], а затем пометить модуль с помощью #[macro_use]:

#[macro_use]
mod macros {
    #[macro_export]
    macro_rules! my_macro(() => (42));
}

pub mod foo {
    pub mod junk {
        pub fn usage() -> u8 {
            my_macro!()
        }
    }
}

fn main() {
    println!("{:?}", foo::junk::usage());
}

Технически вам нужно использовать #[macro_export], если вы хотите, чтобы макрос был доступен для пользователей вашего ящика.

(ссылка для воспроизведения)

Ответ 2

Принятый ответ правильный, но для любого, кто найдет этот вопрос в будущем, я хотел бы добавить, что порядок загрузки модулей важен.

Например, в этой последовательности:

pub mod terminal;
pub mod terminals;
pub mod graphics;

#[macro_use]
mod macros;

Если терминал использует макрос из макросов, он не будет работать; #[macro_use] должен происходить над любым другим модулем, который использует макрос:

#[macro_use]
mod macros;

pub mod terminal;
pub mod terminals;
pub mod graphics;