Javier Jerónimo


Crear “App Bundle” OS X para una aplicación XUL

27 Jun 2013 » macos, programacion

No soy un fanboy de Apple, pero tuve la oportunidad de escoger un MacBook Air como mi ordenador de trabajo y estoy la mar de contento con esa opción: pesa poco, es un Mac ;), y tengo una consola para todo lo que necesito (bendito homebrew). Además, me permite hacer todo lo que necesito hacer en el día a día. Salvo una cosa, hasta hace poco tiempo: usar de forma cómoda la aplicación XUL que nos permite administrar los portales web.

Tenemos una aplicación de administración construida con XUL de Mozilla. En este artículo no voy a entrar en detalles sobre la aplicación ni sobre XUL. Simplemente voy a dejar por escrito lo que he tenido que hacer para poder ejecutar esta aplicación en OS X como una aplicación más.

Instalar xulrunner

No recuerdo cómo he instalado esto… pero sí que ahora mismo tengo dos versiones instaladas:

raichu:~ javier$ ls -l /Library/Frameworks/XUL.framework/Versions/
total 8
drwxr-xr-x  41 root    admin 1394 11 ago 00:52 1.9.2
drwxr-xr-x@ 41 javier  admin 1394 11 ago 10:46 14.0.1
lrwxr-xr-x   1 javier  admin    6 14 jul 00:11 Current -> 14.0.1

Están instaladas en la ruta /Library así que supongo que encontré las imágenes DMG por algún sitio.

Crear “App Bundle” OS X

Aunque he buscado información en mil sitios, incluyendo la propia página de desarrollo de XUL, al final sólo un popurrí de indicaciones me han funcionado.

Estructura de directorios de un “App Bundle”

Los “app bundle”, es decir, las aplicaciones en OSX no son más que carpetas con una estructura concreta parecida a lo siguiente:

  • Contents/
    • Frameworks/
    • MacOS/
    • Resources/

El diseño que han hecho en Apple hace que tanto el contenido de la aplicación (ficheros binarios, recursos, etc) como las dependencias de la misma puedan ir contenidas en esa estructura de carpetas, lo que hace que las aplicaciones de OS X sean autocontenidas.

En un principio no me gustó la idea, claramente opuesta al concepto de biblioteca compartida como el que se puede encontrar en Linux. Pero pensándolo un poco, y recordando el “infierno de las DLLs” de Windows y la cantidad de enlaces simbólicos para versionar bibliotecas en Linux, no me parece tan mal idea. Además, gracias a esto, instalar es “mover a /Applications” y des-instalar es “mover a la papelera”.

El punto en contra de este diseño: se desperdicia espacio en disco pues sucederá que muchas aplicaciones auto-contenidas tengan las mismas dependencias, lo que llevará a que estén repetidas en disco.

Info.plist

Este fichero define la aplicación: tipo de aplicación, información del desarrollador, versión, información necesaria para su ejecución, etc.

Comparándolo con otras plataformas, es el típico “manifest”.

En mi caso, lo que hice fue generar un info.plist básico con la información de la aplicación que conocía, y con una referencia al lanzador: xulrunner.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>English</string>
    <key>CFBundleExecutable</key>
    <string>xulrunner</string>
    <key>CFBundleGetInfoString</key>
    <string>3.0</string>
    <key>CFBundleIdentifier</key>
    <string>com.example</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>${version}</string>
    <key>CFBundleName</key>
    <string>CMS-XUL</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>${version}</string>
    <key>CFBundleSignature</key>
    <string>My app</string>
    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleURLName</key>
            <string>CMS-XUL</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>chrome</string>
            </array>
    </dict>
    </array>
    <key>CFBundleVersion</key>
    <string>${version}</string>
</dict>
</plist>

En el fichero anterior se pueden leer variables del tipo ${version}. El motivo no es otro que la forma en que genero la aplicación: un trabajo del sistema de integración continua Jenkins se encarga de generar la aplicación desde un repositorio, y en el proceso sustituye la versión en el Info.plist con la que se está construyendo.

Dependencias y recursos de la aplicación XUL

Contenido de la aplicación basada en XULLa única dependencia que tiene esta aplicación es el propio XUL: por una parte el framework de OS X, y por otra el ejecutable xulrunner, quien realmente ejecuta la aplicación.

Y para terminar, la propia aplicación basada en XUL, que se convierte en un conjunto de “recursos” de la aplicación OS X. La carpeta Resources contiene el directorio raíz de mi aplicación.

Resumiendo

El objetivo de este artículo es dejar constancia de cómo he creado la aplicación OS X (el bundle app) para esta aplicación basada en XUL, y resumiendo:

  1. Estructura de directorios estándar de una bundle app.
  2. Info.plist haciendo referencia al ejecutable xulrunner en la carpeta MacOS. El ejecutable se encuentra dentro del framework con el nombre xulrunner: yo lo he copiado porque son escasos 59 KB.
  3. Dependencia XUL.framework incluída como parte de la aplicación
  4. El código fuente de la aplicación basada en XUL dentro de la carpeta Resources.