Una mesa de trabajo con una PC de torre antigua, un monitor CRT mostrando una terminal de compilación y varios disquetes y manuales técnicos alrededor.
Volver al blog

Compilar Quake como en 1997

Compilar Quake como en 1997 sirve para entender cómo cambiaron las toolchains, la reproducibilidad y el costo real de mover código viejo a máquinas modernas. Una guía histórica y práctica para lectores técnicos en Latinoamérica.

Si hoy abres un proyecto grande y compilas con un solo comando, probablemente das por hecho que todo va a funcionar: dependencias descargadas, compilador correcto, flags razonables y una salida reproducible. Pero a finales de los 90 la historia era otra. Compilar software complejo era una mezcla de hardware limitado, toolchains frágiles, sistemas operativos muy distintos entre sí y una tolerancia al error bastante más alta que la actual.

Este artículo toma a Quake como excusa para mirar ese salto. No se trata solo de nostalgia. Compilar Quake como en 1997 te deja ver cómo cambió el trabajo de ingeniería: de pelear con Makefiles y librerías específicas a depender de cadenas de herramientas más estandarizadas, contenedores, CI y builds reproducibles. Y sí, hoy puedes seguir compilándolo, pero el contexto ya no es el mismo.

Qué significaba compilar Quake en 1997

En 1997 Quake no era un proyecto “retro”. Era software vivo, con una base de código en C, dependencias muy ligadas al sistema operativo y un objetivo claro: correr bien en máquinas que hoy nos parecerían modestísimas. La compilación no era un trámite. Era parte del producto. Si el binario no salía para tu plataforma, o salía pero no rendía, el juego sencillamente no existía para ti.

Fabien Sanglard documenta muy bien ese proceso en su artículo original, donde reconstruye el entorno de desarrollo y las decisiones de la época: https://fabiensanglard.net/compile_like_1997/ . La lectura deja claro algo que hoy se nos olvida: el código fuente era solo una parte del problema. También importaban el compilador exacto, las bibliotecas instaladas, la versión del sistema y hasta la forma en que se distribuían los binarios.

Para entender la diferencia, piensa en una estación de trabajo de la época. Un Pentium II a 233 MHz con 64 MB de RAM podía ser una máquina seria. Compilar un proyecto grande ahí no era instantáneo. Cada iteración costaba minutos valiosos, y si el build fallaba por una dependencia o un flag incompatible, tocaba volver a empezar. Esa fricción moldeó la forma de programar.

El entorno importaba tanto como el código

Hoy hablamos de “el proyecto” como si fuera una carpeta con código. En 1997, el entorno era parte del proyecto. Quake dependía de detalles del compilador, del sistema de archivos, de la libc y de la plataforma objetivo. Lo que en Linux funcionaba, en Windows podía romperse por nombres de archivos, rutas o diferencias en el toolchain.

Además, cada plataforma tenía su propio costo de soporte. No era raro que el mismo código necesitara ajustes para DOS, Windows, Linux o variantes Unix. La portabilidad existía, pero no venía gratis. Había que ganarla con ifdefs, scripts y mucha prueba manual.

Eso también explica por qué la documentación y los archivos de build eran tan valiosos. Un Makefile no era solo automatización. Era memoria operativa. Sin él, reproducir el entorno exacto podía convertirse en arqueología.

Toolchains: de la artesanía al sistema

Una toolchain es más que el compilador. Incluye preprocesador, ensamblador, linker, bibliotecas y herramientas auxiliares. En los 90, esa cadena era mucho menos uniforme que hoy. GCC existía y era importante, pero no todo el mundo usaba la misma versión, ni el mismo libc, ni el mismo linker. El resultado era simple: el mismo código podía compilar de manera distinta según dónde lo intentaras.

Hoy la situación mejoró, pero no porque la magia haya aparecido. Mejoró porque se estandarizaron interfaces, se documentaron flags, se popularizaron sistemas de build y se empujó la reproducibilidad como objetivo. Aun así, si trabajas con software legacy, sabes que una versión vieja de GCC puede ser tan importante como el código mismo.

La diferencia práctica se ve en algo básico: compilar Quake hoy en una distro moderna puede requerir adaptar flags, cambiar rutas o usar un compilador compatible con C antiguo. No porque el código esté mal, sino porque el ecosistema evolucionó. El estándar cambió, y el software quedó anclado a decisiones de hace casi 30 años.

GCC, MSVC y la fragmentación real

En esa época no existía la misma homogeneidad que damos por sentada. GCC era dominante en Unix-like, mientras que en Windows el ecosistema giraba alrededor de herramientas de Microsoft o de ports menos consistentes. Eso implicaba diferencias en sintaxis, optimización y hasta en el comportamiento de warnings.

Si un proyecto como Quake quería llegar a más usuarios, tenía que convivir con esa fragmentación. En la práctica, eso significaba condicionales de compilación y muchas decisiones específicas por plataforma. El código portátil era el ideal; el código realmente portable era el resultado de mucho trabajo manual.

La lección sigue vigente. Aunque hoy tengas CMake, Meson o Bazel, el problema de fondo no desapareció. Solo cambió de forma. Ahora peleas menos con el compilador base y más con versiones de dependencias, flags de optimización, ABI y diferencias entre sistemas operativos.

ÉpocaToolchain típicaProblema dominanteTiempo de iteración
1997GCC, MSVC, linkers específicosFragmentación por plataformaMinutos largos
2005Toolchains más estables, scripts más madurosDependencias y compatibilidadMinutos
2025Contenedores, CI, compiladores modernosReproducibilidad y drift de versionesSegundos a minutos

Reproducibilidad: el problema que antes se aceptaba y hoy se combate

En los 90, reproducir una build exacta era difícil y muchas veces no era prioridad. Si el binario funcionaba en la máquina del desarrollador y en la de QA, bastaba. El concepto moderno de reproducible builds todavía no estaba en el centro de la conversación. Lo que importaba era sacar la versión siguiente.

Hoy el listón subió. Quieres poder reconstruir el binario a partir del mismo código, con las mismas dependencias, y obtener resultados consistentes. Eso no solo ayuda a seguridad y auditoría. También reduce el tiempo perdido cuando algo falla en CI y no puedes replicarlo localmente.

Quake es un buen caso para ver ese contraste. Su código refleja una época en la que el entorno era mutable y el build era una especie de ritual. En cambio, hoy puedes encerrar el proyecto en un contenedor y fijar la versión del compilador, del sistema base y de las librerías. El objetivo ya no es solo compilar. Es poder volver a compilar mañana y obtener el mismo resultado.

Qué rompe la reproducibilidad hoy

Aunque tengamos mejores herramientas, la reproducibilidad sigue siendo frágil. Las causas más comunes son bastante concretas:

  1. Versiones distintas de GCC o Clang.
  2. Rutas absolutas incrustadas en el binario.
  3. Fechas y horas incluidas en artefactos.
  4. Dependencias no fijadas con precisión.
  5. Flags de optimización diferentes entre máquinas.

Si trabajas con software antiguo, además sumas otro factor: el código puede asumir comportamientos hoy desaconsejados o eliminados. Eso vuelve más valioso el uso de entornos cerrados, como contenedores o máquinas virtuales, para congelar el contexto.

La documentación oficial de Docker explica bien la idea de aislar el entorno de ejecución y construcción: https://docs.docker.com/ . No resuelve todo, pero sí reduce la variación entre tu laptop y la máquina de CI.

Compilar Quake hoy: qué cambia de verdad

Si intentas compilar Quake hoy, el primer choque no suele ser el código fuente en sí, sino el entorno. Algunas partes del proyecto original dependen de supuestos que ya no son válidos. Otras se pueden reconstruir con relativa facilidad si usas una toolchain compatible o un port mantenido por la comunidad.

La parte interesante es que el problema moderno no es “falta de poder de cómputo”. Al contrario. Ahora tienes CPU de sobra, SSD rápidos y más RAM de la que cualquier build de 1997 habría soñado. El cuello de botella cambió a compatibilidad, mantenimiento y documentación.

Eso también modifica tu estrategia. En vez de instalar todo a mano, probablemente uses un contenedor con una versión concreta de GCC o Clang, o una imagen base de Linux vieja pero controlada. Luego verificas que el binario se genere y que el comportamiento coincida con lo esperado. El objetivo ya no es solo correrlo, sino entender por qué corre.

Un flujo moderno razonable

Un camino práctico para una build de software legado suele verse así:

# 1. Clonar el código fuente o recuperar el snapshot exacto
# 2. Entrar a un entorno controlado
# 3. Fijar la versión del compilador
# 4. Compilar con flags previsibles
# 5. Ejecutar pruebas o lanzar el binario

Si quisieras formalizarlo más, un contenedor con una imagen específica te ayuda a evitar sorpresas. Por ejemplo, una base Debian o Ubuntu vieja puede ser más útil que una distro muy nueva, si el código depende de headers o comportamientos anteriores.

También conviene registrar qué cambiaste. No basta con decir “funcionó en mi máquina”. Si alteraste una línea del Makefile o desactivaste una optimización, eso forma parte de la historia de la build. En software legacy, esa trazabilidad vale oro.

Lo que aprendemos para proyectos actuales

La utilidad de mirar Quake no es solo histórica. Te deja lecciones aplicables a proyectos modernos, sobre todo si trabajas con C, C++, Rust con bindings nativos o repos con dependencias sensibles. La primera lección es que el build es parte del producto. Si no puedes reconstruirlo, no lo controlas del todo.

La segunda lección es que el entorno debe ser explícito. En los 90, la ambigüedad era común porque el ecosistema lo permitía a medias. Hoy ya no hay excusa para no fijar versiones, documentar prerequisitos y automatizar el proceso. Si tu equipo depende de un compilador específico, dilo. Si tu binario cambia por la fecha de compilación, arréglalo o al menos regístralo.

La tercera lección es que la compatibilidad histórica cuesta. Mantener software de hace décadas no es solo “hacerlo andar”. Es conservar decisiones técnicas que a veces chocan con herramientas modernas. Por eso los proyectos serios documentan el entorno, el comando de build y las versiones exactas de sus dependencias.

Recomendaciones prácticas para tu propio proyecto

Si quieres evitar parte del caos que vivieron en los 90, puedes aplicar esto desde hoy:

  • Fija la versión del compilador en CI y en local.
  • Usa un archivo de lock o una imagen base reproducible.
  • Documenta el comando exacto de build.
  • Guarda el hash del commit y el hash de la imagen o entorno.
  • Añade una verificación de artefacto, no solo de compilación.

Si trabajas con equipos distribuidos en Latinoamérica, esto además reduce el costo operativo. No todos tienen la misma distro, la misma versión de sistema o la misma red. Mientras más explícito sea el entorno, menos tiempo pierdes en soporte interno y más fácil es mover builds entre laptops, runners y servidores.

Tabla resumen

Pregunta cortaRespuesta corta
¿Qué hacía difícil compilar en 1997?La fragmentación de toolchains, sistemas y bibliotecas.
¿Qué cambió más desde entonces?La estandarización del entorno y la obsesión por reproducibilidad.
¿Quake es difícil de compilar hoy?Puede serlo por compatibilidad, no por falta de potencia.
¿Qué ayuda más ahora?Contenedores, CI y versiones fijadas.
¿Qué lección deja para proyectos nuevos?El build debe ser tan mantenible como el código.

Compilar Quake como en 1997 no es un ejercicio de nostalgia vacía. Es una forma de ver cómo evolucionó el oficio de construir software. Antes, el reto era sobrevivir a un ecosistema fragmentado. Hoy, el reto es no perder control en medio de tanta automatización. La buena noticia es que ahora tienes herramientas para hacerlo mejor, siempre que no des por sentado que “compilar” significa lo mismo que hace 30 años.

Si alguna vez te toca rescatar un proyecto viejo, este caso te deja una brújula útil: documenta el entorno, fija versiones, conserva el build y no subestimes la historia que hay detrás de un binario que parece simple.

Preguntas frecuentes

¿Por qué Quake es un buen ejemplo para hablar de compilación antigua?
Porque su código refleja una época en la que la portabilidad dependía mucho del compilador, del sistema operativo y de bibliotecas concretas. Además, es un proyecto suficientemente famoso como para comparar el pasado con herramientas actuales sin perder contexto.
¿Compilar software de los 90 hoy es más fácil o más difícil?
Depende del caso. Tienes más potencia y mejores herramientas de aislamiento, pero también más incompatibilidades con compiladores modernos, headers cambiados y supuestos obsoletos del código original.
¿Qué significa reproducibilidad en una build?
Significa poder reconstruir el mismo artefacto a partir del mismo código y del mismo entorno, con diferencias mínimas o nulas. En la práctica, eso exige fijar versiones, controlar dependencias y evitar datos variables como rutas o fechas.
¿Sirve usar contenedores para software legacy?
Sí, mucho. Un contenedor te ayuda a congelar versiones de compilador, librerías y sistema base, lo que reduce el ruido cuando intentas compilar o depurar código antiguo.
¿Qué toolchain se usaba más en esa época?
GCC era muy común en entornos Unix-like, mientras que en Windows predominaban herramientas de Microsoft y otros ports. La elección dependía bastante de la plataforma objetivo y del soporte disponible.
¿Qué lecciones prácticas deja esto para equipos en Latinoamérica?
Que documentar y fijar el entorno ahorra tiempo y dinero. Cuando los equipos usan máquinas distintas, distros distintas o conexiones irregulares, una build reproducible reduce fallos difíciles de diagnosticar.
¿Necesito una máquina vieja para entender este tema?
No. Puedes aprender mucho leyendo el código, usando una imagen de sistema antigua o revisando documentación histórica. La idea no es imitar el hardware, sino entender las restricciones que imponía.

Azirgo

¿Listo para construir tu Producto Digital?

Sitios web, apps móviles, software a medida y soluciones blockchain. Cuéntanos qué tienes en mente y armamos un plan claro contigo.

  • Cotización clara en 48 horas
  • Equipo en Ecuador, atención en español
  • Desde un MVP hasta un producto en producción