Eu usei o Linux um pouco na faculdade e estou familiarizado com os termos. Eu desenvolvo em linguagens .NET regularmente, por isso não sou analfabeto do computador.
Dito isto, eu realmente não posso dizer que entendo a mentalidade "compile você mesmo" [CIY] que existe nos círculos * nix. Eu sei que está indo embora, mas ainda ouço de vez em quando. Como desenvolvedor, sei que configurar compiladores e dependências necessárias é um problema, então sinto que os fluxos de trabalho da CIY ajudaram a tornar o * nix muito menos acessível.
Quais fatores sociais ou técnicos levaram ao surgimento da mentalidade do CIY?
./configure <options>
e faça e instale. Eu cortei meus dentes há 30 anos nos servidores AT&T 3B2 executando o AT&T SysV Unix e o ferro Gould executando o UTX. As coisas estavam muito mais difíceis naquela época. Alguns tiveram o início doconfigure
processo, a maioria dos quais você teve que editar manualmentemakefile(s)
para seu sistema específico.Respostas:
Muito simplesmente, durante grande parte da história do * nix, não havia outra escolha. Os programas foram distribuídos como tarballs de origem e a única maneira de usá-los era compilar a partir do código-fonte. Portanto, não é tanto uma mentalidade, mas um mal necessário.
Dito isso, existem boas razões para compilar as coisas você mesmo, pois elas serão compiladas especificamente para o seu hardware, você pode escolher quais opções ativar ou não e, portanto, pode acabar com um executável ajustado da maneira que desejar. . Isso, no entanto, obviamente é apenas algo que faz sentido para usuários experientes e não para pessoas que desejam apenas uma máquina em funcionamento para ler seus e-mails.
Agora, no mundo Linux, as principais distribuições se afastaram disso há muitos anos. Atualmente, você muito, muito raramente precisa compilar qualquer coisa, a menos que esteja usando uma distribuição projetada especificamente para pessoas que gostam de fazer isso como o Gentoo. Para a grande maioria das distribuições, no entanto, o usuário médio nunca precisará compilar nada, pois praticamente tudo o que eles precisam está presente e compilado nos repositórios da distribuição.
Portanto, essa mentalidade CIY, como você chama, desapareceu essencialmente. Pode ainda estar vivo e chutando no mundo UNIX, não tenho experiência lá, mas no Linux, se você estiver usando uma distribuição popular com um repositório decente, quase nunca precisará compilar nada.
fonte
Existem algumas causas para essa mentalidade, de usuários finais, mantenedores de distribuição e grupos de fornecedores / desenvolvedores / projetos de código, e cada um deles é perfeitamente válido.
O aspecto de código aberto
Há quem goste de saber que está usando o software livre e o valida escolhendo compilar a partir do código-fonte. É aí que entram coisas como o projeto / howto / guia / livro do Linux From Scratch.
O aspecto de otimização e opções
Deseja compilar coisas com otimizações específicas para sua arquitetura de CPU específica? Talvez haja uma opção de tempo de compilação (ou correção para criar uma) para ativar ou desativar um recurso específico que você precisa. Exemplos disso podem ser o patchfix do patchfix para ter a capacidade de gerenciar cotas, ou usar uma distribuição como o Gentoo, na qual você pode optar por não usar o systemd ou, especificamente, oferecer suporte ao ogg / theora / vorbis / Whatever e NOT mp3 devido a problemas de licenciamento como queiras.
O aspecto da arquitetura da CPU
Seu local de trabalho usa máquinas de ponta não-x86 / amd64? O pacote que você precisa / deseja pode não estar disponível pré-compilado para sua arquitetura de CPU, muito menos em qualquer distribuição que você esteja executando. É verdade que a maioria dos locais que executam esse tipo de hardware também é suportada pela IBM etc., e não instala / compila coisas à vontade. Mas e se você escolher um de uma venda excedente, desenterrar um antigo iMac com processador PPC, etc.?
O aspecto Distribuição
"Famílias" de distribuição - isto é, Debian com Ubuntu, Mint, et al e RedHat com CentOS, Whitebox, Fedora, et al - usam formatos de pacotes diferentes. E cada versão é fornecida com diferentes versões da biblioteca, etc. Mesmo para um simples script de shell de arquivo único, a configuração de um arquivo Debian .deb adequado leva tempo e esforço. Se você escreveu algum software para coçar um pouco de coceira e queria torná-lo gratuito e publicá-lo no gitlab, seu próprio servidor web, o que seja, você prefere publicar um arquivo .tar.gz genérico da fonte com instruções de construção ou prefere empacote versões para 2 versões do Debian (stable e testing, talvez oldstable), várias versões do Redhat e Fedora como RPMs, um TGZ para Slackware, um perfil ebuild para o Gentoo, etc. etc. etc.
fonte
Como diz @terdon, hoje em dia a necessidade de compilar as coisas é muito pequena, especialmente para usuários domésticos.
No passado, no mundo Unix, eu era altamente dependente de compilar fontes, por exemplo, enquanto gerenciava os sistemas Solaris, AIX, Ultrix, Digital Ultrix e HP / UX que às vezes não eram mais mantidos pelo fornecedor ou quais implementações dos serviços comuns estavam muito atrás do que era comumente usado por outros Unixes, incluindo o Linux.
Ainda existem necessidades genuínas de compilar coisas no presente, para obter algum software mais obscuro ou obsoleto que não esteja nos repositórios ou usar uma versão mais recente de um pacote para o qual você não possui binários compatíveis ou quando você deseja adicionar funcionalidade extra ou raramente, se conseguir escrever um patch ou módulo para ele.
Eu também tive que compilar o software manualmente ao fazer a reengenharia de sistemas para portar para o Debian e / ou novas versões do Debian que tinham uma estrutura que não era mais suportada pelo sistema operacional.
Por exemplo, no passado, eu tive que compilar manualmente os daemons DHCP para ter suporte (até então recente) para alterações no protocolo do Windows ou para oferecer suporte a patches específicos para provisionamento no mundo das telecomunicações.
Eu ainda mantenho no meu repositório local as debs para versões do FreeRadius compiladas por mim no repositório dev git, pois havia uma série de versões estáveis que apresentavam bugs (sérios) no Debian e, geralmente, os .debs correspondentes para o Debian / Ubuntu não foram adequado às nossas necessidades.
E nem é preciso dizer que, de vez em quando, também precisamos executar / ou compilar coisas escritas por nós mesmos.
Instalar as dependências hoje em dia não é tão difícil quanto no passado, e alguns softwares ainda têm arquivos de regras customizados para algumas distribuições comuns do Linux que nomeiam as dependências a serem compiladas e fazem o trabalho pesado de criar o arquivo de pacote com a lista de dependências incorporadas. Instalar um pacote desse tipo a partir de um repositório local não é muito diferente de instalar o mesmo pacote dos repositórios oficiais.
fonte
A causa raiz é obviamente a razão técnica: a portabilidade binária é mais difícil que a portabilidade de origem . Fora dos pacotes de distribuição, a maioria dos softwares livres ainda está disponível apenas na forma de código-fonte, porque é muito mais conveniente para o (s) autor (es) / mantenedor (es).
Até as distribuições Linux começarem a empacotar a maioria das coisas que as pessoas comuns gostariam de usar, sua única opção era obter a fonte e compilá-la para seu próprio sistema. Os fornecedores comerciais do Unix geralmente não incluíam coisas que quase todo mundo queria (por exemplo, um bom shell como o GNU
bash
ou similar), apenas sua própria implementaçãosh
e / oucsh
, então você precisava criar as coisas sozinho, se quisesse (como administrador de sistemas) para fornecer um ambiente Unix agradável aos seus usuários para uso interativo.A situação agora, com a maioria das pessoas sendo o único administrador e o único usuário da máquina em sua área de trabalho, é muito diferente do modelo tradicional do Unix. Um administrador de sistema mantinha o software no sistema central e na área de trabalho de todos. (Muitas vezes, tendo as estações de trabalho das pessoas apenas montadas em NFS
/opt
e a/usr/local/
partir do servidor central e instalando coisas lá.)Antes de coisas como .NET e Java, a verdadeira portabilidade binária em diferentes arquiteturas de CPU era impossível. A cultura Unix evoluiu com portabilidade de origem como padrão por esse motivo, com pouco esforço para tentar habilitar a portabilidade binária até esforços recentes do Linux como o LSB. Por exemplo, o POSIX ( o principal padrão Unix) tenta apenas padronizar a portabilidade de origem, mesmo em versões recentes.
Fator cultural relacionado: Os primeiros comerciais da AT&T Unix vieram com código-fonte (em fitas). Você não precisava criar o sistema a partir da fonte, ele estava lá para o caso de você querer ver como algo realmente funcionava quando os documentos não eram suficientes.
Não sei ao certo o que motivou essa decisão, já que é inédito nos dias de hoje oferecer aos clientes o código-fonte do software comercial. Existem claramente alguns preconceitos culturais nessa direção, mas talvez isso tenha surgido das raízes do Unix como um sistema operacional portátil escrito principalmente em C (não na linguagem assembly) que poderia ser compilado para diferentes hardwares. Eu acho que muitos sistemas operacionais anteriores tinham mais de seu código escrito em asm para uma CPU específica, portanto a portabilidade no nível da fonte foi um dos pontos fortes do Unix. (Eu posso estar errado sobre isso; não sou especialista no Unix inicial, mas Unix e C estão relacionados.)
A distribuição de software na forma de origem é, de longe, a maneira mais fácil de permitir que as pessoas o adaptem a qualquer sistema em que desejam que ele seja executado. (Usuários finais ou pessoas que o empacotam para uma distribuição Linux). Se o software já foi empacotado por / para uma distribuição, os usuários finais podem apenas usá-lo.
Mas é demais esperar que os autores da maioria dos pacotes façam binários para cada sistema possível. Alguns projetos importantes fornecem binários para alguns casos comuns (especialmente x86 / windows em que o sistema operacional não vem com um ambiente de construção e o fornecedor do sistema operacional enfatiza bastante a distribuição de instaladores apenas binários).
Conseguir que um software seja executado em um sistema diferente daquele usado pelo autor pode exigir algumas pequenas alterações, que são fáceis com a fonte . Um pequeno programa único que alguém escreveu para coçar sua própria coceira provavelmente nunca foi testado na maioria dos sistemas obscuros. Ter a fonte torna possível fazer essas alterações. O autor original pode ter esquecido algo ou intencionalmente escreveu um código menos portátil, porque economizou muito tempo. Mesmo grandes pacotes como o Info-ZIP não tinham testadores em todas as plataformas imediatamente e precisavam de pessoas para enviar seus patches de portabilidade à medida que os problemas fossem descobertos.
(Existem outros tipos de problemas de portabilidade de nível de fonte que só acontecem por causa de diferenças na construção env, e não são realmente relevantes para a questão aqui. Com Java-style portabilidade binária, auto-ferramentas (
autoconf
/auto-make
) e coisas semelhantes, comocmake
wouldn E não teríamos coisas que alguns sistemas exigem a inclusão de, em<netinet/in.h>
vez de<arpa/inet.h>
parantohl(3)
(e talvez não tivéssemosntohl()
ou qualquer outra coisa de ordem de bytes em primeiro lugar!)Compilar uma vez, executar em qualquer lugar é um dos principais objetivos do .NET e também do Java; portanto, é justo dizer que linguagens inteiras foram inventadas em um esforço para resolver esse problema , e sua experiência com o desenvolvedor é com uma delas. Com o .NET, seu binário é executado em um ambiente de tempo de execução portátil (CLR) . Java chama seu ambiente de tempo de execução de Java Virtual Machine . Você só precisa distribuir um binário que funcione em qualquer sistema (pelo menos, qualquer sistema em que alguém já tenha implementado uma JVM ou CLR). Você ainda pode ter problemas de portabilidade, como
/
vs\
separadores de caminho, ou como imprimir, ou detalhes de layout da GUI, é claro.Muitos softwares são escritos em idiomas totalmente compilados no código nativo . Não há
.net
bytecode ou java, apenas código de máquina nativo para a CPU em que será executado, armazenado em um formato de arquivo executável não portátil. C e C ++ são os principais exemplos disso, especialmente no mundo Unix. Obviamente, isso significa que um binário precisa ser compilado para uma arquitetura específica da CPU.As versões da biblioteca são outro problema . As bibliotecas podem e muitas vezes mantêm a API no nível de origem estável ao alterar a ABI no nível binário. (Consulte Diferença entre API e ABI .) Por exemplo, adicionar outro membro a um opaco
struct
ainda muda de tamanho e requer uma recompilação com cabeçalhos para a nova versão da biblioteca para qualquer código que aloque espaço para essa estrutura, seja ela dinâmica (malloc ), estático (global) ou automático (local na pilha).Os sistemas operacionais também são importantes . Um sabor diferente de Unix para a mesma arquitetura de CPU pode ter diferentes formatos de arquivos binários, a ABI diferente para fazer chamadas de sistema e valores numéricos diferentes para constantes como
fopen(3)
'sO_RDONLY
,O_APPEND
,O_TRUNC
.Observe que mesmo um binário vinculado dinamicamente ainda possui algum código de inicialização específico do SO que é executado anteriormente
main()
. No Windows, é issocrt0
. Unix e Linux têm a mesma coisa, onde algum código de inicialização do C-Runtime está estaticamente vinculado a todos os binários. Eu acho que, em teoria, você poderia projetar um sistema em que esse código também fosse dinamicamente vinculado, e parte da libc ou do próprio vinculador dinâmico, mas não é assim que as coisas funcionam na prática em qualquer sistema operacional que eu conheça. Isso resolveria apenas o problema de ABI da chamada de sistema, não o problema de valores numéricos para constantes para funções de biblioteca padrão. (Normalmente, as chamadas do sistema são feitas através das funções do invólucro libc: Um binário x86-64 Linux normal para a fonte que usammap()
não inclui asyscall
instrução, apenas umcall
instruções para a função wrapper libc com o mesmo nome.Isso é parte do motivo pelo qual você não pode simplesmente executar os binários do i386-FreeBSD no i386-Linux. (Por um tempo, o kernel do Linux tinha uma camada de compatibilidade de chamada do sistema. Acho que pelo menos um dos BSDs pode executar binários do Linux, com uma camada compatível semelhante, mas é claro que você precisa de bibliotecas do Linux.)
Se você quisesse distribuir binários, seria necessário criar um separado para cada combinação de CPU / OS-sabor + versão / versão-biblioteca-instalada .
Nos anos 80/90, havia muitos tipos diferentes de CPU em uso comum para sistemas Unix (MIPS, SPARC, POWER, PA-RISC, m68k etc.) e muitos tipos diferentes de Unix (IRIX, SunOS, Solaris, AIX, HP-UX, BSD etc.).
E isso é apenas sistemas Unix . Muitos pacotes de código-fonte também compilariam e funcionariam em outros sistemas, como VAX / VMS, MacOS (m68k e PPC), Amiga, PC / MS-DOS, Atari ST, etc.
Ainda existem muitas arquiteturas de CPU e sistemas operacionais, embora agora a grande maioria dos desktops esteja x86 executando um dos três principais sistemas operacionais.
Portanto, já há mais combinações de CPU / OS do que você pode imaginar, mesmo antes de começar a pensar nas dependências de bibliotecas de terceiros que podem estar em versões diferentes em sistemas diferentes. (Qualquer coisa que não seja fornecida pelo fornecedor do SO deve ser instalada manualmente.)
Todos os caminhos que são compilados no binário também são específicos do sistema. (Isso economiza RAM e tempo em comparação com a leitura de um arquivo de configuração na inicialização). Os sistemas Unix da velha escola geralmente tinham muitas coisas personalizadas à mão, então não há como você fazer suposições válidas sobre o que é onde.
A distribuição de binários era totalmente inviável para o Unix da velha escola, exceto para os principais projetos comerciais que podem se dar ao luxo de construir e testar todas as principais combinações .
Mesmo fazendo binários por apenas
i386-linux-gnu
eamd64-linux-gnu
é difícil. Muito tempo e esforço foram gastos em coisas como a Linux Standard Base para possibilitar binários portáteis . Mesmo binários vinculados estaticamente não resolvem tudo. (por exemplo, como um programa de processamento de texto deve ser impresso em um sistema RedHat vs. um sistema Debian? Como a instalação deve adicionar um usuário ou grupo para um daemon e organizar seu script de inicialização após cada reinicialização?) exemplos, porque a recompilação a partir da fonte não os resolve.Além de tudo isso, antigamente a memória era mais preciosa do que é agora. Deixar de lado os recursos opcionais em tempo de compilação pode criar binários menores (menos tamanho de código) que também usam menos memória para suas estruturas de dados. Se um recurso exigir um membro extra em todas as instâncias de um determinado item
class
oustruct
rastrear algo, a desativação desse recurso reduzirá o objeto em 4 bytes (por exemplo), o que é bom se for um objeto ao qual o programa aloca 100k.Atualmente, os recursos opcionais em tempo de compilação são usados com mais frequência para tornar opcionais bibliotecas extras. por exemplo, você pode compilar
ffmpeg
com ou semlibx264
,libx265
,libvorbis
, e muitas outras bibliotecas para vídeo específico / codificadores de áudio, a manipulação das legendas, etc. etc. Mais comumente, um monte de coisas podem ser compilados com ou semlibreadline
: se estiver disponível quando você executa./configure
, o O binário resultante dependerá da biblioteca e fornecerá edição de linha sofisticada ao ler de um terminal. Caso contrário, o programa usará algum suporte de fallback para ler apenas linhas do stdin comfgets()
algo assim.)Alguns projetos ainda usam recursos opcionais para omitir códigos desnecessários por motivos de desempenho. por exemplo, o próprio kernel do Linux pode ser construído sem o suporte a SMP (por exemplo, para um sistema incorporado ou uma área de trabalho antiga); nesse caso, grande parte do bloqueio é mais simples. Ou com muitos outros recursos opcionais que afetam parte do código principal, não apenas deixando de fora os drivers ou outros recursos de hardware. (Embora as opções de configuração específicas do arco e do hardware sejam responsáveis por grande parte do código fonte total. Consulte Por que o kernel do Linux tem mais de 15 milhões de linhas de código? )
fonte