Actualizado Autor email Licencia Versión PDF
10-01-2025 Fran Gallego fjgallego@ua.es CC-BY-4.0 📄⬇️ Descarga PDF

Cómo hacer la release del juego en Linux

Nuestros juegos deben funcionar en ordenadores de usuarios, que no tendrán instaladas herramientas ni librerías de desarrollo. Además, no debemos pedirles que instalen nada de esto: no es lógico pedir a un usuario que modifique su sistema para poder jugar a nuestro juego.

Por tanto, debemos dar nuestro juego a los usuarios listo para que puedan hacer uso de él. En este documento, os explico cómo lo haremos.

Nota: para el port a Windows, ved "Cómo compilar para Windows con GCC". Todo lo que cuento sirve, excepto quizá la forma de instalar MSYS2, que puede haber variado en estos 2 años. El resto es válido y os enseña bastante de todo el proceso de despliegue. Os recomiendo verlo.

Qué es una release

Para nosotros, una release será un único fichero ZIP que servirá para ejecutar el juego en la máquina del usuario final.

Es importante tener en cuenta:

  • La release es diferente para cada Sistema Operativo.
  • Sólo debe incluir lo estrictamente necesario para que el juego funcione.
  • Evitaremos distribuir símbolos o herramientas de depuración.
  • Evitaremos distribuir código fuente o ficheros con datos personales/confidenciales.
  • NUNCA, BAJO NINGÚN CONCEPTO distribuiremos librerías o ejecutables descargados de Internet.

Ejecutar código en una máquina de usuario abre una puerta a malware y potenciales daños. Si esto sucede, podemos ser denunciados y ser responsables de reparar los daños causados. Esto podría suponer grandes multas, daños a nuestro prestigio o incluso penas de cárcel. Por tanto, debemos ser exquisitos y cuidadosos con cualquier fichero que vaya en nuestra release.

Cómo crear la release

Los siguientes pasos te ayudarán a crear una release, entendiendo y resolviendo la mayor parte de situaciones asociadas. Como siempre, asegúrate de comprender los detalles y saber el por qué de las cosas.

Una vez hayas hecho estos pasos a mano, y los hayas comprendido, podrás crear un script o un objetivo en tu makefile que automatice todo el proceso. De esta forma, sólo tendrías que hacer make release cada vez que quieras crear una nueva release.

Estos son los pasos principales:

  1. Crea las carpetas para la release/. Estructura recomendada:
%% Puedes llamar a las carpetas de otra forma. Por ejemplo, 'release/'
%% podría ser el nombre de tu juego, y 'assets' podría ser 'datos'
%%
release/
  |--libs/      %% Carpeta para binarios de librerías dinámicas
  |--assets/    %% Carpeta para todos los assets del juego
  |--juego      %% Binario del juego (ejecutable)
  1. Compila tu juego en 'modo release'
    • Con optimizaciones, sin símbolos de depuración, sin sanitizers, etc.
  2. Recopila binarios y assets:
    • Librerías requeridas en release/libs/
    • Assets del juego en release/assets/
    • Ejecutable del juego en release/
  3. Crea un paquete y distribuye
    • Comprime la carpeta release/ en un fichero ZIP.

Los siguientes apartados explican detalles de cada paso importante del proceso.

Compilar en 'modo release'

Se habla de compilar en 'modo release' a seleccionar las opciones de compilación y enlazado que producirán un ejecutable optimizado, que sólo tendrá lo que queremos para el usuario final.

Por tanto, cuando compiles tu juego para la release, asegúrate de que estás generando un ejecutable pensado para el usuario final:

  1. Activa las optimizaciones del compilador.
  2. Elimina símbolos y herramientas de depuración.
  3. Enlaza sólo con las librerías definitivas.
  4. Desactiva cheats, cargas de ficheros de texto y otras opciones de nuestro propio juego.

Optimizaciones del compilador

Las optimizaciones básicas del compilador se activan con el modificador -O y tienen varios niveles:

  • -O0: Ninguna optimización (por defecto). Conversión de código 'verbose' (línea por línea). Útil para depurar.
  • -O1: Optimizaciones básicas. Eliminación de redundancias y código muerto. Optimización de flujo de control y reordenamiento simple de instrucciones.
  • -O2: Optimización completa. Añade fusión de bucles, desenrollado, sustitución de constantes, inlining de funciones y generación de código eficiente.
  • -O3: Optimización agresiva/especulativa. Intenta ganar velocidad incluso a costa de aumentar el uso de espacio (precálculos). Puede no ser seguro para todos los programas (especialmente si hay comportamiento no-definido). Vectoriza bucles automáticamente. Añade predicción de ramas. Este es el mejor para nuestros juegos, si los hemos programado bien.
  • -Ofast: Optimización máxima. Incluye optimizaciones fuera del estándar de C++, lo que comporta riesgo de que algunas cosas puedan fallar (especialmente si tenemos comportamiento no definido). Ignora verificaciones de conformidad (puede hacer fallar redondeos de coma flotante). Instrucciones específicas del hardware.

Existen otros flags de optimización, e incluso podéis pedirle al compilador que genere código para una CPU concreta. Esto no es necesario en el nivel en que trabajamos nosotros, pero podéis verlo y jugar con ello si tenéis curiosidad. Importante: no uséis flags que no comprendáis bien cómo funcionan, qué hacen y, especialmente, qué pueden producir como resultado. Comprended bien y usad según consideréis oportuno.

Símbolos y herramientas de depuración

Se habla de compilar en 'modo debug' cuando se activan opciones de depuración, que son útiles mientras estamos desarrollando. Todas estas opciones hay que asegurarse de que están quitadas cuando compilemos en release:

  • -g / -ggdb: añade los símbolos de depuración al ejecutable. Esto sirve para poder trazarlo con el debugger, y ver el código fuente. Pero si dejamos esto en el ejecutable, además de hacerlo más lento y grande, también es como si distribuyéramos el código fuente. Hay que quitarlo.
  • -fsanitize=: elimina los sanitizers. Son muy útiles para saber cuándo hemos cometido un error de acceso a memoria o de comportamiento no-definido, pero no deben saltarle al usuario final. Además, hacen que la ejecución sea más lenta y ocupan muchísima memoria.
  • Librerías en debug: algunas librerías vienen en versiones con símbolos de depuración, o podríamos haberlas compilado nosotros así. Sirven para poder depurar también en el código de la librería, pero no deben distribuirse al usuario.

Enlaza con las librerías definitivas

A la hora de enlazar con las librerías para la release, asegúrate que no incluyes librerías que no usas, ni tampoco librerías que sólo usas para desarrollar. Para eso, asegúrate de las librerías de las que depende tu ejecutable usando ldd. Ejemplo:

[user@host release]$ ldd platform_climber
    linux-vdso.so.1 (0x00007ffde7d58000)
    libasan.so.8 => /usr/lib/libasan.so.8 (0x00007f634c200000)
    libraylib.so.550 => /usr/lib/libraylib.so.550 (0x00007f634c00e000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f634bc00000)
    libm.so.6 => /usr/lib/libm.so.6 (0x00007f634c945000)
    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f634c917000)
    libc.so.6 => /usr/lib/libc.so.6 (0x00007f634ba0f000)
    /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f634ca9c000)

El ejecutable platform_climber (nuestro juego) depende de 8 ejecutables (librerías dinámicas) que deben cargarse en memoria antes que él. Si nos fijamos, veremos que depende de libasan.so.8 (ASAN = Address Sanitizer). Esto ha pasado porque hemos enlazado con esa librería mediante la opción -fsanitize=address, que tenemos que quitar y volver a recompilar y ensamblar.

Las librerías linux-vdso.so.1 y /lib64/ld-linux-x86-64.so.2 son los loaders del sistema operativo (son el código que sabe cargar los demás ejecutables en memoria). Son parte del sistema operativo, y no debemos distribuirlas: estarán en todos los Linux. Las librerías libc.so.6 y libm.so.6 son las librerías de C (librería estándar y funciones matemáticas). Estas también están en todos los Linux y no debemos distribuirlas. Nuestro juego podrá ejecutarse en otras máquinas y encontrará y cargará estas librerías de las carpetas del sistema, igual que aquí.

libgcc_s.so.1 es la librería del compilador GCC, que incluye código para gestionar excepciones en C++, aritmética avanzada (flotantes de 64 bits en máquinas de 32) y compatibilidad con la ABI (Application Binary Interface). Por su parte libstdc++.so.6 es la librería estándar de C++, donde están las implementaciones de todo lo que usáis de C++, como los contenedores. Estas dos librerías están a menudo en casi todos los Linux, pero no siempre. Como podrían no estar en la máquina destino, puede ser interesante que las distribuyáis junto con el juego. Sin embargo, la mejor opción para distribuirlas no es incluir una copia de estos archivos, sino enlazarlos de forma estática en vez de dinámica. Eso significa que el código de estos dos ejecutables (estas dos librerías) se añadirá directamente al binario de vuestro juego. Eso lo más cómodo para estas dos. Para esto, al enlazar, añadiremos los flags -static-libgcc y -static-libstdc++. Así, en el ejemplo, la línea de enlazado del platform_climber quedaría así:

g++ -o platform_climber obj/sceneintro.o obj/scenestars.o obj/entitymanager.o obj/game.o obj/main.o -lraylib -static-libgcc -static-libstdc++

Nota: En la línea de ensamblado no aparece -O2 porque es una opción de compilación, no de enlazado. Esa opción estará en todas las líneas en las que se compilen archivos fuente.

Tras estos ajustes, si ahora hacemos ldd, obtenemos lo siguiente:

[user@host release]$ ldd platform_climber 
    linux-vdso.so.1 (0x00007ffcbd553000)
    libraylib.so.550 => /usr/lib/libraylib.so.550 (0x00007f5dd8105000)
    libm.so.6 => /usr/lib/libm.so.6 (0x00007f5dd8016000)
    libc.so.6 => /usr/lib/libc.so.6 (0x00007f5dd7e25000)
    /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f5dd8377000)
    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f5dd7df7000)

Ya no tenemos libasan.so.8 ni libstdc++.so.6(esta última está dentro de platform_climber, enlazada estática). Sin embargo, libgcc_s.so.1 sí aparece, aunque hemos añadido el flag -static-libgcc. ¿Por qué? Porque, como decimos, las librerías son ejecutables (igual que el nuestro, platform_climber) y, por tanto, pueden requerir, a su vez, de otras librerías. Y eso es lo que está ocurriendo aquí, con libraylib.so.550, que requiere libgcc_s.so.1 dinámica, como vemos si le hacemos ldd:

[user@host release]$ ldd /usr/lib/libraylib.so.550 
    linux-vdso.so.1 (0x00007ffe89b56000)
    libm.so.6 => /usr/lib/libm.so.6 (0x00007f156d60b000)
    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f156d5dd000)
    libc.so.6 => /usr/lib/libc.so.6 (0x00007f156d3ec000)
    /usr/lib64/ld-linux-x86-64.so.2 (0x00007f156d933000)
¿Qué hacemos con libgcc_so.so.1?

Si nos encontramos en este caso, y quisiéramos no depender de libgcc_so.so.1 de forma dinámica, tendríamos estas opciones:

  1. No enlazar con libraylib.so.550, ni con nada que requiera libgcc_so.so.1
  2. Recompilar y enlazar libraylib.so.550 a partir del código fuente, incluyendo libgcc_s de forma estática.
  3. Distribuir libgcc_so.so.1 con nuestra release. Si hacemos esto, podemos quitar -static-libgcc porque duplicamos el código (estará libgcc_s estático dentro de platform_climber y, además, como fichero dinámico libgcc_so.so.1)
  4. Confiar en que libgcc_so.so.1 estará instalada en las carpetas del sistema del usuario, y no distribuirla (en este caso, también eliminamos -static-libgcc para ahorrar espacio)

Aunque parezca contradictorio, en este curso tomaremos la opción 4: asumir que libgcc_so.so.1 estará en el sistema del usuario. En general, en Linux, vamos a encontrar esta librería instalada casi siempre. Es parte del paquete gcc-libs y, dado que Linux está programado en C y, usualmente, compilado con GCC, suele estar. En la máquina restrictiva, estará sin problemas.

Como único detalle, indicaros que esto no será así cuando hagáis port a Windows. En Windows, si compiláis y ensambláis usando MSYS2, ahí estará libgcc_so.dll. Esto hará que, curiosamente, funcione si lo ejecutáis desde el terminal de MSYS2, pero falle si hacéis doble clic. Y esto es, por la forma en que serán buscadas las librerías dinámicas al ejecutar: Windows, por defecto, las busca en la misma carpeta del ejecutable. Por eso, al hacer doble clic, no la encontrará. Por tanto, en Windows, tendréis que añadirla (además de poner todas las DLL junto con el ejecutable).

Recopilar binarios y assets

Para tener nuestra release completa, debemos recopilar todos los archivos que necesita nuestro juego para ejecutarse, sean librerías dinámicas (binarios) o assets. Para ello, simplemente los copiaremos desde donde los tengamos en nuestro sistema, a las carpetas release/libs/ y release/assets/. Si nos es necesario, podemos tener subcarpetas dentro de estas carpetas. Con release/libs/ hay que tener en cuenta que el loader buscará dependencias (librerías) sólo en las carpetas que le digamos, nunca en sus subcarpetas. Si tenemos varias subcarpetas de release/libs/ habrá que dárselas todas como ruta de búsqueda al loader.

Al recopilar los archivos de la release (binarios y assets), el punto crítico son los binarios de las librerías dinámicas (los .so, o shared objects, en Linux). Por defecto, cuando lanzamos un ejecutable compilado con GCC o CLANG, busca los ejecutables de los que depende (las librerías dinámicas) en las carpetas del sistema (/lib/,/usr/lib/,/lib64/). Si no los encuentra, da un error de ejecución como este:

[user@host release]$ ./platform_climber
./platform_climber: error while loading shared libraries: libraylib.so.550: cannot open shared object file: No such file or directory

Cuando distribuimos nuestra release a usuarios finales, en sus máquinas no estarán instalados los binarios de las librerías (como libraylib.so.550). Por tanto, recopilaremos estos binarios, copiándolos a la carpeta release/libs/. Así, nuestra release incluirá estos binarios para que sean ejecutados junto con nuestro juego. El problema es que, al lanzar nuestro juego (./platform_climber) no va a buscar en la carpeta release/libs/ a no ser que se lo digamos nosotros.

Cómo configurar dónde se buscan las dependencias

Para que un ejecutable busque las dependencias donde nosotros queramos (además de en las carpetas del sistema), tenemos dos métodos:

  1. Cabeceras del ejecutable.
  2. Variable de entorno.
    En Linux preferiremos el primero, normalmente. Vamos a ver ambos.
Método de cabeceras del ejecutable

Un binario ejecutable en Linux está estructurado según el formato ELF (Executable and Linkable Format). Sin entrar en detalles, un fichero ELF tiene una primera parte con todos los metadatos (la cabecera), y luego una segunda parte con los segmentos (trozos) de código y datos que deben cargarse en memoria para poder ejecutarlo.

En la cabecera se puede añadir una lista de carpetas, donde se buscarán los binarios de los que dependa. Esta lista la usará el loader del sistema operativo (el programa que cargará y lanzará el ejecutable) para buscar ahí primero las librerías dinámicas. En caso de que no las encuentre ahí, pasará a buscarlas en las carpetas del sistema.

Para añadir carpetas a esta lista de la cabecera, el linker (ld) debe recibir el flag -rpath=carpeta/. Este flag se le puede pasar varias veces al linker, para añadir varias carpetas, por orden. Nosotros, normalmente, no llamaremos a ld directamente; usaremos g++ o clang++. Entonces, para pasar flags al linker usaremos, a su vez, el flag -Wl. Eso le indica al compilador (g++ o clang++) que debe pasar al linker (ld) lo que venga a continuación.

Por tanto, modificaríamos el comando para enlazar platform_climber, dejándolo así:

g++ -o platform_climber obj/sceneintro.o obj/scenestars.o obj/entitymanager.o obj/game.o obj/main.o -lraylib -static-libgcc -static-libstdc++ -Wl,-rpath=libs/

Después de -Wl tenemos que poner una coma (,) seguida de la opción que queremos para el linker (-rpath) sin dejar espacios; de lo contrario, los espacios harán que se interprete como dos flags diferentes en vez de uno, ya que el espacio es un separador. La opción -rpath=libs/ añadirá libs/ como ruta donde buscar dependencias. Como no tiene / delante, es una ruta relativa; por tanto, esa carpeta se buscará desde donde se lanza el ejecutable (llamado, directorio/carpeta de trabajo). Si pusiéramos /libs/ la ruta sería absoluta; la barra inicial / indica que hay que buscar libs/ en la carpeta raíz del árbol de carpetas.

Si hemos hecho bien el proceso, podemos comprobar con ldd que la ejecución buscará y usará los binarios de la carpeta release/libs cuando ejecutemos platform_climber desde dentro de la carpeta release/(nuestra carpeta de trabajo):

[user@host release]$ ldd platform_climber
    linux-vdso.so.1 (0x00007ffc9c6e6000)
    libraylib.so.550 => libs/libraylib.so.550 (0x00007fcd7d81b000)
    libm.so.6 => /usr/lib/libm.so.6 (0x00007fcd7d6f5000)
    libc.so.6 => /usr/lib/libc.so.6 (0x00007fcd7d504000)
    /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fcd7da47000)
    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007fcd7d4d6000)

Ahí vemos como libraylib.so.550 es encontrada enlibs/ (que es release/libs porque estamos lanzando desde release/) y será usada al ejecutar.

Método de la variable de entorno

En ocasiones podemos tener un ejecutable que no está encontrando las dependencias, pero nosotros sí sabemos dónde están. Esto puede ser porque no hayamos usado el método de las cabeceras o bien porque no esté bien adaptado para la situación en que queramos ejecutar. En estos casos, podemos forzar a que busque las librerías al ejecutar usando la variable de entorno LD_LIBRARY_PATH.

Para hacer esto, sólo tenemos que darle el valor que queramos a la variable de entorno LD_LIBRARY_PATH en el shell (terminal) en que vamos a ejecutar nuestro juego. Supongamos que tenemos nuestro platform_climber que busca en release/libs/ y en el sistema, pero queremos hacer una prueba para que busque en release/testlb/. En vez de recompilar, con este método, podemos hacerlo así:

[user@host release]$ export LD_LIBRARY_PATH="testlb/" && ./platform_climber

El doble ampersand (&&) sirve en bash (nuestro shell o terminal) para ejecutar un comando (export LD_LIBRARY_PATH="testlb/") y, sólo si ha tenido éxito, ejecutar el segundo (./platform_climber). De esta forma, en una sola línea, establecemos el valor de la variable de entorno LD_LIBRARY_PATH y ejecutamos nuestro juego, que ahora buscará primero en testlb/.

Puedes comprobar que el método funciona, usando ldd:

[user@host release]$ export LD_LIBRARY_PATH="testlb/" && ldd platform_climber
    linux-vdso.so.1 (0x00007fffb058f000)
    libraylib.so.550 => testlb/libraylib.so.550 (0x00007fc9b8558000)
    libm.so.6 => /usr/lib/libm.so.6 (0x00007fc9b8432000)
    libc.so.6 => /usr/lib/libc.so.6 (0x00007fc9b8241000)
    /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fc9b8784000)
    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007fc9b8213000)

Estas ideas te pueden servir para hacer pruebas y encontrar errores. A veces, los errores son tan sencillos como tener mal el nombre o la ruta de una subcarpeta. Este método puede ayudarte a hacer pruebas rápidas. Recuerda que, en Linux, las mayúsculas y minúsculas son diferentes en los nombres de archivo y carpeta.

Detalles a tener en cuenta

Respecto a las librerías, recuerda que:

  1. linux-vdso.so.1, libm.so.6, libc.so.6 y /lib64/ld-linux-x86-64.so.2 son del sistema y no debes distribuirlas. Por tanto, no las copies a release/libs/
  2. No copies tampoco libgcc_s.so.1, ya que la vamos a considerar instalada en el sistema. Además de la máquina restrictiva, es seguro considerarla instalada en general, ya que está en casi todos los sistemas Linux.
  3. Asegúrate de que copias los ficheros de las librerías y no sus enlaces simbólicos. Observa el comando ls -l | grep ray (listado de ficheros que contienen 'ray' en su nombre), dentro de la carpeta del sistema lib/. Las flechitas -> indican que los archivos son enlaces simbólicos (similar a los 'accesos directos' en Windows). De hecho, verás que todos los enlaces simbólicos son archivos de muy pocos bytes (18, 16, 21...). Esto es porque sólo contienen la ruta del archivo al que realmente se refieren. Cuando copies ficheros a tu carpeta release/libs/ usa después ls -l para comprobar que no son enlaces simbólicos. Presta atención a los tamaños y las flechitas.
[user@host lib]$ ls -l | grep ray
       18 ago 19 23:38 libbluray.so -> libbluray.so.2.4.3
       18 ago 19 23:38 libbluray.so.2 -> libbluray.so.2.4.3
   378856 ago 19 23:38 libbluray.so.2.4.3
       16 nov 25 12:15 libraylib.so -> libraylib.so.550
  1845664 nov 25 12:15 libraylib.so.5.5.0
       18 nov 25 12:15 libraylib.so.550 -> libraylib.so.5.5.0
       21 mar 17  2024 libref_array.so -> libref_array.so.1.2.1
       21 mar 17  2024 libref_array.so.1 -> libref_array.so.1.2.1
    14288 mar 17  2024 libref_array.so.1.2.1
  1. Asegúrate de que sólo copias las librerías una vez. Como ves en el comando anterior, libraylib.so.5.5.0 es el binario real de la librería raylib. Los ficheros libraylib.so y libraylib.so.550 son enlaces simbólicos. Por error, podrías copiarlos todos y, según cómo lo hagas, puedes acabar con 3 copias completas del mismo binario. Revisa que esto no suceda.
  2. Si usas el comando cp (copy) en el shell (o automatizado en tu makefile), puedes estar seguro de que no copiarás enlaces simbólicos. Por ejemplo, con el comando cp /lib/libraylib.so.550 libs/ copiarás el fichero real de raylib a la carpeta release/libs/ aunque estés accediendo a través del enlace simbólico libraylib.so.550. Se creará un fichero release/libs/libraylib.so.550 que será copia de /lib/libraylib.so.5.5.0.

Crear un paquete y distribuir

Cuando ya tengas todo en tu carpeta release/, comprueba que puedes lanzar el juego desde ahí y todo funciona correctamente. Después, procede a crear un paquete comprimido para poder distribuirlo.

Esta última parte es importante: no copies la carpeta 'cruda' a un pendrive, ni la subas así a Internet, ni nada parecido. Crea un único fichero ZIP y usa ese fichero para distribuir. Puede valer cualquier fichero de tipo paquete, como TAR, GZIP, 7ZIP o cualquier otro. Lo importante es que sea un único fichero con toda tu estructura de carpeta dentro.

Cuando creas un único fichero almacenando en él una carpeta con todos sus archivos, se guarda también toda la información del sistema de ficheros. En particular, se guardan usuarios, permisos de los archivos (como los permisos de ejecución en los ejecutables) e información sobre los tipos de fichero. Toda esta información no es igual en distintos sistemas de ficheros. En Linux, por defecto, se usan sistemas de ficheros como EXT3/EXT4, mientras que Windows usa NTFS y ExFAT. En general, los pendrives suelen formatearse con alguno de estos sistemas de ficheros de Windows. En esos sistemas, no existe ni está organizada igual la información de los ficheros. Eso hace que, cuando copias ficheros a un pendrive, pierdas toda esta información por el camino. Por eso, si copias una carpeta completa a un pendrive es muy probable que, al volver a copiarla a otra máquina, muchas cosas no funcionen y haya que reponerlas, como los permisos de ejecución de los ficheros.

Así pues, en Linux, puedes comprimir la carpeta de la siguiente forma:

[user@host dev]$ zip -r release.zip release/

Con este comando, comprimes la carpeta release/, junto con todo su contenido de forma recursiva (-r) y creas el fichero release.zip. Obviamente, este comando se ejecuta justo desde fuera de la carpeta release/, en el nivel inmediatamente superior.

Si no tienes instalada la utilidad zip, puedes instalarla fácilmente en Linux Manjaro así:

[user@host dev]$ sudo pacman -S zip

Desplegar y probar la release

Una vez ya tengas la release, es hora de probarla. Para esto, es super-importante que cuentes con una máquina de pruebas. En clase, dispondréis de la máquina restrictiva. Pero, para poder hacer pruebas en casa, es bueno que tengáis vuestra propia máquina de pruebas.

Máquina de pruebas virtual

Para tener una máquina de pruebas virtual, sigue estos pasos:

  1. Descarga e instala VirtualBox.
  2. Descarga una imagen ISO de Linux Manjaro XFCE.
  3. Crea una máquina virtual en VirtualBox.:
    • Con 2 CPUs, 2GB de RAM y 256 MB de GPU-RAM (compartida).
    • Ponle un disco duro. 10 GBs serán suficientes, pero puedes hacer un disco de 120GBs que ocupará sólo lo que uses, si eliges que sea 'dinámico'.
    • Ponle una unidad óptica (lector de CD) e 'introduce' en él la imagen de Linux Manjaro XFCE que has descargado.
  4. Instala Linux Manjaro XFCE en la máquina virtual
    • Usa todas las opciones por defecto.

Prueba tu release en la máquina de pruebas

En cuanto tengas tu máquina de pruebas virtual, puedas arrancarla y usarla, es el momento de probar en ella tu release.

Puedes configurar la máquina virtual de VirtualBox para que lea de tu pendrive, o puedes copiarte el paquete ZIP a través de Internet o conectándote por ssh a la máquina virtual, si sabes hacerlo (si no sabes, es algo muy muy útil de aprender).

Una vez copiado a la máquina virtual, descomprímelo y pruébalo. Por ejemplo, así:

[user@maquinapruebas ~]$ unzip release.zip
....
[user@maquinapruebas ~]$ cd release/
[user@maquinapruebas release]$ ./platform_climber

Si te aparece algún error al ejecutar porque no encuentre alguna librería, no instales nada en la máquina virtual. Esta máquina es precisamente para esto: para que sepas que hay algo que tienes que mejorar en tu release para que funcione en máquinas sin nada instalado.

Nota: puedes instalar unzip si no está. Esto no afectará a la validez de la prueba para saber si tu juego funciona en una máquina recién instalada.

Puedes usar ldd en la máquina virtual para ver qué dependencias necesita y no encuentra, y todas las demás ideas que hemos visto en este artículo. Una vez lo tengas claro, mejora tu release, corrige el problema y vuelve a probar.

Automatiza el proceso

Cuando hayas hecho todos estos pasos y comprendido bien cómo funciona todo, es el momento de ahorrar tu tiempo: automatízalo. Lo más apropiado es que añadas una regla a tu makefile para producir la release. Por ejemplo, podrías empezar creando una regla para producir release.zip así:

release.zip: platform_climber
   mkdir -p release/libs/
   mkdir -p release/assets/
   cp platform_climber release/
   %%... comandos para copiar las librerías ...
   %%... comandos para copiar los assets ...
   zip -r release.zip release/

Así, una vez tengas todos los comandos puestos en la regla, con sólo ejecutar,

[user@host dev]$ make release.zip

Se creará automáticamente el release.zip. De hecho, al poner que depende de platform_climber, si el ejecutable no está actualizado, se compilará y enlazará antes de crear el release.zip.

Última modificación: viernes, 10 de enero de 2025, 20:06