jueves, 1 de marzo de 2018

¿Qué va en el instalador?

Supongamos que hicimos una aplicación con ZinjaI, y ahora la queremos distribuir. No vamos a pretender que cualquier usuario que quiera usar la aplicación deba instalar ZinjaI, los complementos y conseguirse el código fuente, ¿no? ¿No? ¿Nooo? !NO! Lo razonable es armar un instalador que copie en el sistema del usuario el ejecutable de nuestra aplicación y cualquier otra cosa que esta necesite. De eso habla este post; de cómo generar ese ejecutable y cómo determinar qué más necesita.

Aclaración: Voy a considerar solo el escenario en el que estamos queriendo armar un instalador para Windows. Las ideas básicas son comunes a cualquier sistema operativo, pero el temilla de las bibliotecas se complica bastante en GNU/Linux.

Vamos a armar entonces una carpeta con las cosas indispensables para ejecutar nuestra aplicación en una PC cualquiera; que son:


1. El ejecutable

Lo primero que el usuario va a necesitar es el ejecutable de nuestra aplicación, el .exe final. Cada vez que ejecutamos desde ZinjaI, estamos generando un .exe; pues de lo contrario no habría nada que ejecutar. El .exe estará generalmente en una carpeta llamada release o debug, o similar, junto con un montón de archivos .o. En ZinjaI, desde "Ejecución->Opciones...->General->Ubicación del ejecutable" definimos dónde va a parar el .exe. A veces esta dirección hace referencia al "${TEMP_DIR}", que es la carpeta que definimos en la misma ventana en "Compilación->Directorio para archivos temporales e intermedios".


Solo debemos tomar el ejecutable, el .exe. Los demás archivos son partes del exe. Cada cpp se compila en un .o, y luego se unen todos los .o para formar el exe; así que está todo en el .exe y los fuentes y los .o ya no son necesarios. Peeero, ya hablé hace poco de las diferencias entre Debug y Release. Asegúrense de compilar utilizando una configuración "Release".


2. Las bibliotecas

Cuando nuestro programa utiliza bibliotecas de terceros, tenemos que considerar de dónde sale el código ejecutable de esas bibliotecas. No lo compila nuestro proyecto, ya que no tiene los cpps. En general nuestro proyecto solo ve los .h de una biblioteca, como para saber cómo se usa, pero luego para generar el exe hay que conseguir el código compilado de la misma. Y aquí hay dos opciones: o bien se coloca todo ese código dentro del .exe, junto con nuestros .o; o bien se los deja en archivos separados .dll y se coloca dentro de nuestro exe código que busque y cargue esos dlls. Si vamos por la segunda opción, entonces se dice que nuestro programa "depende" de ciertos dlls.

Si nuestro programa depende de dlls, hay que asegurarse de que los encuentre en el sistema del usuario final; y entonces probablemente tengamos que ponerlos en el instalador. Al ejecutar un programa Windows busca dlls en tres lugares: en la carpeta del ejecutable, entre los archivos de Windows (digamos \windows\system32), y además las rutas que mencione la variable de entorno PATH. ZinjaI usa generalmente este último mecanismo al ejecutar un proyecto desde el IDE. En la pestaña "general" de las opciones de compilación, verán que el último campo "Variables de entorno" a veces dice algo como "PATH+=;${MINGW_DIR}\foo\bin".


Allí le estamos diciendo a ZinjaI que modifique esa variable path y agregue algo. Usualmente ese algo es la subcarpeta bin de la subcarpeta de la biblioteca en cuestión, dentro de la carpeta mingwXX-gccY de la instalación de ZinjaI. Si es un proyecto generado por un complemento de ZinjaI, entonces allí encontrarán los dlls. Deberán agregar esos dlls al instalador, y hacer que el instalador los copie junto al exe, en su misma carpeta. No conviene modificar la variable PATH en el sistema del usuario, y tampoco es buena idea mandarselos a SystemXX.

Podemos ver en ZinjaI cuales son los dlls de los cuales depende "directamente" nuestro ejecutable desde "Herramientas"->"Propiedades del ejecutable..."->pestaña "Dependencias". Allí veremos varios dlls. Algunos serán propios de Windows y no tendremos que copiarlos porque cada Windows tendrá su propia copia/versión; otros serán propios de las bibliotecas que utilicemos. Sin embargo, puede que algunos de estos dlls intenten ellos a su vez cargar más dlls, así que prueben.

Eventualmente podría haber un par que dependan del compilador (cosas con "mingw", "libc", "libstdc++" o hasta "pthreads" en el nombre, que estarán en "ZinjaI/mingwXX-gccY/bin/"). Por defecto ZinjaI está configurado para meter casi todo esto dentro del exe, pero eso se puede alterar cambiando la configuración del toolchain, o puede requerirlo indirectamente alguna biblioteca.


3. Los recursos

Por último, hay que agregar lo que sea que nosotros explícitamente le hagamos cargar a nuestro programa. Por ejemplo, si es un juego habrá que agregar los archivos de imágenes, de sonidos, de música, etc. Esto ya depende de cada uno, de cada proyecto, ustedes sabrán qué usan y qué no.

Si van a distribuir más o menos abierta o públicamente el programa, también deberían agregar algún texto explicitando cuestiones de autoría, licencia e información de contacto si no lo dice ya la aplicación misma.


Teniendo todo eso, lo ideal es generar el instalador y probarlo en otro Windows que no tenga ZinjaI a ver si funciona. Pueden tener una máquina virtual en su entorno de desarrollo para facilitar estas pruebas.

Respecto a qué herramienta en particular utilizar para generar el instalador, no voy a hacer muchos comentarios. Algo muy muy simple aunque poco elegante para mi gusto es WinRar y su opción de autoextraibles (puede generar un exe, mostrar licencia, crear accesos directos, etc). Opciones más específicas y además libres pueden ser por ejemplo NSIS, InnoSetup, BitRock InstallBuilder. Los dos primeros se basan en scripts para definir qué archivos usar y demás configuraciones, pero tienen asistentes gráficos para generar automáticamente esos scripts para los casos más simples. El último tiene una cantidad de opciones increíbles, pero no lo veo tan user-friendly para empezar. Seguramente habrá muchos más, aquí ya les dejo a ustedes la tarea de probar y elegir.

3 comentarios:

  1. Gracias por compartir tus conocimientos...

    ResponderEliminar
  2. Gracias por la info ya que como no sabia nada del la opción de propiedades del ejecutable que trae zinjai abia optado por crear ejecutables independientes (hacer que el ejecutable contenga los .a estatic de la librería y no los .dll dynamic) XD

    ResponderEliminar
  3. De verdad te agradezco la dedicación!! Estudio sistemas en la frsf y este blog es muy muy útil.
    Saludos!! Seguí así

    ResponderEliminar