Memahami Conditional Compilation di Rust
Rust merupakan bahasa cross-platform, tapi kenapa hasil kompilasi binary-nya sangat kecil? Kenapa Rust lebih unggul dari bahasa cross-platform lainnya? Tidak seperti bahasa lainnya, di Rust kita bisa menambahkan logika untuk mengecualikan kode tertentu selama proses kompilasi, jadi ini yang membuat hasil kompilasi Rust menjadi sangat efisien.
Conditional Compilation di pemrograman adalah konsep yang digunakan oleh kompiler untuk menyertakan atau mengecualikan bagian kode tertentu selama proses kompilasi. Di Rust sendiri ada beberapa metode yang bisa kita gunakan, yaitu:
A. Attribute #[cfg(...)]
Attribute #[cfg(...)] yang berarti kode akan dikompilasi jika kondisi di dalam attribute itu terpenuhi. Jadi, jika di luar dari kondisi itu kode akan diskip. Beberapa kondisi yang tersedia di attribute ini yaitu:
Platform & OS
#[cfg(target_os = "macos")]
#[cfg(target_os = "linux")]
#[cfg(target_os = "windows")]
#[cfg(unix)] // semua sistem Unix-like
#[cfg(windows)] // semua sistem Windows Arsitektur CPU
#[cfg(target_arch = "x86_64")]
#[cfg(target_arch = "aarch64")] // ARM 64-bit
#[cfg(target_arch = "wasm32")] // WebAssembly Tipe Kompilasi
#[cfg(debug_assertions)] // aktif saat `cargo build` (debug)
#[cfg(test)] // aktif saat `cargo test` Endianness & Pointer Width
#[cfg(target_endian = "little")]
#[cfg(target_pointer_width = "64")] Operator Logika
// AND - semua kondisi harus terpenuhi
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn linux_x64_only() { }
// OR — salah satu kondisi
#[cfg(any(target_os = "linux", target_os = "macos"))]
fn unix_like() { }
// NOT — kebalikan kondisi
#[cfg(not(windows))]
fn non_windows() { }
// Kombinasi
#[cfg(all(unix, not(target_os = "macos")))]
fn linux_bsd_only() { } Selain itu, kita bisa custom cfg dengan --cfg flag saat proses kompilasi, seperti berikut ini:
#[cfg(feature_x)]
fn experimental() {
println!("Fitur eksperimental aktif!");
} Kemudian saat running, kita bisa seperti ini:
RUSTFLAGS='--cfg feature_x' cargo build B. Macro cfg!(...)
Berbeda dengan attribute sebelumnya, macro ini digunakan sebagai ekspresi boolean di dalam kode. Macro ini tetap mengkompilasi semua ekspresi, tapi memilih satu ketika runtime. Berikut contoh penerapannya:
fn main() {
if cfg!(debug_assertions) {
println!("Mode: DEBUG");
} else {
println!("Mode: RELEASE");
}
} C. Features
Ini merupakan jenis Conditional Compilation yang paling sering digunakan. Berikut cara penerapannya:
Definisikan di cargo.toml
[features]
default = ["logging"] # fitur aktif secara default
logging = []
database = ["dep:sqlx"] # fitur dengan dependensi opsional
advanced = ["logging", "database"] # fitur gabungan Gunakan di kode:
#[cfg(feature = "logging")]
fn setup_logger() {
println!("Logger diinisialisasi");
}
fn main() {
#[cfg(feature = "logging")]
setup_logger();
println!("App berjalan");
} Kompilasi dengan:
cargo build --features "logging,database"
cargo build --features "advanced"
cargo build --all-features # aktifkan semua fitur
cargo build --no-default-features # nonaktifkan default D. Attribut cfg_attr
Dengan metode ini akan menerapkan attribute lain secara kondisional, contohnya:
// Hanya tambahkan derive(Debug) saat testing
#[cfg_attr(test, derive(Debug))]
struct Config {
value: u32,
}
// Hanya aktifkan serde saat fitur "serde" diaktifkan
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
struct Data {
name: String,
} E. Build.rs
File build.rs dijalankan sebelum kompilasi dan bisa mengatur cfg secara dinamis. Berikut contoh di build.rs
fn main() {
// Set cfg berdasarkan kondisi saat build
if std::env::var("CARGO_CFG_TARGET_OS").unwrap() == "linux" {
println!("cargo:rustc-cfg=use_epoll");
}
// Emit cfg berdasarkan versi atau environment lain
println!("cargo:rustc-cfg=my_custom_flag");
} Dan ini di main.rs
#[cfg(use_epoll)]
fn io_backend() {
println!("Menggunakan epoll (Linux)");
} Kesimpulan
Exclude item secara keseluruhan#[cfg(...)]-- Cek kondisi sebagai ekspresi boolcfg!(...)di Cargo.toml - Fitur opsional yang bisa diaktifkan oleh pengguna[features]Terapkan attribute secara kondisional#[cfg_attr(...)] -Set cfg dinamis berdasarkan environment buildbuild.rs-
References
- https://doc.rust-lang.org/reference/conditional-compilation.html
- https://lightwavephotonics.com/lig/rise-of-the-rust-empire-how-rust-crossplatform-development-is-revolutionizing-the-industry