Determinando compilaciones debug/release en Rust mediante cfg: guía completa

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Cómo diferenciar debug de release en Rust? Analizamos cfg con ejemplos reales

\n\n

¿Alguna vez has escrito código en Rust y has pensado: «Ojalá en modo debug añadir un registro detallado, y en release eliminar todo lo superfluo»? ¿O quizás querías incluir aserciones solo durante el desarrollo, pero desactivarlas en la compilación final? Si es así, has llegado al lugar indicado. Hoy analizaremos cómo, con la magia de cfg, controlar el comportamiento del código según el tipo de compilación. Esto no es solo teoría árida: recorreremos el camino desde una simple bandera hasta una solución lista para producción.

\n\n

El tema no surge de la nada: en Stack Overflow, la pregunta «How to check release / debug builds using cfg in Rust?» ha acumulado miles de visitas. Esto significa que muchos lo necesitan. Y lo explicaremos en detalle.

\n\n

¿Por qué es importante? Dos mundos, dos enfoques

\n\n

En Rust existen dos perfiles principales de compilación: debug (con la bandera --debug o simplemente cargo build) y release (cargo build --release). Se diferencian no solo en las optimizaciones, sino también en el comportamiento de algunas verificaciones integradas.

\n\n

Por ejemplo:

\n
    \n
  • debug: lento, pero con verificaciones de límites de arreglos, símbolos de depuración y aserciones.
  • \n
  • release: rápido, pero sin verificaciones adicionales, todo en aras del rendimiento.
  • \n
\n\n

¿Qué pasa si necesitas que en la versión debug el programa registre cada acción, y en release solo los errores críticos? ¿O que un endpoint de prueba solo esté disponible localmente? Para eso existe cfg.

\n\n

Herramientas principales: cfg!() y #[cfg()]

\n\n

En Rust hay dos formas de verificar el tipo de compilación:

\n
    \n
  • La macro cfg!() — se ejecuta durante la compilación, devuelve un bool. Se usa dentro de funciones.
  • \n
  • El atributo #[cfg()] — incluye o excluye completamente un bloque de código de la compilación.
  • \n
\n\n

Ambos usan las mismas claves. La más popular para nuestra tarea es debug_assertions. Está activa solo en la compilación debug. También existe la inversa: not(debug_assertions) para release.

\n\n

Ejemplo 1: Verificación simple dentro de una función

\n\n

Empecemos con la macro cfg!(). Supongamos que tenemos una función que calcula algo complejo. En debug queremos verificar los datos de entrada:

\n\n
fn calculate_something(x: i32) -> i32 {\n    // Verificación solo en compilación debug\n    if cfg!(debug_assertions) {\n        println!("[DEBUG] calculate_something llamada con x = {}", x);\n        assert!(x > 0, "¡x debe ser positivo!");\n    }\n\n    // Lógica principal\n    x * 2\n}\n\nfn main() {\n    let result = calculate_something(10);\n    println!("Resultado: {}", result);\n}\n
\n\n

¿Qué sucederá?

\n
    \n
  • Con cargo build (debug) — verás el registro y, si x ≤ 0, el programa fallará con una aserción.
  • \n
  • Con cargo build --release — la línea con cfg!(debug_assertions) se convertirá en false, y el compilador eliminará este bloque como código muerto. ¡Sin sobrecarga!
  • \n
\n\n

Ejemplo 2: Exclusión total de código con #[cfg()]

\n\n

A veces no basta con saltarse la ejecución, sino que se necesita eliminar por completo una función o un módulo del binario. Para eso usamos el atributo:

\n\n
// Este módulo se compilará SOLO en compilación debug\n#[cfg(debug_assertions)]\nmod debug_helpers {\n    pub fn print_state(state: &str) {\n        println!("[DEBUG] Estado actual: {}", state);\n    }\n\n    pub fn validate_data(data: &[u8]) -> bool {\n        // Verificación costosa, no necesaria en release\n        data.len() < 1000\n    }\n}\n\n// Este módulo es solo para release\n#[cfg(not(debug_assertions))]\nmod release_helpers {\n    pub fn print_state(_state: &str) {\n        // En release no hacemos nada — ahorramos CPU\n    }\n\n    pub fn validate_data(_data: &[u8]) -                

Blogs

Book Recommendations