Breve resumen: Esta guía detallada explica cómo para instalar un programa a partir del código fuente en Linux y cómo eliminar el software instalado del código fuente.
Una de las mayores fortalezas de su distribución Linux es su gestor de paquetes y el repositorio de software asociado. Con ellos, dispones de todas las herramientas y recursos necesarios para descargar e instalar nuevo software en tu ordenador de forma totalmente automatizada.
Pero a pesar de todos sus esfuerzos, los mantenedores de paquetes no pueden manejar todos y cada uno de los casos de uso. Tampoco pueden empaquetar todo el software disponible. Por lo tanto, todavía hay situaciones en las que tendrá que compilar e instalar software nuevo usted mismo. En cuanto a mí, la razón más común, de lejos, es que tengo que compilar algún software cuando necesito ejecutar una versión muy específica, o modificar el código fuente mediante el uso de algunas opciones de compilación elegantes.
Si sus necesidades pertenecen a esta última categoría, es probable que ya sepa qué hacer. Pero, para la gran mayoría de los usuarios de Linux, compilar e instalar software a partir del código fuente por primera vez podría parecer una ceremonia de iniciación: algo aterradora; pero con la promesa de entrar en un nuevo mundo de posibilidades y un lugar de prestigio en una comunidad privilegiada.
- A. Instalación de software desde código fuente en Linux
- Paso 1: Obtener el código fuente de GitHub
- Paso 2: Comprender el sistema de compilación del programa
- Paso 3: El FHS
- B. ¿Qué pasa si las cosas salen mal al instalar desde el código fuente?
- De Debian 9.0 «Stretch»
- De CentOS 7.0
- C. Realizar cambios en el software instalado desde el código fuente
- D. Deje que el shell localice nuestro software de compilación personalizado
- Agregar un enlace desde /usr/local/bin
- Modificar la RUTA
- E. Cómo eliminar el software recién instalado del código fuente
- Esperar? ¿Dónde estaba el Infierno de la Dependencia?
A. Instalación de software desde código fuente en Linux
Y eso es exactamente lo que haremos aquí. Para el propósito de este artículo, digamos que necesito instalar NodeJS 8.1.1 en mi sistema. Esa versión exactamente. Una versión que no está disponible en el repositorio Debian:
sh$ apt-cache madison nodejs | grep amd64 nodejs | 6.11.1~dfsg-1 | http://deb.debian.org/debian experimental/main amd64 Packages nodejs | 4.8.2~dfsg-1 | http://ftp.fr.debian.org/debian stretch/main amd64 Packages nodejs | 4.8.2~dfsg-1~bpo8+1 | http://ftp.fr.debian.org/debian jessie-backports/main amd64 Packages nodejs | 0.10.29~dfsg-2 | http://ftp.fr.debian.org/debian jessie/main amd64 Packages nodejs | 0.10.29~dfsg-1~bpo70+1 | http://ftp.fr.debian.org/debian wheezy-backports/main amd64 Packages
Ahora, instalar NodeJS en Ubuntu o Debian es bastante simple si lo hace con el gestor de paquetes. Pero hagámoslo a través del código fuente.
Paso 1: Obtener el código fuente de GitHub
al Igual que muchos proyectos de código abierto, las fuentes de NodeJS se puede encontrar en GitHub: https://github.com/nodejs/node
Así que, vamos a ir directamente allí.
Si no está familiarizado con GitHub, git o cualquier otro sistema de control de versiones que valga la pena mencionar, el repositorio contiene el código fuente actual del software, así como un historial de todos los las modificaciones hechas a través de los años a ese software. Eventualmente hasta la primera línea escrita para ese proyecto. Para los desarrolladores, mantener esa historia tiene muchas ventajas. Para nosotros hoy en día, la principal es que podremos obtener las fuentes del proyecto como lo fueron en cualquier momento dado. Más precisamente, podré obtener las fuentes tal como estaban cuando se lanzó la versión 8.1.1 que quiero. Incluso si hubo muchas modificaciones desde entonces.
En GitHub, puede usar el botón «branch» para navegar entre diferentes versiones del software. «Rama » y» etiquetas » son conceptos algo relacionados en Git. Básicamente, los desarrolladores crean «ramas» y «etiquetas» para realizar un seguimiento de eventos importantes en el historial del proyecto, como cuando comienzan a trabajar en una nueva función o cuando publican una versión. No entraré en los detalles aquí, todo lo que necesita saber es que estoy buscando la versión etiquetada «v8.1.1»
Después de haber elegido en el «v8.1.etiqueta de 1», la página se actualiza, el cambio más obvio es que la etiqueta ahora aparece como parte de la URL. Además, notará que la fecha de cambio de archivo también es diferente. El árbol de fuentes que está viendo ahora es el que existía en el momento en que se creó la etiqueta v8.1.1. En cierto sentido, puedes pensar en una herramienta de control de versiones como git como una máquina de viajes en el tiempo, que te permite ir y venir al historial de un proyecto.
En este punto, podemos descargar las fuentes de NodeJS 8.1.1. No te puedes perder el gran botón azul que sugiere descargar el archivo ZIP del proyecto. En cuanto a mí, descargaré y extraeré el ZIP de la línea de comandos por el bien de la explicación. Pero si prefiere usar una herramienta GUI, no dude en hacerlo:
wget https://github.com/nodejs/node/archive/v8.1.1.zipunzip v8.1.1.zipcd node-8.1.1/
Descargar el archivo ZIP funciona muy bien. Pero si quieres hacerlo» como un profesional», te sugeriría usar directamente la herramienta git
para descargar las fuentes. No es complicado en absoluto, y será un buen primer contacto con una herramienta que a menudo encontrará:
# first ensure git is installed on your systemsh$ sudo apt-get install git# Make a shallow clone the NodeJS repository at v8.1.1sh$ git clone --depth 1 \ --branch v8.1.1 \ https://github.com/nodejs/nodesh$ cd node/
Por cierto, si tiene un problema, considere la primera parte de este artículo como una introducción general. Más adelante tengo explicaciones más detalladas para las distribuciones basadas en Debian y RedHat para ayudarle a solucionar problemas comunes.
De todos modos, siempre que haya descargado el código fuente usando git
o como un archivo ZIP, ahora debería tener exactamente los mismos archivos de código fuente en el directorio actual:
sh$ lsandroid-configure BUILDING.md common.gypi doc Makefile srcAUTHORS CHANGELOG.md configure GOVERNANCE.md node.gyp testbenchmark CODE_OF_CONDUCT.md CONTRIBUTING.md lib node.gypi toolsBSDmakefile COLLABORATOR_GUIDE.md deps LICENSE README.md vcbuild.bat
Paso 2: Comprender el sistema de compilación del programa
Normalmente hablamos de «compilar los orígenes», pero la compilación es solo una de las fases necesario para producir un software de trabajo a partir de su fuente. Un sistema de compilación es un conjunto de herramientas y prácticas utilizadas para automatizar y articular esas diferentes tareas con el fin de construir completamente el software con solo emitir unos pocos comandos.
Si el concepto es simple, la realidad es algo más complicada. Porque diferentes proyectos o lenguajes de programación pueden tener diferentes requisitos. O por los gustos del programador. O las plataformas soportadas. O por razones históricas. O or o.. hay una lista casi interminable de razones para elegir o crear otro sistema de compilación. Todo eso para decir que hay muchas soluciones diferentes que se utilizan por ahí.
NodeJS utiliza un sistema de compilación de estilo GNU, es una opción popular en la comunidad de código abierto y, una vez más, una buena manera de comenzar su viaje.
Escribir y ajustar un sistema de compilación es una tarea bastante compleja, pero para el «usuario final», los sistemas de compilación de estilo GNU facilitan la tarea utilizando dos herramientas: configure
y make
.
El archivoconfigure
es un script específico del proyecto que verificará la configuración del sistema de destino y la función disponible para garantizar que el proyecto se pueda construir, y finalmente se ocupará de las especificidades de la plataforma actual.
Una parte importante de un típico configure
trabajo es construir el Makefile
. Este es el archivo que contiene las instrucciones necesarias para construir el proyecto de manera efectiva.
La herramientamake
, por otro lado, es una herramienta POSIX disponible en cualquier sistema tipo Unix. Leerá el Makefile
específico del proyecto y realizará las operaciones necesarias para compilar e instalar su programa.
Pero, como siempre en el mundo de Linux, todavía tienes algo de indulgencia en personalizar la compilación a tus necesidades específicas.
./configure --help
El configure -help
comando te mostrará todas las opciones de configuración disponibles. Una vez más, se trata de un proyecto muy específico. Y para ser honesto, a veces es necesario profundizar en el proyecto antes de comprender completamente el significado de todas y cada una de las opciones de configuración.
Pero hay al menos una opción estándar de GNU Autotools que debe conocer: la opción --prefix
. Esto tiene que ver con la jerarquía del sistema de archivos y el lugar donde se instalará el software.
Paso 3: El FHS
La jerarquía del sistema de archivos Linux en una distribución típica cumple principalmente con el Estándar de Jerarquía del sistema de archivos (FHS)
Ese estándar explica el propósito de los diversos directorios de su sistema: /usr
/tmp
/var
y así sucesivamente.
Cuando utilice GNU Autotools— y la mayoría de los demás sistemas de compilación— la ubicación de instalación predeterminada para su nuevo software será /usr/local
. ¿Cuál es una buena opción, ya que según el FSH «La jerarquía /usr/local es para uso del administrador del sistema al instalar software localmente? Debe estar a salvo de sobrescribirse cuando se actualice el software del sistema. Se puede usar para programas y datos que se pueden compartir entre un grupo de hosts, pero que no se encuentran en /usr.»
La jerarquía /usr/local
de alguna manera replica el directorio raíz, y encontrará allí /usr/local/bin
para los programas ejecutables, /usr/local/lib
para las bibliotecas, /usr/local/share
para los archivos independientes de la arquitectura y y así sucesivamente.
El único problema al usar el árbol /usr/local
para la instalación de software personalizado es que los archivos de todo su software se mezclarán allí. Especialmente, después de haber instalado un par de software, será difícil rastrear a qué archivo exactamente de /usr/local/bin
y /usr/local/lib
pertenece a qué software. Sin embargo, eso no causará ningún problema al sistema. Después de todo, /usr/bin
es casi el mismo lío. Pero eso se convertirá en un problema el día que desee eliminar un software instalado manualmente.
Para resolver ese problema, normalmente prefiero instalar software personalizado en el subárbol /opt
. Una vez más, para citar a la FHS:
_» / opt está reservado para la instalación de paquetes de software de aplicaciones adicionales.
Un paquete para ser instalado en /opt debe localizar sus archivos estáticos en una partición /opt/<el paquete> o /opt/<proveedor> árbol de directorios, donde <el paquete> es un nombre que describe el paquete de software y <proveedor> es el proveedor de LANANA nombre registrado.»_
Así que crearemos un subdirectorio de /opt
específicamente para nuestra instalación personalizada de NodeJS. Y si algún día quiero eliminar ese software, simplemente tendré que eliminar ese directorio:
sh$ sudo mkdir /opt/node-v8.1.1sh$ sudo ln -sT node-v8.1.1 /opt/node# What is the purpose of the symbolic link above?# Read the article till the end--then try to answer that# question in the comment section!sh$ ./configure --prefix=/opt/node-v8.1.1sh$ make -j9 && echo ok# -j9 means run up to 9 parallel tasks to build the software.# As a rule of thumb, use -j(N+1) where N is the number of cores# of your system. That will maximize the CPU usage (one task per# CPU thread/core + a provision of one extra task when a process# is blocked by an I/O operation.
Cualquier cosa menos» ok»después de que el comando make
se haya completado significaría que hubo un error durante el proceso de compilación. Como ejecutamos una compilación paralela debido a la opción -j
, no siempre es fácil recuperar el mensaje de error dado el gran volumen de salida producido por el sistema de compilación.
En el caso de un problema, simplemente reinicie make
, pero sin la opción -j
esta vez. Y el error debería aparecer cerca del final de la salida:
sh$ make
Finalmente, una vez que la compilación haya llegado al final, puede instalar su software en su ubicación ejecutando el comando:
sh$ sudo make install
Y probarlo:
sh$ /opt/node/bin/node --versionv8.1.1
B. ¿Qué pasa si las cosas salen mal al instalar desde el código fuente?
Lo que he explicado anteriormente es principalmente lo que puedes ver en la página de «instrucciones de construcción» de un proyecto bien documentado. Pero dado que el objetivo de este artículo es permitirle compilar su primer software a partir de fuentes, tal vez valga la pena tomarse el tiempo para investigar algunos problemas comunes. Por lo tanto, haré todo el procedimiento de nuevo, pero esta vez desde sistemas Debian 9.0 y CentOS 7.0 nuevos y mínimos para que pueda ver los errores que encontré y cómo los resolví.
De Debian 9.0 «Stretch»
:~$ git clone --depth 1 \ --branch v8.1.1 \ https://github.com/nodejs/node-bash: git: command not found
Este problema es bastante fácil de diagnosticar y resolver. Sólo tiene que instalar el git
paquete:
:~$ sudo apt-get install git
:~$ git clone --depth 1 \ --branch v8.1.1 \ https://github.com/nodejs/node && echo okok
:~/node$ sudo mkdir /opt/node-v8.1.1:~/node$ sudo ln -sT node-v8.1.1 /opt/node
No hay problema aquí.
:~/node$ ./configure --prefix=/opt/node-v8.1.1/WARNING: failed to autodetect C++ compiler version (CXX=g++)WARNING: failed to autodetect C compiler version (CC=gcc)Node.js configure error: No acceptable C compiler found! Please make sure you have a C compiler installed on your system and/or consider adjusting the CC environment variable if you installed it in a non-standard prefix.
Obviamente, para compilar un proyecto, usted necesita un compilador. NodeJS está escrito usando el lenguaje C++, necesitamos un compilador de C++. Aquí instalaré `g++’, el compilador C++ de GNU para ese propósito:
:~/node$ sudo apt-get install g++:~/node$ ./configure --prefix=/opt/node-v8.1.1/ && echo okok
:~/node$ make -j9 && echo ok-bash: make: command not found
Otra herramienta que falta. Los mismos síntomas. La misma solución:
:~/node$ sudo apt-get install make:~/node$ make -j9 && echo okok
:~/node$ sudo make install:~/node$ /opt/node/bin/node --versionv8.1.1
el Éxito!
por Favor note: He instalado las diversas herramientas una por una para mostrar cómo diagnosticar los problemas de compilación y para mostrarle la solución típica para resolver esos problemas. Pero si busca más información sobre el tema o lee otros tutoriales, descubrirá que la mayoría de las distribuciones tienen «meta-paquetes» que actúan como un paraguas para instalar algunas o todas las herramientas típicas utilizadas para compilar un software. En sistemas basados en Debian, probablemente encontrará el paquete build-essentials para ese propósito. Y en las distribuciones basadas en Red-Hat, ese será el grupo de «Herramientas de desarrollo».
De CentOS 7.0
~]$ git clone --depth 1 \ --branch v8.1.1 \ https://github.com/nodejs/node-bash: git: command not found
Comando no encontrado? Simplemente instálelo usando el administrador de paquetes yum
:
~]$ sudo yum install git
~]$ git clone --depth 1 \ --branch v8.1.1 \ https://github.com/nodejs/node && echo okok
~]$ sudo mkdir /opt/node-v8.1.1 ~]$ sudo ln -sT node-v8.1.1 /opt/node
~]$ cd node node]$ ./configure --prefix=/opt/node-v8.1.1/WARNING: failed to autodetect C++ compiler version (CXX=g++)WARNING: failed to autodetect C compiler version (CC=gcc)Node.js configure error: No acceptable C compiler found! Please make sure you have a C compiler installed on your system and/or consider adjusting the CC environment variable if you installed it in a non-standard prefix.
Lo adivinas: NodeJS está escrito usando el lenguaje C++, pero mi sistema carece del compilador correspondiente. Yum al rescate. Como no soy un usuario habitual de CentOS, en realidad tuve que buscar en Internet el nombre exacto del paquete que contenía el compilador de g++. Me lleva a esa página: https://superuser.com/questions/590808/yum-install-gcc-g-doesnt-work-anymore-in-centos-6-4
node]$ sudo yum install gcc-c++ node]$ ./configure --prefix=/opt/node-v8.1.1/ && echo okok
node]$ make -j9 && echo okok
node]$ sudo make install && echo okok
node]$ /opt/node/bin/node --versionv8.1.1
el Éxito. Nuevo.
C. Realizar cambios en el software instalado desde el código fuente
Puede instalar software desde el código fuente porque necesita una versión muy específica que no está disponible en su repositorio de distribución, o porque desea modificar el programa para corregir un error o agregar una característica. Después de todo, el código abierto se trata de hacer modificaciones. Por lo tanto, aprovecharé esta oportunidad para darles una muestra del poder que tienen a mano ahora que son capaces de compilar su propio software.
Aquí, haremos un pequeño cambio en las fuentes de NodeJS. Y veremos si nuestro cambio se incorporará a la versión compilada del software:
Abra el archivonode/src/node.cc
en su editor de texto favorito (vim, nano, gedit,)). Y trata de localizar ese fragmento de código:
if (debug_options.ParseOption(argv, arg)) { // Done, consumed by DebugOptions::ParseOption(). } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) { printf("%s\n", NODE_VERSION); exit(0); } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) { PrintHelp(); exit(0); }
Está alrededor de la línea 3830 del archivo. A continuación, modifique la línea que contiene printf
para que coincida con esa:
printf("%s (compiled by myself)\n", NODE_VERSION);
Luego vuelve a tu terminal. Antes de ir más allá, y para darte más información sobre el poder detrás de git, puedes comprobar si has modificado el archivo correcto:
diff --git a/src/node.cc b/src/node.ccindex bbce1022..a5618b57 100644--- a/src/node.cc+++ b/src/node.cc@@ -3828,7 +3828,7 @@ static void ParseArgs(int* argc, if (debug_options.ParseOption(argv, arg)) { // Done, consumed by DebugOptions::ParseOption(). } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {- printf("%s\n", NODE_VERSION);+ printf("%s (compiled by myself)\n", NODE_VERSION); exit(0); } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) { PrintHelp();
Deberías ver un » — » (signo menos) antes de la línea tal como estaba antes de cambiarla. Y un » + » (signo más) antes de la línea después de los cambios.
Ahora es el momento de recompilar y volver a instalar su software:
make -j9 && sudo make install && echo okok
Esta vez, la única razón por la que podría fallar es que ha cometido un error tipográfico al cambiar el código. Si este es el caso, vuelva a abrir el archivo node/src/node.cc
en su editor de texto y corrija el error.
Una vez que haya logrado compilar e instalar esa nueva versión modificada de NodeJS, podrá verificar si sus modificaciones se incorporaron al software:
:~/node$ /opt/node/bin/node --versionv8.1.1 (compiled by myself)
¡Felicitaciones! ¡Has hecho tu primer cambio a un programa de código abierto!
D. Deje que el shell localice nuestro software de compilación personalizado
Es posible que haya notado que siempre he lanzado mi software NodeJS recién compilado especificando la ruta absoluta al archivo binario.
/opt/node/bin/node
funciona. Pero esto es molesto, por decir lo menos. En realidad, hay dos formas comunes de arreglar eso.
En realidad hay dos formas comunes de solucionar el molesto problema de especificar la ruta absoluta a los archivos binarios, pero para entenderlos primero debe saber que su shell localiza los archivos ejecutables buscándolos solo en los directorios especificados por la variable de entorno PATH.
:~/node$ echo $PATH/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
Aquí, en ese sistema Debian, si no especifica explícitamente ningún directorio como parte de un nombre de comando, el shell buscará primero los programas ejecutables en /usr/local/bin
, luego si no se encuentra en /usr/bin
, luego si no se encuentra en /bin
entonces si no se encuentra en /usr/local/games
entonces si no se encuentra en /usr/games
, entonces si no se encuentra the el shell reportará un error «comando no encontrado».
Dado eso, tenemos dos formas de hacer que un comando sea accesible para el shell: agregándolo a uno de los directorios PATH
ya configurados. O añadiendo el directorio que contiene nuestro archivo ejecutable al PATH
.
Agregar un enlace desde /usr/local/bin
Simplemente copiar el ejecutable binario de nodo de/opt/node/bin
a/usr/local/bin
sería una mala idea, ya que al hacerlo, el programa ejecutable ya no sería capaz de localizar los otros componentes necesarios pertenecientes a/opt/node/
(es una práctica común para el software localizar sus archivos de recursos en relación con su propia ubicación).
Entonces, la forma tradicional de hacerlo es usando un enlace simbólico:
:~/node$ sudo ln -sT /opt/node/bin/node /usr/local/bin/node:~/node$ which -a node || echo not found/usr/local/bin/node:~/node$ node --versionv8.1.1 (compiled by myself)
Esta es una solución simple y efectiva, especialmente si un paquete de software está hecho de solo unos pocos programas ejecutables conocidos, ya que debe crear un enlace simbólico para todos y cada uno de los comandos invocables por el usuario. Por ejemplo, si está familiarizado con NodeJS, también conoce la aplicación complementaria npm
Debería establecer un enlace simbólico desde /usr/local/bin
. Pero te lo permití como un ejercicio.
Modificar la RUTA
Primero, si probó la solución anterior, elimine el enlace simbólico de nodo creado previamente para comenzar desde un estado claro:
:~/node$ sudo rm /usr/local/bin/node:~/node$ which -a node || echo not foundnot found
Y ahora, aquí está el comando mágico para cambiar su PATH
:
:~/node$ export PATH="/opt/node/bin:${PATH}":~/node$ echo $PATH/opt/node/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
Simplemente dije, reemplazé el contenido de la variable de entorno PATH
por su contenido anterior, pero con el prefijo /opt/node/bin
. Por lo tanto, como se puede imaginar ahora, el shell buscará primero en el directorio /opt/node/bin
para los programas ejecutables. Podemos confirmar que usando el comando which
:
:~/node$ which -a node || echo not found/opt/node/bin/node:~/node$ node --versionv8.1.1 (compiled by myself)
Mientras que la solución «link» es permanente tan pronto como haya creado el enlace simbólico en /usr/local/bin
, el PATH
cambia es efectivo solo en el shell actual. Los dejaré para que investiguen cómo hacer cambios en los permanentes PATH
. Como sugerencia, tiene que ver con su «perfil». Si encuentra la solución, no dude en compartirla con los demás lectores utilizando la sección de comentarios a continuación.
E. Cómo eliminar el software recién instalado del código fuente
Dado que nuestro software NodeJS compilado personalizado se encuentra completamente en el directorio /opt/node-v8.1.1
, eliminar ese software no requiere más esfuerzo que usar el comando rm para eliminar ese directorio:
sudo rm -rf /opt/node-v8.1.1
CUIDADO: sudo
y rm -rf
son un cóctel peligroso! Compruebe siempre el comando dos veces antes de pulsar la tecla «enter». No tendrá ningún mensaje de confirmación ni recuperará si elimina el directorio incorrecto
Entonces, si ha modificado su PATH
, tendrá que revertir esos cambios, lo cual no es complicado en absoluto.
Y si ha creado vínculos de /usr/local/bin
usted tendrá que eliminar a todos ellos:
:~/node$ sudo find /usr/local/bin \ -type l \ -ilname "/opt/node/*" \ -print -delete/usr/local/bin/node
Esperar? ¿Dónde estaba el Infierno de la Dependencia?
Como comentario final, si lees sobre compilar tu propio software personalizado, es posible que hayas oído hablar del infierno de las dependencias. Este es un apodo para esa situación molesta en la que antes de poder compilar un software con éxito, primero debe compilar una biblioteca de requisitos previos, que a su vez requiere otra biblioteca que a su vez podría ser incompatible con algún otro software que ya haya instalado.
Parte del trabajo de los mantenedores de paquetes de su distribución es resolver realmente ese infierno de dependencias y asegurarse de que los diversos programas de su sistema utilicen bibliotecas compatibles y se instalen en el orden correcto.
Para este artículo, elegí, a propósito, instalar NodeJS, ya que prácticamente no tiene dependencias. Dije «virtualmente» porque, de hecho, tiene dependencias. Pero el código fuente de esas dependencias está presente en el repositorio de código fuente del proyecto (en el subdirectorio node/deps
), por lo que no tiene que descargarlas e instalarlas manualmente.