Как установить зависимости для макроса в Rust?

#rust

#Ржавчина

Вопрос:

Я написал макрос в ящике и импортировал его в основную функцию основного проекта.

Макрос зависит от:

 use chrono::{Utc, Local, DateTime, Date};
 

В настоящее время я включаю зависимость в Cargo.toml основного проекта.

Нужно ли мне делать то же самое для всех основных проектов? Или я могу объявить зависимость в Cargo.toml ящика макросов?

 //lib.rs //Mymacro 
#[macro_export]
macro_rules! time {
    () => {
        use chrono::{Utc, Local, DateTime, Date};
        let local_datetime: DateTime<Local> = Local::now();
        println!("{:?}",local_datetime);
    }
}
 
 //main.rs // main project
extern crate Mymacro;

#[macro_use]
fn main() {
    time!();
}

// Cargo.html 
[dependencies] 
chrono=""
 

Ответ №1:

Нужно ли мне делать то же самое для всех основных проектов? Или я могу объявить зависимость в Cargo.toml ящика макросов?

Вы можете либо (1) вызвать макрокомандой функцию в своей библиотеке, либо (2) выполнить реэкспорт chrono (частично или полностью).


Давайте рассмотрим, что у нас есть рабочее пространство с ящиком lib и bin .

 [workspace]
members = [
    "bin",
    "lib",
]
 

Теперь в вашем Cargo.toml для lib ящика, который вы бы включили в chrono качестве зависимости, как и в противном случае.

 [dependencies]
chrono = "0.4"
 

В то время Cargo.toml как для bin ящика есть только зависимость lib .

 [dependencies]
lib = { path = "../lib" }
 

Теперь давайте рассмотрим, что main.rs в bin ящике выглядит так:

 use lib::time;

fn main() {
    time!();
}
 

Он останется неизменным, независимо от того, какой вариант вы выберете.


Следующие фрагменты представляют lib.rs .


Библиотечная функция

Если вы никогда не возвращаете какие-либо chrono конкретные типы, это может быть проще всего. Поскольку вы полностью избегаете повторного экспорта chrono.

 use chrono::{DateTime, Local};

pub fn _time() {
    let local_datetime: DateTime<Local> = Local::now();
    println!("{:?}", local_datetime);
}

#[macro_export]
macro_rules! time {
    () => {
        $crate::_time();
    };
}
 

Если вы не хотите _time появляться в документации вашей библиотеки, вы можете использовать #[doc(hidden)] атрибут.

Повторный экспорт некоторых элементов

В качестве альтернативы, если вы хотите, чтобы все оставалось внутри макроса, вы можете повторно экспортировать chrono типы, которые он использует, и добавить типы в свой макрос $crate:: .

Недостатком этого является то, что если вашему bin ящику нужен chrono тип, который не реэкспортируется, то это может быть «раздражением» и, следовательно bin , должно зависеть в chrono = "0.4" любом случае.

 pub use chrono::{DateTime, Local};

#[macro_export]
macro_rules! time {
    () => {
        let local_datetime: $crate::DateTime<$crate::Local> = $crate::Local::now();
        println!("{:?}", local_datetime);
    };
}
 

main.rs Если вы вместо этого это сделаете use lib::*; , то вам, конечно, не нужно добавлять $crate:: , но лучше этого не делать use lib::*; .

Повторный экспорт Chrono

Наконец, если вам нужны chrono типы в вашем bin ящике. Затем вы также можете повторно экспортировать весь chrono ящик с pub extern crate chrono; помощью .

Обратите внимание, что на этот раз вам нужно добавить типы в свой макрос с $crate::chrono:: помощью .

 pub extern crate chrono;

#[macro_export]
macro_rules! time {
    () => {
        let local_datetime: $crate::chrono::DateTime<$crate::chrono::Local> =
            $crate::chrono::Local::now();
        println!("{:?}", local_datetime);
    };
}