Программирование ARM Условная компиляция на языке Rust Fri, August 29 2025  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


Условная компиляция на языке Rust Печать
Добавил(а) microsin   

Рано или поздно по мере освоения возможностей языка Rust встает вопрос: есть ли на нем условная компиляция, наподобие директив препроцессора #if, #ifdef, #elif, #else, #endif языка C? Это очень распространенная проблема для разработчиков, переходящих из C/C++ на Rust.

Короткий ответ: нет. На языке Rust нет препроцессора с директивами в стиле #ifdef или #if, работающих на том же уровне, что и на C/C++.

Однако Rust обладает мощной и более интегрированной системой для условной компиляции, которая служит той же цели. Это реализовано через атрибуты и cfg-систему (от слова configuration).

[Rust-эквивалент препроцессора: #[cfg(...)]

Вместо отдельного шага препроцессора, Rust обрабатывает условную компиляцию на уровне языка с помощью атрибутов. Самый важный из них это #[cfg(...)].

Вот как концепция C/C++ выглядит по сравнению с Rust:

1. #ifdef FEATURE / #if defined(FEATURE) на языке C:

#ifdef UNIX
printf("Работа в среде Unix\n");
#endif

Аналог на Rust:

#[cfg(unix)]
{
println!("Работа в среде Unix"); }

Или для функции:

#[cfg(unix)]
fn unix_specific_function()
{
// ... }

2. #ifndef FEATURE (if NOT defined) на языке C:

#ifndef WINDOWS
printf("Работа не в среде Windows\n");
#endif

Аналог на Rust:

#[cfg(not(windows))]
{
println!("Работа не в среде Windows"); }

3. #else на языке C:

#ifdef UNIX
printf("Unix\n");
#else
printf("Not Unix\n");
#endif

Аналог на Rust:

#[cfg(unix)]
{
println!("Unix"); }
#[cfg(not(unix))] {
println!("Not Unix"); }

4. #elif (else if) на языке C:

#if defined(UNIX)
// ...
#elif defined(WINDOWS)
// ...
#else
// ...
#endif

Аналог на Rust:

#[cfg(unix)] {
println!("Unix"); }
#[cfg(windows)] {
println!("Windows"); }
#[cfg(not(any(unix, windows)))] {
println!("Какая-то другая OS"); }

На Rust есть несколько общих предопределенных условий для cfg:

• Операционные системы: windows, unix, linux, macos
• Архитектуры: target_arch = "x86_64", target_arch = "aarch64"
• Семейство: target_family = "unix", target_family = "windows"
• Разрядность указателя (Pointer Width): target_pointer_width = "64"

Пользовательские фичи: вы их можете определить самостоятельно (см. далее).

[Определение ваших собственных фич (наподобие -D компилятора GCC)]

На языке C вы можете компилировать код с -DDEBUG_MODE. На Rust вы определяете пользовательские фичи в своем файле Cargo.toml:

[features]
default = [] # фичи, разрешенные по умолчанию
advanced_mode = [] # ваша собственная фича
special_algorithm = [] # другая пользовательская фича

Затем, в вашем коде Rust:

// Эта функция компилируется только если разрешена фича "advanced_mode":
#[cfg(feature = "advanced_mode")]
fn do_advanced_thing() {
// Здесь находится комплексная логика }

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

#[cfg(all(unix, feature = "special_algorithm"))]
fn unix_specific_algorithm() {
// ... }

Чтобы запустить сборку с разрешенной фичей, используйте Cargo с опцией --features, например:

$ cargo build --features "advanced_mode"

.. или для релиза:

$ cargo build --release --features "advanced_mode"

[Макрос cfg! для условной проверки runtime]

Атрибут #[cfg] удаляет код во время компиляции. Если вам нужно проверять наличие фичи runtime (код скомпилирован, но есть ветвления кода), то используйте макрос cfg!. Он возвратит bool.

if cfg!(target_os = "macos") {
println!("Мы работаем на macOS!"); } else {
println!("Мы работаем не на macOS."); }
// Обе ветки if компилируются в бинарный код,
// и во время выполнения (runtime) выполнится
// только одна из них.

[Общие выводы: ключевые отличия от C]

Концепция C/C++ Rust
Синтаксис Директивы препроцессора (#if, #ifdef) Атрибуты (#[cfg(...)])
Интеграция Отдельная фаза замены текста исходного кода Интегрировано в сам язык
Область действия На базе файла, в текстовом режиме Семантическое применение к элементам кода (функции, структуры, импорт)
Пользовательские флаги #define, флаг компилятора -D [features] в файле Cargo.toml
Проверка runtime Невозможна С помощью макроса cfg!(...)

Система условной компиляции Rust считается в основном более безопасной и надежной, поскольку она понимает структуру кода, защищая от общих ошибок препроцессора наподобие несоответствующих директив #endif.

 

Добавить комментарий


Защитный код
Обновить

Top of Page