В Rust есть специальный атрибут, #[cfg]
, который позволяет компилировать код в
зависимости от флагов, переданных компилятору. Он имеет две формы:
#[cfg(foo)] #[cfg(bar = "baz")]
Над атрибутами конфигурации определены логические операции:
fn main() { #[cfg(any(unix, windows))] fn foo() {} #[cfg(all(unix, target_pointer_width = "32"))] fn bar() {} #[cfg(not(foo))] fn not_foo() {} }#[cfg(any(unix, windows))] #[cfg(all(unix, target_pointer_width = "32"))] #[cfg(not(foo))]
Они могут быть как угодно вложены:
fn main() { #[cfg(any(not(unix), all(target_os="macos", target_arch = "powerpc")))] fn foo() {} }
#[cfg(any(not(unix), all(target_os="macos", target_arch = "powerpc")))]
Что же касается того, как включить или отключить эти флаги: если вы используете
Cargo, то они устанавливаются в разделе [features]
вашего
Cargo.toml
:
[features]
# по умолчанию, никаких дополнительных возможностей
default = []
# возможность «secure-password» зависит от пакета bcrypt
secure-password = ["bcrypt"]
Если вы определите такие возможности, Cargo передаст флаг в rustc
:
--cfg feature="${feature_name}"
Совокупность этих флагов конфигурации (cfg
) будет определять, какие из них
будут активны, и, следовательно, какой код будет скомпилирован. Давайте
рассмотрим такой код:
#[cfg(feature = "foo")] mod foo { }
Если скомпилировать его с помощью cargo build --features "foo"
, то в rustc
будет передан флаг --cfg feature="foo"
, и результат будет содержать
модуль mod foo
. Если скомпилировать его с помощью обычной команды cargo build
, то никаких дополнительных флагов передано не будет, и поэтому, модуль
mod foo
будет отсутствовать.
Вы также можете установить другой атрибут в зависимости от переменной cfg
с
помощью атрибута cfg_attr
:
#[cfg_attr(a, b)]
Этот код будет равносилен атрибуту #[b]
, если в атрибуте cfg
установлен флаг
a
, или «без атрибута» в противном случае.
Расширение синтаксиса cfg!
позволяет использовать данные
виды флагов и в другом месте в коде:
if cfg!(target_os = "macos") || cfg!(target_os = "ios") { println!("Think Different!"); }
Значение флага будет заменено на true
или false
во время компиляции, в
зависимости от настройки конфигурации.