Есть ли в Rust макрос отладки?

В C++ я использую что-то вроде этого макроса DEBUG:

#ifdef DEBUG
#define DEBUG_STDERR(x) (std::cerr << (x))
#define DEBUG_STDOUT(x) (std::cout << (x))
#else 
#define DEBUG_STDERR(x)
#define DEBUG_STDOUT(x)
#endif

Есть ли в Rust что-то похожее?

2 ответа

Решение

Хотя имеет смысл использовать что-то вроде log Ящик, как указано в ответе ДК, вот как сделать прямой эквивалент того, что вы просили:

// The debug version
#[cfg(feature = "my_debug")]
macro_rules! debug_print {
    ($( $args:expr ),*) => { println!( $( $args ),* ); }
}

// Non-debug version
#[cfg(not(feature = "my_debug"))]
macro_rules! debug_print {
    ($( $args:expr ),*) => {}
}

fn main() {
    debug_print!("Debug only {}", 123);
}

И в твоем Cargo.toml, добавить [features] раздел:

[features]
my_debug = []

Выход появляется с cargo run --features my_debugи не с равниной cargo run,

Руст 1.32.0

Руст 1.32.0 стабилизировался dbg!() макрос, который выводит:

  • Имя файла, для которого был вызван макрос.
  • Номер строки, на которой был вызван макрос.
  • Красивая печать аргумента (который должен реализовывать Debug черта характера).

Замечания: dbg!() перемещает свой аргумент, поэтому вы можете передавать не-копии типов по ссылке.

Пример: массив точек ( игровая площадка)

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let points = [
        Point { x: 0, y: 0 },
        Point { x: 2, y: 3 },
        Point { x: 5, y: 7 },
    ];

    dbg!(&points);
}

Выход программы

[src/main.rs:14] &points = [
    Point {
        x: 0,
        y: 0
    },
    Point {
        x: 2,
        y: 3
    },
    Point {
        x: 5,
        y: 7
    }
]

Пример: условная компиляция ( площадка)

ОП выразил желание отображать содержимое отладки только при компиляции в режиме отладки.

Ниже приведен способ достижения этого:

#[cfg(debug_assertions)]
macro_rules! debug {
    ($x:expr) => { dbg!($x) }
}

#[cfg(not(debug_assertions))]
macro_rules! debug {
    ($x:expr) => { std::convert::identity($x) }
}

fn main() {
    let x = 4;
    debug!(x);
    if debug!(x == 5) {
        println!("x == 5");
    } else {
        println!("x != 5");
    }
}

Вывод программы (режим отладки)

---------------------Standard Error-----------------------

[src/main.rs:13] x = 4
[src/main.rs:14] x == 5 = false

---------------------Standard Output----------------------

x != 5

Выход программы (режим выпуска)

---------------------Standard Output----------------------

x != 5

До ржавчины 1.32.0

Вы можете использовать ящик для журналов или определить его самостоятельно.

Вы можете определить их самостоятельно, но было бы проще использовать log crate, который определяет несколько макросов для различных целей (см. log документация).

Обратите внимание, что ящик предоставляет только внешний интерфейс для регистрации; вам также нужно будет выбрать бэкэнд. Есть основной пример в log документация, или вы могли бы использовать что-то вроде env_logger или же log4rs,

Макрос на основе ответа Криса Эмерсона и комментария Си Джея Макаллистера

// Disable warnings

#[allow(unused_macros)]

// The debug version

#[cfg(debug_assertions)]
macro_rules! log {
    ($( $args:expr ),*) => { println!( $( $args ),* ); }
}

// Non-debug version

#[cfg(not(debug_assertions))]
macro_rules! log {
    ($( $args:expr ),*) => {()}
}

С помощью

log!("Don't be crazy");
log!("Answer is {}", 42);

Строительство cargo build --release заменит все log!(...) с единичным кортежем ();

Я не нашел способа ничего заменить, но я думаю, что компилятор сделает это.

Другие вопросы по тегам