Instalando paquetes externos

Vamos a ilustrar 3 ejemplos de instalación de programas externos (que no vienen en las distribuciones de Linux) y los posibles problemas o dificultades que pueden presentar.

Estos ejemplos no cubren todas las posibilidades, pero ilustran algunos casos típicos. Habitualmente los desarrolladores adoptan estrategias similares de distribución, configuración e instalación de paquetes de software. Con los años, esas estrategias han ido cambiando, en función de nuevas herramientas y/o medios de distribución que han aparecido. sin ser exhaustivos, vamos a cubrir al menos los casos más habituales.

¿Programas o paquetes?

Si bien uno sigue hablando de programa, lo que generalmente se distribuye e instala es más que un programa y por eso adopta el nombre de paquete.

Paquete: conjunto de

  • programa o programas y utilitarios (source code o binary)
  • bibliotecas (libraries) (propias o de terceros)
  • archivos de configuración
  • archivos de datos
  • documentación y/o manuales

¿Source code o binary?

Cuando se escribe un programa, se emplea un lenguaje de programación (habitualmente un lenguaje de alto nivel), que da lugar a lo que se llama código fuente (source code).

Pero las computadoras no son capaces de ejecutar código fuente, sólo pueden ejecutar código binario o código objeto. El código binario constituye la secuencia de instrucciones de máquina que la computadora puede correr (ejecutar) en su CPU.

Es posible crear un programa generando directamente la secuencia de instrucciones que corresponda a el código binario que se desea correr, pero es muy raro que alguien haga eso hoy. A lo sumo se programa en Lenguaje ensamblador, que es un lenguaje de muy bajo nivel, equivalente a las instrucciones de máquina y a partir del cual se genera el código binario, empleando un programa que se llama ensamblador (assembler).

Lo habitual es escribir el código fuente en un lenguaje de alto nivel y emplear o bien un intérprete para ejecutar ese código o bien un compilador que, a partir del código fuente, genera el código binario que resulta en el ejecutable que puede correr en la computadora.

Lenguajes de programación

Tipo Lenguajes Ejecutable
Interpretado Shell, Perl, Ruby, PHP, R, Julia, etc. Intérprete
Código intermedio (p-code, byte-code) Python, Java Intérprete o VM
Compilado C, C++, FORTRAN, Go, Ada, etc. código binario

Si el lenguaje es compilado, entonces el programa no se puede ejecutar inmediatamente. El ejecutable no es intérprete que “corre” (interpreta) el código fuente, sino el código binario que resulta de una etapa previa, de compilado y linkeditado con bibliotecas del lenguaje y/o del sistema.

Instalar programas que requieran compilación suele ser más complicado, pues además de instalar todas las bibliotecas externas que el programa requiera, también hay que instalar él o los compiladores (un programa puede estar escrito en más de un lenguaje compilado) y además usualmente requieren de una etapa de configuración previa, antes del propio compilado, para especificar qué compilador se va a utilizar, qué bibliotecas externas o internas van a ser incluidas en el ejecutable, y si el linkeditado va a ser estático o dinámico.

Con programas escritos en lenguajes interpretado, la situación suele ser más sencilla, porque se supone que es el intérprete el que resuelve esos temas. Aunque no es muy habitual que un programa (o paquete de programas) requieran de la instalación adicional de módulos o bibliotecas de terceros que no están incorporados por defecto en la instalación estándar del intérprete que se vaya a utilizar. Por ese motivo antes de poder instalar un programa interpretado también es habitual pasar por una etapa de configuración y/o instalación de dependencias (módulos y/o bibliotecas adicionales) y hay que revisar la documentación que detalla cuales son esas dependencias, qué números de versión mínima requiere, y resolver esas dependencias antes de poder instalar y correr.

Configuración, compilación e instalación de programas

En el caso de programas simples, configurar, compilar e instalar programas resulta ser una tarea relativamente simple y rápida. Pero en el caso de paquetes complejos o sofisticados, que pueden llegar a correr en diferentes sistemas operativos, arquitecturas de computadora, que pueden ser compilados con diferentes compiladores, diferentes opciones de compilación y pueden llegar a utilizar diferentes bibliotecas, propias o de terceros, el proceso de configuración, compilación e instalación puede llegar a ser muy engorroso y complicado.

Para ayudar en ese proceso, es habitual emplear herramientas que faciliten y automaticen gran parte del trabajo, dejando al usuario únicamente la tarea de elegir (con mucho juicio) cuales de todas las opciones disponibles son las que desea aplicar a una compilación e instalación particular.

Hay una gran variedad de herramientas que facilitan ese proceso. Apenas mencionaremos las 3 más habituales:

  • make: Makefile
  • CMake
  • Autotools: autoconf y automake

Cmake y autotools son meta-herramientas, que facilitan la creación de Makefiles adecuados a las opciones que un usuario selecciones a la hora de configurar, compilar e instalar un paquete. La herramienta básica siempre es make, que utiliza los Makefiles para todo el proceso.

El problema es que hoy en día, el abanico de compiladores, arquitecturas, opciones de compilación y uso de bibliotecas es tan amplio, que es absolutamente imposible mantener un Makefile que abarque todas las posibilidades y es necesario recurrir a cmake o autoconf+automake para facilitar la construcción de él o los Makefiles necesarios para el proceso de compilación e instalación.

Interesante referencia sobre cómo usar Make: https://tech.davis-hansson.com/p/make/

Versionado de programas y bibliotecas

Desde hace décadas existen herramientas que facilitan el mantenimiento de diferentes versiones de un mismo paquete de programas. Por mencionar algunos conocidos:

  • RCS: Revision Control System
  • SCCS: Source Code Control System (originalmente de Unix)
  • CVS: Concurrent Versions System
  • Subversion (SVN): inspirado en CVS
  • BitKeeper: originalmente utilizado en el desarrollo del kernel de Linux
  • Mercurial (hg)
  • git: desarrollado por Linus Torvalds como sustitución de BitKeeper. El más popular hoy en día

Medios de distribución de software

  • Distribuciones oficiales de Linux
  • CD/DVD
  • Sitio web oficial: FTP, URL(http, https), foros, etc.
  • Servicios web de versionado de software: github.com, gitlab.com, etc

Casos de estudio

Vamos a ver 3 casos, que no cubren todas las posibilidades, pero combinan algunas de las alternativas más comunes que se ven por ahí:

  • Gaussian 2009: se distribuye en forma binaria, en DVD, es de fácil instalación y sólo requiere poner cuidado en los permisos de ejecución
  • Orca: se distribuye como binario, pero requiere la instalación específica de bibliotecas de OpenMPI (que utiliza autotools para generar los Makefiles necesarios para su compilación)
  • Dalton: que se distribuye como código fuente, desde un repositorio en gitlab.com y utiliza cmake para construir los Makefiles requeridos para la compilación.