Usé Linux un poco en la universidad y estoy familiarizado con los términos. Me desarrollo regularmente en lenguajes .NET, por lo que no soy analfabeto informático.
Dicho esto, realmente no puedo decir que entiendo la mentalidad de "compílelo usted mismo" [CIY] que existe en los círculos * nix. Sé que va a desaparecer, pero aún lo escucho de vez en cuando. Como desarrollador, sé que configurar compiladores y dependencias necesarias es una molestia, por lo que siento que los flujos de trabajo de CIY han ayudado a que * nix sea mucho menos accesible.
¿Qué factores sociales o técnicos condujeron al surgimiento de la mentalidad CIY?
./configure <options>
, luego haga y realice la instalación. Me corté los dientes hace 30 años en servidores AT&T 3B2 con AT&T SysV Unix y Gould iron con UTX. Las cosas eran mucho más difíciles en aquel entonces. Algunos tuvieron los inicios delconfigure
proceso, la mayoría tuvo que editarlos manualmentemakefile(s)
para su sistema en particular.Respuestas:
Muy simple, durante gran parte de la historia de * nix, no había otra opción. Los programas se distribuyeron como tarballs de origen y la única forma que tenía de usarlos era compilar desde el origen. Entonces no es tanto una mentalidad como un mal necesario.
Dicho esto, hay muy buenas razones para compilar cosas usted mismo, ya que luego se compilarán específicamente para su hardware, puede elegir qué opciones habilitar o no y, por lo tanto, puede terminar con un ejecutable ajustado, tal como le gusta. . Sin embargo, eso es obviamente algo que tiene sentido para usuarios expertos y no para personas que solo quieren que una máquina en funcionamiento lea sus correos electrónicos.
Ahora, en el mundo de Linux, las principales distribuciones se han alejado de esto hace muchos años. Muy, muy raramente necesita compilar algo usted mismo en estos días, a menos que esté utilizando una distribución diseñada específicamente para personas a las que les gusta hacer esto como Gentoo. Sin embargo, para la gran mayoría de las distribuciones, su usuario promedio nunca necesitará compilar nada, ya que prácticamente todo lo que necesitará está presente y compilado en los repositorios de su distribución.
Así que esta mentalidad CIY como la llamas esencialmente ha desaparecido. Es posible que todavía esté vivo y funcionando en el mundo UNIX, no tengo experiencia allí, pero en Linux, si está utilizando una distribución popular con un repositorio decente, casi nunca necesitará compilar nada usted mismo.
fuente
Hay algunas causas para esa mentalidad, desde usuarios finales, mantenedores de distribución y proveedores de código / desarrolladores / grupos de proyectos, y todos y cada uno de ellos son perfectamente válidos.
El aspecto de código abierto
Hay algunos que disfrutan sabiendo que están utilizando software gratuito y lo validan eligiendo compilar desde la fuente. Aquí es donde entran en juego cosas como el proyecto / tutorial / guía / libro Linux From Scratch.
El aspecto de optimización y opciones
¿Desea compilar cosas con optimizaciones específicas para su arquitectura de CPU particular? Quizás haya una opción de tiempo de compilación (o parche para crear una) para habilitar o deshabilitar una característica particular que necesita. Ejemplos de esto podrían ser parchear postfix para tener la capacidad de administrar cuotas, o usar una distribución como Gentoo donde puede optar por no usar systemd, u optar específicamente por soportar ogg / theora / vorbis / lo que sea y NO mp3 debido a problemas de licencia o lo que sea.
El aspecto de la arquitectura de la CPU
¿Su lugar de trabajo utiliza máquinas de gama alta que no sean x86 / amd64? El paquete que necesita / desea puede no estar disponible precompilado para su arquitectura de CPU, y mucho menos cualquier distribución que esté ejecutando. De acuerdo, la mayoría de los lugares que ejecutan este tipo de hardware también cuentan con el soporte de IBM, etc. y no van a instalar / compilar cosas de manera involuntaria. Pero, ¿qué pasa si elige uno de una venta excedente, desenterra un viejo iMac con procesador PPC, etc.?
El aspecto de distribución
Las "familias" de distribución, es decir, Debian con Ubuntu, Mint, et al y RedHat con CentOS, Whitebox, Fedora, et al., Usan diferentes formatos de paquete. Y cada versión se entrega con diferentes versiones de biblioteca, etc. Incluso para un simple script de shell de un solo archivo, configurar un archivo Debian .deb adecuado requiere tiempo y esfuerzo. Si escribiste algún software para rascar algo de picor, y quisiste hacerlo gratis y publicarlo en gitlab, tu propio servidor web, lo que sea, preferirías simplemente publicar un archivo genérico .tar.gz de código fuente con instrucciones sobre la construcción o prefieres versiones de paquete para 2 versiones de Debian (estable y de prueba, tal vez antiguamente estable), múltiples versiones de Redhat y Fedora como RPM, un TGZ para Slackware, un perfil de ebuild para Gentoo, etc., etc., etc.
fuente
Como dice @terdon, hoy en día la necesidad de compilar cosas es bastante escasa, especialmente para los usuarios domésticos.
En el pasado, en el mundo de Unix, dependía mucho de las fuentes de compilación, por ejemplo, ya que administraba sistemas Solaris, AIX, Ultrix, Ultrix digital y HP / UX que a veces el proveedor ya no mantenía, o qué implementaciones de los servicios comunes estaban muy por detrás de lo que comúnmente usaban otros Unixes, incluido Linux.
Todavía hay necesidades genuinas de compilar cosas en el presente, ya sea para obtener una pieza de software más oscura u obsoleta que no está en los repositorios, o usar una versión más reciente de un paquete para el que no tiene binarios compatibles, o cuando desea agregar funcionalidad adicional o rara vez, si puede escribir un parche o módulo para ello.
También tuve que compilar software a mano cuando realicé la reingeniería de sistemas para portar a Debian y / o nuevas versiones de Debian que tenían un marco que ya no era compatible con el sistema operativo.
Por ejemplo, en el pasado tuve que compilar a mano los demonios DHCP para tener soporte para (por entonces reciente) cambios de Windows en el protocolo, o para soportar parches específicos para el aprovisionamiento en el mundo de las telecomunicaciones.
Todavía mantengo en mi repositorio local las versiones de FreeRadius compiladas por mí mismo del dev git repo, ya que había una serie de versiones estables que tenían errores (serios) en Debian, y generalmente los correspondientes .debs para Debian / Ubuntu no han sido adecuado para nuestras necesidades.
Y no hace falta decir que a menudo en un momento también tenemos que ejecutar / o compilar cosas escritas por nosotros mismos.
Instalar las dependencias hoy en día no es tan difícil como en el pasado, y algunos softwares incluso tienen archivos de reglas personalizados para algunas distribuciones comunes de Linux que nombran las dependencias para compilar y hacen el trabajo pesado de crear el archivo del paquete con la lista de dependencias incorporada. Instalar dicho paquete desde un repositorio local no es muy diferente de instalar el mismo paquete desde los repositorios oficiales.
fuente
La causa raíz es obviamente la razón técnica: la portabilidad binaria es más difícil que la portabilidad de origen . Fuera de los paquetes de distribución, la mayoría del software gratuito solo está disponible en forma de fuente porque es mucho más conveniente para los autores / mantenedores.
Hasta que las distribuciones de Linux comenzaron a empaquetar la mayoría de las cosas que la gente promedio querría usar, su única opción era obtener la fuente y compilarla para su propio sistema. Los proveedores comerciales de Unix generalmente no incluían cosas que casi todos querían (por ejemplo, un buen shell como GNU
bash
o similar), solo su propia implementaciónsh
y / ocsh
, por lo que necesitabas construir cosas tú mismo si (como administrador del sistema) para proporcionar un entorno agradable de Unix a sus usuarios para uso interactivo.La situación ahora, con la mayoría de las personas siendo el único administrador y el único usuario de la máquina sentada en su escritorio, es muy diferente del modelo tradicional de Unix. Un administrador de sistemas mantuvo el software en el sistema central y en el escritorio de todos. (A menudo, haciendo que las estaciones de trabajo de la gente solo monten NFS
/opt
y/usr/local/
desde el servidor central, e instalen cosas allí)Antes de cosas como .NET y Java, la verdadera portabilidad binaria en diferentes arquitecturas de CPU era imposible. La cultura de Unix evolucionó con la portabilidad de origen como predeterminada por este motivo, con poco esfuerzo incluso para intentar habilitar la portabilidad binaria hasta los esfuerzos recientes de Linux como LSB. Por ejemplo, POSIX ( el principal estándar de Unix) solo intenta estandarizar la portabilidad de origen, incluso en versiones recientes.
Factor cultural relacionado: los primeros comerciales de AT&T Unix venían con código fuente (en cintas). No tenía que construir el sistema desde la fuente, solo estaba allí en caso de que quisiera ver cómo funcionaba realmente algo cuando los documentos no eran suficientes.
No estoy seguro de qué motivó esta decisión, ya que dar a los clientes acceso al código fuente del software comercial es inaudito en estos días. Claramente, hay algunos sesgos culturales tempranos en esta dirección, pero tal vez eso surgió de las raíces de Unix como un sistema operativo portátil escrito principalmente en C (no en lenguaje ensamblador) que podría compilarse para hardware diferente. Creo que muchos sistemas operativos anteriores tenían más de su código escrito en asm para una CPU específica, por lo que la portabilidad a nivel de origen fue uno de los puntos fuertes de Unix. (Puedo estar equivocado sobre esto; no soy un experto en Unix temprano, pero Unix y C están relacionados).
La distribución de software en forma de fuente es, con mucho, la forma más fácil de permitir que las personas lo adapten a cualquier sistema en el que quieran que se ejecute. (Ya sea usuarios finales o personas que lo empaquetan para una distribución de Linux). Si el software ya ha sido empaquetado por / para una distribución, los usuarios finales pueden usarlo.
Pero es demasiado esperar que los autores de la mayoría de los paquetes creen binarios para cada sistema posible. Algunos proyectos importantes proporcionan binarios para algunos casos comunes (especialmente x86 / windows donde el sistema operativo no viene con un entorno de compilación, y el proveedor del sistema operativo ha puesto un gran énfasis en la distribución de instaladores solo binarios).
Hacer que un software se ejecute en un sistema diferente del que utilizó el autor podría incluso requerir algunos pequeños cambios, que son fáciles con la fuente . Un pequeño programa único que alguien escribió para rascarse su propio picor probablemente nunca se haya probado en la mayoría de los sistemas oscuros. Tener la fuente hace posible hacer tales cambios. El autor original podría haber pasado por alto algo o haber escrito intencionalmente menos código portátil porque le ahorró mucho tiempo. Incluso los paquetes principales como Info-ZIP no tenían probadores en todas las plataformas de inmediato, y necesitaban que las personas enviaran sus parches de portabilidad a medida que se descubrían problemas.
(Hay otros tipos de problemas de portabilidad a nivel de origen que solo suceden debido a diferencias en el entorno de compilación, y no son realmente relevantes para el problema aquí. Con la portabilidad binaria al estilo Java, las herramientas automáticas (
autoconf
/auto-make
) y cosas similares comocmake
wouldn no será necesario. Y no tendríamos cosas como algunos sistemas requieren la inclusión de en<netinet/in.h>
lugar de<arpa/inet.h>
forntohl(3)
. (¡Y tal vez no tendríamosntohl()
ni ninguna otra cosa de orden de bytes en primer lugar!)Compilar una vez, ejecutar en cualquier lugar es uno de los principales objetivos de .NET y también de Java, por lo que es justo decir que se han inventado lenguajes completos en un esfuerzo por resolver este problema , y su experiencia de desarrollo es con uno de ellos. Con .NET, su binario se ejecuta en un entorno de tiempo de ejecución portátil (CLR) . Java llama a su entorno de tiempo de ejecución la Máquina virtual Java . Solo necesita distribuir un binario que funcione en cualquier sistema (al menos, cualquier sistema en el que alguien ya haya implementado un JVM o CLR). Todavía puede tener problemas de portabilidad como,
/
vs\
separadores de ruta, o cómo imprimir, o detalles de diseño de GUI, por supuesto.Una gran cantidad de software está escrito en idiomas que están completamente compilados en código nativo . No hay
.net
código de bytes o Java, solo código de máquina nativo para la CPU en la que se ejecutará, almacenado en un formato de archivo ejecutable no portátil. C y C ++ son los principales ejemplos de esto, especialmente en el mundo de Unix. Obviamente, esto significa que se debe compilar un binario para una arquitectura de CPU específica.Las versiones de la biblioteca son otro problema . Las bibliotecas pueden y a menudo mantienen estable la API de nivel fuente mientras cambian la ABI de nivel binario. (Consulte Diferencia entre API y ABI ). Por ejemplo, agregar otro miembro a un opaco
struct
todavía cambia su tamaño y requiere una recompilación con encabezados para la nueva versión de la biblioteca para cualquier código que asigne espacio para dicha estructura, ya sea dinámico (malloc ), estático (global) o automático (local en la pila).Los sistemas operativos también son importantes . Un sabor diferente de Unix para la misma arquitectura de CPU puede tener diferentes formatos de archivo binario, un ABI diferente para hacer llamadas al sistema, y diferentes valores numéricos de las constantes como
fopen(3)
'sO_RDONLY
,O_APPEND
,O_TRUNC
.Tenga en cuenta que incluso un binario vinculado dinámicamente todavía tiene algún código de inicio específico del sistema operativo que se ejecuta antes
main()
. En Windows, esto escrt0
. Unix y Linux tienen lo mismo, donde algunos códigos de inicio de C-Runtime están vinculados estáticamente en cada binario. Supongo que, en teoría, podría diseñar un sistema donde ese código también se vincule dinámicamente, y sea parte de libc o del enlazador dinámico en sí, pero no es así como funcionan las cosas en la práctica en cualquier sistema operativo que conozca. Eso solo resolvería el problema ABI de llamada al sistema, no el problema de los valores numéricos para las constantes de las funciones de la biblioteca estándar. (Normalmente, las llamadas al sistema se realizan a través de las funciones de contenedor libc: un binario Linux x86-64 normal para la fuente que usammap()
no incluirá lasyscall
instrucción, solo uncall
instrucción para la función de contenedor libc del mismo nombre.Esto es parte de por qué no puede simplemente ejecutar binarios i386-FreeBSD en i386-Linux. (Durante un tiempo, el kernel de Linux tenía una capa de compatibilidad de llamadas al sistema. Creo que al menos uno de los BSD puede ejecutar binarios de Linux, con una capa de compatibilidad similar, pero por supuesto necesita bibliotecas de Linux).
Si quisiera distribuir binarios, necesitaría hacer uno separado para cada combinación de CPU / OS-flavour + versión / instalado-biblioteca-versiones .
En los años 80 y 90, había muchos tipos diferentes de CPU de uso común para sistemas Unix (MIPS, SPARC, POWER, PA-RISC, m68k, etc.), y muchos sabores diferentes de Unix (IRIX, SunOS, Solaris, AIX, HP-UX, BSD, etc.).
Y eso es solo sistemas Unix . Muchos paquetes fuente también compilan y funcionan en otros sistemas, como VAX / VMS, MacOS (m68k y PPC), Amiga, PC / MS-DOS, Atari ST, etc.
Todavía hay muchas arquitecturas de CPU y sistemas operativos, aunque ahora la gran mayoría de los equipos de escritorio son x86 con uno de los tres sistemas operativos principales.
Por lo tanto, ya hay más combinaciones de CPU / OS de las que puede sacudir, incluso antes de comenzar a pensar en las dependencias de bibliotecas de terceros que pueden estar en diferentes versiones en diferentes sistemas. (Todo lo que no esté empaquetado por el proveedor del sistema operativo debería instalarse a mano).
Cualquier ruta que se compila en el binario también es específica del sistema. (Esto ahorra RAM y tiempo en comparación con leerlos desde un archivo de configuración al inicio). Los sistemas Unix de la vieja escuela generalmente tenían muchas cosas personalizadas a mano, por lo que no hay forma de que puedas hacer suposiciones válidas sobre qué es dónde.
La distribución de binarios era totalmente inviable para la Unix de la vieja escuela, excepto para los grandes proyectos comerciales que pueden permitirse construir y probar todas las combinaciones principales .
Incluso hacer binarios para justos
i386-linux-gnu
yamd64-linux-gnu
es difícil. Se ha dedicado mucho tiempo y esfuerzo a cosas como Linux Standard Base para hacer posibles los archivos binarios portátiles . Incluso la vinculación estática de binarios no resuelve todo. (p. ej., ¿cómo debería imprimirse un programa de procesamiento de texto en un sistema RedHat frente a un sistema Debian? ¿Cómo debería la instalación agregar un usuario o grupo para un demonio y organizar su script de inicio para que se ejecute después de cada reinicio?) ejemplos, porque recompilar desde la fuente no los resuelve.Además de todo eso, en el pasado la memoria era más preciosa de lo que es ahora. Dejar de lado las características opcionales en tiempo de compilación puede crear binarios más pequeños (menos tamaño de código) que también usan menos memoria para sus estructuras de datos. Si una característica requirió un miembro adicional en cada instancia de un determinado
class
ostruct
para rastrear algo, deshabilitar esa característica reducirá el objeto en 4 bytes (por ejemplo), lo cual es bueno si es un objeto al que el programa asigna 100k.Las características de tiempo de compilación opcionales actualmente se usan con mayor frecuencia para hacer que las bibliotecas adicionales sean opcionales. por ejemplo, puede compilar
ffmpeg
con o sinlibx264
,libx265
,libvorbis
, y muchas otras bibliotecas de vídeo específico / codificadores de audio, el manejo de los subtítulos, etc. etc. Más comúnmente, muchas cosas pueden ser compilados con o sinlibreadline
: si está disponible cuando se ejecuta./configure
, el El binario resultante dependerá de la biblioteca y proporcionará una edición de línea elegante al leer desde un terminal. Si no es así, entonces el programa utilizará algún soporte alternativo para simplemente leer líneas del stdin confgets()
o algo así).Algunos proyectos aún usan características opcionales para omitir el código innecesario por razones de rendimiento. por ejemplo, el kernel de Linux en sí mismo puede construirse sin compatibilidad con SMP (por ejemplo, para un sistema integrado o un escritorio antiguo), en cuyo caso gran parte del bloqueo es más simple. O con muchas otras características opcionales que afectan parte del código central, no solo omitiendo controladores u otras características de hardware. (Aunque las opciones de configuración específicas del arco y del hardware representan una gran parte del código fuente total. Consulte ¿Por qué el kernel de Linux tiene más de 15 millones de líneas de código? )
fuente