Miriam Ruiz
random thoughts on technology and life











{August 16, 2007}   Fénix en Debian

Fénix ha entrado por fin en Debian, aunque he tenido que parchearlo seriamente para dejarlo un poco en condiciones, al menos hasta que salga la primera release de Bennu. En el foro de Fénix expliqué con detalle alguno de los cambios que he tenido que hacer, pero creo que es conveniente que ponga también una nota aquí por si alguien que no lea dichos foros tiene interés. Asímismo también he dejado disponible un archivo con los parches ya aplicados, por si alguna persona que use otra distribución quiere usarlo. Fénix es el nombre de un proyecto libre destinado a crear un compilador gratuito para un lenguaje derivado del que en su día Hammer Technologies creó para el desarrollo de videojuegos con su entorno DIV, ya he escrito anteriormente sobre él en mi bitácora.

En todo caso, no se trata de un fork, sino que la versión de referencia de Fénix para mí sigue siendo el código que hay en el repositorio CVS de SourceForge. Mi idea es mantener la compatibilidad de los juegos y de los plugins respecto al código que ya hay e incorporar los últimos cambios que haya en el CVS.

El código original tenía cosas que ni por asomo se podían consentir desde el punto de vista de la calidad de los paquetes, así que he tenido que modificar ciertas cosas. Asímismo, los mensajes eran un caos, la mitad en español y la mitad en inglés. Los he pasado todos a inglés y los he internacionalizado con gettext, incluída una traducción (aún a medias) al Español, pero esta vez con un sistema estándar y en condiciones.

Otro problema con el que me he encontrado es que no está garantizada la compatibilidad de bytecodes entre programas compilados con diferentes versiones de Fénix. Ésto, para mucha gente, no es especialmente un problema, ya que suelen acompañar los releases de sus juegos con una copia ejecutable del intérprete, pero es una política aberrante respecto a lo que significaría hacer algo así en una distribución, especialmente a nivel de mantenimiento de bugs o de correcciones de seguridad.

La idea entonces era encontrar una forma de poder distribuir los juegos en Debian de tal forma que siguieran funcionando incluso a pesar de actualizaciones de Fénix. Para ello, puesto que no está en mi mano garantizar la estabilidad del byecode (que, reconozco, fué mi primer pensamiento, y el primer paquete de Fénix que hice iba en esa línea) ya que eso a medio plazo sí que significaría a nivel efectivo crear un fork, mi única solución es hacer como hacemos con algunos programas en Python, y no distribuir los juegos precompilados a .dcb, sino su código fuente (los .prg, .inc y demás), de tal forma que se compilen silenciosamente y bajo demanda a la hora de ejecutarlos. Esto es válido solamente mientras el código de los juegos que esté empaquetando sea lo suficientemente rápido de compilar para que no sea un problema, y de momento no lo es, pero en algún momento del futuro tendré que modificar el sistema de nuevo de tarl forma que se guarde una caché del juego precompilado, y se use o se recompile dependiendo del timestamp y de algunos factores más, parecido a como Python hace con los .pyc. Ésto, que es una idea futurible, aún no lo he implementado.

La primera idea para compilar los juegos bajo demanda fué compilar un fichero temporal en /tmp/ y simplemente cargarlo normalmente, todo ello con un script, pero me pareció una chapuza, y además más difícil de asegurar el sistema a nivel de seguridad, así que me decidí a usar pipes (tuberías) y poder encadenarlas. Para ello, añadí al compilador la opción -o para especificar el fichero de salida, donde el nombre del fichero de salida puede ser “-”, lo que significa stdout (la salida estándar, file descriptor 1), y modifiqué el intérprete para poder leer de “-” (entrada estándar, stdin, file descriptor 0) en vez de desde un archivo convencional. Por supuesto, tuve que modificar el compilador para que todos los mensajes de error fueran redireccionados a stderr (salida estándar de errores, file descriptor 2) en vez de a stdout, para evitar que éstos se mezclaran con el programa quze está saliendo por stdout.

Todo ello se puede ver en acción ejecutando el siguiente comando:

fenix-fxc -o – | fenix-fxi -

Pero claro, cuando hacía ésto, quedaba un título muy feo en la ventana, el nombre del archivo “-”, así que modifiqué el código para que si éste era el caso, y no sabíamos el nombre del archivo, el título de la ventana pasara a ser “Fenix”. Más tarde se me ocurrió añadir un modificador para poder cambiar el título de la ventana y poder poner el nombre del juego desde el script de arranque del mismo, en vez del nombre del archivo. Se puede ver en acción usando:

fenix-fxc -o – | fenix-fxi -t “Nombre del Juego” -

Otro de los subsistemas que he tenido que tocar es el de los plugins, o extensiones al lenguaje mediante librerías enlazadas dinámicamente. Necesitaba la opción de incluir los plugins de forma única en el sistema, en lugar de una vez en cada juego como hasta ahora, aunque he mantenido esa opción de momento por retrocompatibilidad. En todo caso todo ese subsistema (el de cargar los plugins desde el directorio del juego), en algún momento deberá ser rehecho en la versión original de Fénix, ya que ahora mismo es imposible distribuir un juego precompilado para diferentes arquitecturas de Linux a la vez, digamos i386, amd64 y powerpc, por ejemplo. Las tres librerías dinámicas resultantes (archivos .so) usarían el mismo nombre. Otro apunte para corregir en el futuro.

En todo caso, como digo, necesitaba varias cosas, una de ellas es poder poner un repositorio estándar para tener los plugins comunes instalados una sola vez para todo el sistema, y que los programas los cogieran de ahí si no existe el plugin correspondiente en el directorio del juego. Tal y como está hecho, ésta sigue siendo la opción principal de carga de plugins, y todo sigue siendo retrocompatible y comportándose igual que lo hacía. Solamente en el caso de que el plugin no estuviera, lo que en la versión oficial daría un error, en este caso lo busca en el directorio global antes de dar dicho error. El directorio que he elegido es “/usr/lib/fenix/plugins”.

La segunda modificación importante que he hecho al código de los plugins ha sido añadir un símbolo nuevo exportado opcionalmente por los plugins (o DLL’s, como mucha gente de la que programa en Fénix los conoce, aunque la extensión .dll solamente tiene sentido en Windows, ni en Linux ni en Mac). Este símbolo se llama “PluginVersion”, y define la versión del ABI binario de las cabeceras contra las que ha sido compilado el plugin. Si estas cabeceras tuvieran cambios relevantes respecto a la versión compilada de Fenix usada (las cabeceras que usan los plugins son: include/fxdll.h, fxi/inc/instance_st.h, fxi/inc/grlib_st.h, include/files_st.h, include/typedef_st.h, include/xctype_st.h, fxi/inc/flic_st.h, fxi/inc/i_procdef_st.h, include/offsets.h, include/pslang.h, include/fbm.h ), daria lugar a fallos extraños en el comportamiento de las mismas, y muy probablemente SIGSEGV (Segmentation Fault). Para incluir el número del ABI binario he añadido el archivo fxdll_version.h. Los cambios relevantes sobre todo este subsistema de plugins en este sentido están en el parche fxdll_version.patch.

Por supuesto, he realizado este cambio hecho teniendo en cuenta la retrocompatibilidad, de tal forma que si se intenta cargar un plugin que no exporte el símbolo PluginVersion, por defecto se carga igual (garantizando, por tanto, que los plugins viejos siguen funcionando). Asímismo el nuevo símbolo exportado es simplemente ignorado por los intérpretes que no hayan incluído esta característica, por lo que el cambio tampoco les afecta. La idea es más bien que no haya que cambiar nunca este valor, que como he dicho no es la versión de Fénix sino el identificador de la versión del ABI con la que se comunica con los plugins (de igual forma que el SONAME actúa en el caso de las librerías dinámicas), pero en caso de que haya que hacerlo, no se produzca uno de esos misteriosos problemas que ocurren en estos casos. Si PluginVersion existe, y es diferente respecto al número de versión con el que ha sido compilado Fénix, simplemente rechaza cargar ese plugin, detectándolo como incopmatible. PluginVersion es de tipo unsigned int.



demasiada Cafeína v3.0 says:

[...] Miriam Ruiz se ha encargado de apañar Fénix y empaquetarlo para Debian. Si te pica el gusanillo de crear tus propios juegos 2D y no sabes por dónde empezar, Fenix es una buena opción. ¡Gracias, Miry! [...]



University Update - Linux - Fénix en Debian says:

[...] YouTube Contact the Webmaster Link to Article linux Fénix en Debian » Posted at Miriam Ruiz on Thursday, August 16, 2007 Fénix ha entrado por fin en Debian, aunque he tenido que parchearlo seriamente para dejarlo un poco en condiciones, al menos hasta que salga la primera release de Bennu. En el foro de Fénix expliqué con detalle alguno de los cambios que he tenido que hacer, View Original Article » [...]



carlos says:

Que yo sepa, los ficheros de python se precompilan a .pyo al momento de la instalación en un postinst. Tal vez se podría hacer algo así para no tener que compilar cada vez que quieres jugar.

Saludos



Miry says:

Se podría, pero no estoy segura de que fuera una buena idea, ya que tanto el formato de los archivos compilados como las estructuras de memoria tienen problemas con tamaños de palabras diferentes de 32 bits y con diferentes endianess. He optado por lo más seguro.



Leave a Reply


about

This is a personal webpage that belongs to Miriam Ruiz.
If you want to contact her, you can do at:
webmistress(at)miriamruiz(dot)es.

pages
categories
archive
twitter
calendar
August 2019
M T W T F S S
« Nov    
 1234
567891011
12131415161718
19202122232425
262728293031  
credits
WikiLeaks

La Lista de Sinde