Déterminer les builds debug/release en Rust via cfg : guide complet

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Comment distinguer debug de release en Rust ? Décortiquons cfg avec des exemples concrets

\n\n

Avez-vous déjà écrit du code en Rust en pensant : « J'aimerais ajouter une journalisation détaillée en mode debug, et tout enlever en release » ? Ou peut-être vouliez-vous inclure des assertions uniquement pendant le développement, mais les désactiver dans la build finale ? Si oui, vous êtes au bon endroit. Aujourd'hui, nous allons voir comment, grâce à la magie de cfg, gérer le comportement du code en fonction du type de build. Ce n'est pas une simple théorie sèche — nous passerons du simple flag à une solution prête pour la production.

\n\n

Ce sujet n'est pas sorti de nulle part : sur Stack Overflow, la question « How to check release / debug builds using cfg in Rust? » a recueilli des milliers de vues. Cela signifie que beaucoup en ont besoin. Et nous allons l'expliquer en détail.

\n\n

Pourquoi est-ce important ? Deux mondes — deux approches

\n\n

En Rust, il existe deux profils de build principaux : debug (avec le flag --debug ou simplement cargo build) et release (cargo build --release). Ils diffèrent non seulement par les optimisations, mais aussi par le comportement de certaines vérifications intégrées.

\n\n

Par exemple :

\n
    \n
  • debug : lent, mais avec des vérifications de limites de tableaux, des symboles de débogage et des assertions.
  • \n
  • release : rapide, mais sans vérifications superflues — tout pour la performance.
  • \n
\n\n

Et si vous aviez besoin que, dans la version debug, le programme écrive chaque action dans un journal, mais qu'en release, seules les erreurs critiques soient enregistrées ? Ou qu'un point de terminaison de test ne soit accessible qu'en local ? C'est là que cfg intervient.

\n\n

Outils principaux : cfg!() et #[cfg()]

\n\n

En Rust, il existe deux façons de vérifier le type de build :

\n
    \n
  • La macro cfg!() — exécutée lors de la compilation, renvoie un bool. Utilisée à l'intérieur des fonctions.
  • \n
  • L'attribut #[cfg()] — inclut ou exclut complètement un bloc de code de la compilation.
  • \n
\n\n

Les deux utilisent les mêmes clés. La plus populaire pour notre tâche est debug_assertions. Elle est active uniquement dans la build debug. Il existe aussi l'inverse — not(debug_assertions) pour la release.

\n\n

Exemple 1 : Vérification simple à l'intérieur d'une fonction

\n\n

Commençons par la macro cfg!(). Supposons que nous ayons une fonction de calcul complexe. En debug, nous voulons vérifier les données d'entrée :

\n\n
fn calculate_something(x: i32) -> i32 {\n    // Vérification uniquement dans la build debug\n    if cfg!(debug_assertions) {\n        println!("[DEBUG] calculate_something appelée avec x = {}", x);\n        assert!(x > 0, "x doit être positif !");\n    }\n\n    // Logique principale\n    x * 2\n}\n\nfn main() {\n    let result = calculate_something(10);\n    println!("Résultat : {}", result);\n}\n
\n\n

Que va-t-il se passer ?

\n
    \n
  • Avec cargo build (debug) — vous verrez le journal et, si x ≤ 0, le programme plantera avec une assertion.
  • \n
  • Avec cargo build --release — la ligne avec cfg!(debug_assertions) deviendra false, et le compilateur éliminera ce bloc comme du code mort. Aucun surcoût !
  • \n
\n\n

Exemple 2 : Exclusion totale de code avec #[cfg()]

\n\n

Parfois, il ne s'agit pas seulement de sauter l'exécution, mais de retirer complètement une fonction ou un module du binaire. Pour cela, on utilise l'attribut :

\n\n
// Ce module ne sera compilé QUE dans la build debug\n#[cfg(debug_assertions)]\nmod debug_helpers {\n    pub fn print_state(state: &str) {\n        println!("[DEBUG] État actuel : {}", state);\n    }\n\n    pub fn validate_data(data: &[u8]) -> bool {\n        // Vérification coûteuse, inutile en release\n        data.len() < 1000\n    }\n}\n\n// Ce module est uniquement pour la release\n#[cfg(not(debug_assertions))]\nmod release_helpers {\n    pub fn print_state(_state: &str) {\n        // En release, on ne fait rien — on économise le CPU\n    }\n\n    pub fn validate_data(_data: &[u8]) -                

Blogs

Book Recommendations