Como instalar o software do código-fonte ... e removê-lo depois

Resumo: Este guia detalhado explica como instalar um programa a partir do código-fonte no Linux e como remover o software instalado do código-fonte.

Um dos maiores pontos fortes de sua distribuição Linux é seu gerenciador de pacotes e o repositório de software associado. Com eles, você tem todas as ferramentas e recursos necessários para baixar e instalar um novo software em seu computador de forma totalmente automatizada.

Mas, apesar de todos os seus esforços, os mantenedores do pacote não podem lidar com todos os casos de uso. Nem podem empacotar todo o software disponível lá fora. Portanto, ainda existem situações em que você terá que compilar e instalar um novo software sozinho. Quanto a mim, o motivo mais comum, de longe, de ter que compilar algum software é quando preciso rodar uma versão muito específica. Ou porque quero modificar o código-fonte ou usar algumas opções de compilação sofisticadas.

Se suas necessidades pertencem a essa última categoria, é possível que você já saiba o que faz. Mas para a grande maioria dos usuários do Linux, compilar e instalar um software a partir das fontes pela primeira vez pode parecer uma cerimônia de iniciação: um tanto assustador; mas com a promessa de entrar em um novo mundo de possibilidades e de fazer parte de uma comunidade privilegiada se você superar isso.

Leitura sugerida como instalar e remover software no Ubuntu [guia completo]

A. Instalação de software a partir do código-fonte no Linux

E é exatamente isso que faremos aqui. Para o propósito desse artigo, digamos que eu preciso instalar NodeJS 8.1.1 no meu sistema. Essa versão exatamente. Uma versão que não está disponível no repositório 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

Etapa 1: obter o código-fonte do GitHub

Como muitos projetos de código aberto, as fontes do NodeJS podem ser encontradas no GitHub: https://github.com/nodejs/node

Então, vamos direto para lá.

Se você não estiver familiarizado com GitHub, git ou qualquer outro sistema de controle de versão vale a pena mencionar que o repositório contém a fonte atual do software, bem como um histórico de todas as modificações feitas ao longo dos anos nesse software. Eventualmente, até a primeira linha escrita para esse projeto. Para os desenvolvedores, manter esse histórico tem muitas vantagens. Para nós hoje, o principal é que seremos capazes de obter os fontes do projeto como estavam em qualquer momento. Mais precisamente, poderei obter os códigos-fonte como estavam quando a versão 8.1.1 que desejo foi lançada. Mesmo que tenha havido muitas modificações desde então.

No GitHub, você pode usar o botão “branch” para navegar entre as diferentes versões do software. “Branch” e “tags” são conceitos relacionados no Git. Basicamente, os desenvolvedores criam “branch” e “tags” para acompanhar eventos importantes no histórico do projeto, como quando começam a trabalhar em um novo recurso ou quando publicam um lançamento. Não vou entrar em detalhes aqui, tudo o que você precisa saber é que estou procurando a versão Marcado “V8.1.1”

Depois de ter escolhido a tag “v8.1.1”, a página é atualizada, a mudança mais óbvia sendo a tag agora aparece como parte da URL. Além disso, você notará que a data de alteração do arquivo também é diferente. A árvore de origem que você está vendo agora é a que existia no momento em que a tag v8.1.1 foi criada. Em certo sentido, você pode pensar em uma ferramenta de controle de versão como o git como uma máquina de viagem no tempo, permitindo que você volte e avance na história do projeto.

Neste ponto, podemos baixar as fontes do NodeJS 8.1.1. Você não pode perder o grande botão azul sugerindo baixar o arquivo ZIP do projeto. Como eu mesmo, irei baixar e extrair o ZIP da linha de comando para fins de explicação. Mas se você preferir usar um GUI ferramenta, não hesite em fazer isso:

wget https://github.com/nodejs/node/archive/v8.1.1.zip
unzip v8.1.1.zip
cd node-8.1.1/

Baixar o arquivo ZIP funciona muito bem. Mas se você quiser fazer isso "como um profissional", sugiro usar diretamente o git ferramenta para baixar as fontes. Não é nada complicado - e será um bom primeiro contato com uma ferramenta que você encontrará com frequência:

# first ensure git is installed on your system
sh$ sudo apt-get install git
# Make a shallow clone the NodeJS repository at v8.1.1
sh$ git clone --depth 1 
              --branch v8.1.1 
              https://github.com/nodejs/node
sh$ cd node/

A propósito, se você tiver algum problema, considere a primeira parte deste artigo como uma introdução geral. Posteriormente, tenho explicações mais detalhadas para as distribuições baseadas em Debian e ReadHat para ajudá-lo a solucionar problemas comuns.

De qualquer forma, sempre que você baixou a fonte usando git ou como um arquivo ZIP, agora você deve ter exatamente os mesmos arquivos de origem no diretório atual:

sh$ ls
android-configure  BUILDING.md            common.gypi      doc            Makefile   src
AUTHORS            CHANGELOG.md           configure        GOVERNANCE.md  node.gyp   test
benchmark          CODE_OF_CONDUCT.md     CONTRIBUTING.md  lib            node.gypi  tools
BSDmakefile        COLLABORATOR_GUIDE.md  deps             LICENSE        README.md  vcbuild.bat

Etapa 2: Compreendendo o Build System do programa

Normalmente falamos sobre “compilar as fontes”, mas a compilação é apenas uma das fases necessárias para produzir um software funcional a partir de sua fonte. Um sistema de construção é um conjunto de ferramentas e práticas usadas para automatizar e articular essas diferentes tarefas para construir inteiramente o software apenas emitindo alguns comandos.

Se o conceito é simples, a realidade é um pouco mais complicada. Porque diferentes projetos ou linguagens de programação podem ter diferentes requisitos. Ou por causa dos gostos do programador. Ou as plataformas suportadas. Ou por motivos históricos. Ou… ou .. há uma lista quase infinita de razões para escolher ou criar outro sistema de compilação. Tudo isso para dizer que existem muitas soluções diferentes usadas por aí.

NodeJS usa um Sistema de construção estilo GNU. Esta é uma escolha popular na comunidade de código aberto. E mais uma vez, uma boa maneira de começar sua jornada.

Escrever e ajustar um sistema de construção é uma tarefa bastante complexa. Mas para o “usuário final”, os sistemas de construção no estilo GNU resumem-se ao uso de duas ferramentas: configure e make.

A configure file é um script específico do projeto que irá verificar a configuração do sistema de destino e recursos disponíveis para garantir que o projeto possa ser construído, eventualmente atendendo às especificidades da plataforma atual.

Uma parte importante de um típico configure trabalho é construir o Makefile. Esse é o arquivo que contém as instruções necessárias para construir efetivamente o projeto.

A make ferramenta), por outro lado, é uma ferramenta POSIX disponível em qualquer sistema semelhante ao Unix. Irá ler o específico do projeto Makefile e execute as operações necessárias para construir e instalar seu programa.

Mas, como sempre no mundo Linux, você ainda tem alguma latência para personalizar a compilação para suas necessidades específicas.

./configure --help

A configure -help comando irá mostrar-lhe todas as opções de configuração disponíveis. Mais uma vez, isso é muito específico do projeto. E para ser honesto, às vezes é necessário se aprofundar no projeto antes de entender completamente o significado de cada opção de configuração.

Mas há pelo menos uma opção GNU Autotools padrão que você deve saber: o --prefix opção. Isso tem a ver com a hierarquia do sistema de arquivos e o local em que o software será instalado.

Sugestão de read8 Vim dicas e truques que o tornarão um usuário profissional

Etapa 3: O FHS

A hierarquia do sistema de arquivos Linux em uma distribuição típica obedece principalmente aos Padrão de hierarquia do sistema de arquivos (FHS)

Esse padrão explica a finalidade dos vários diretórios do seu sistema: /usr, /tmp, /var e assim por diante.

Ao usar o GNU Autotools - e a maioria dos outros sistemas de compilação - o local de instalação padrão para o seu novo software será /usr/local. O que é uma boa escolha de acordo com o FSH “A hierarquia / usr / local deve ser usada pelo administrador do sistema ao instalar o software localmente? Ele precisa estar protegido contra sobrescritos quando o software do sistema for atualizado. Pode ser usado para programas e dados compartilháveis ​​entre um grupo de hosts, mas não encontrados em / usr. ”

A /usr/local hierarquia de alguma forma replica o diretório raiz, e você vai encontrar lá /usr/local/bin para os programas executáveis, /usr/local/lib para as bibliotecas, /usr/local/share para arquivos independentes de arquitetura e assim por diante.

O único problema ao usar o /usr/local árvore para instalação de software personalizado é que os arquivos de todo o seu software serão misturados lá. Especialmente, depois de instalar alguns softwares, será difícil rastrear qual arquivo exatamente /usr/local/bin e /usr/local/lib pertence a qual software. Isso não vai causar nenhum problema ao sistema. Depois de tudo, /usr/bin é quase a mesma bagunça. Mas isso se tornará um problema no dia em que você quiser remover um software instalado manualmente.

Para resolver esse problema, geralmente prefiro instalar software personalizado no /opt em vez disso, subárvore. Mais uma vez, para citar a ESF:

_ ”/ Opt é reservado para a instalação de pacotes de software de aplicativos adicionais.

Um pacote a ser instalado em / opt deve localizar seus arquivos estáticos em um / opt / separado ou / opt / árvore de diretórios, onde é um nome que descreve o pacote de software e é o nome registrado do provedor LANANA. ”_

Então, vamos criar um subdiretório de /opt especificamente para nossa instalação personalizada do NodeJS. E se algum dia eu quiser remover esse software, simplesmente terei que remover esse diretório:

sh$ sudo mkdir /opt/node-v8.1.1
sh$ 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.1
sh$ 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.

Qualquer coisa menos "ok" após o make O comando foi concluído significa que ocorreu um erro durante o processo de construção. Como executamos uma construção paralela por causa do -j opção, nem sempre é fácil recuperar a mensagem de erro devido ao grande volume de saída produzido pelo sistema de compilação.

No caso de problema, basta reiniciar make, mas sem o -j opção desta vez. E o erro deve aparecer próximo ao final da saída:

sh$ make

Finalmente, uma vez que a compilação tenha chegado ao final, você pode instalar o software em seu local executando o comando:

sh$ sudo make install

E teste:

sh$ /opt/node/bin/node --version
v8.1.1

B. E se as coisas derem errado durante a instalação do código-fonte?

O que eu expliquei acima é principalmente o que você pode ver na página de “instruções de construção” de um projeto bem documentado. Mas, dado que o objetivo deste artigo é permitir que você compile seu primeiro software a partir de fontes, pode valer a pena investigar alguns problemas comuns. Portanto, farei todo o procedimento novamente, mas desta vez de um sistema Debian 9.0 e CentOS 7.0 novo e mínimo. Assim, você pode ver o erro que encontrei e como os resolvi.

Do Debian 9.0 “Stretch”

[email protected]:~$ git clone --depth 1 
                             --branch v8.1.1 
                             https://github.com/nodejs/node
-bash: git: command not found

Este problema é bastante fácil de diagnosticar e resolver. Basta instalar o git pacote:

[email protected]:~$ sudo apt-get install git
[email protected]:~$ git clone --depth 1 
                             --branch v8.1.1 
                             https://github.com/nodejs/node && echo ok
[...]
ok
[email protected]:~/node$ sudo mkdir /opt/node-v8.1.1
[email protected]:~/node$ sudo ln -sT node-v8.1.1 /opt/node

Nenhum problema aqui.

[email protected]:~/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 um projeto, você precisa de um compilador. NodeJS sendo escrito usando o Linguagem C ++, precisamos de um C ++ compilador. Aqui, instalarei o `g ++`, o compilador GNU C ++ para esse propósito:

[email protected]:~/node$ sudo apt-get install g++
[email protected]:~/node$ ./configure --prefix=/opt/node-v8.1.1/ && echo ok
[...]
ok
[email protected]:~/node$ make -j9 && echo ok
-bash: make: command not found

Outra ferramenta que falta. Mesmos sintomas. Mesma solução:

[email protected]:~/node$ sudo apt-get install make
[email protected]:~/node$ make -j9 && echo ok
[...]
ok
[email protected]:~/node$ sudo make install
[...]
[email protected]:~/node$ /opt/node/bin/node --version
v8.1.1

Sucesso!

Observe: Eu instalei as várias ferramentas uma por uma para mostrar como diagnosticar os problemas de compilação e mostrar a solução típica para resolver esses problemas. Mas se você pesquisar mais sobre esse tópico ou ler outros tutoriais, descobrirá que a maioria das distribuições tem “meta-pacotes” agindo como um guarda-chuva para instalar algumas ou todas as ferramentas típicas usadas para compilar um software. Em sistemas baseados em Debian, você provavelmente encontrará o construir essenciais pacote para esse fim. E nas distribuições baseadas no Red Hat, esse será o "Ferramentas de desenvolvimento" grupo.

Do CentOS 7.0

[[email protected] ~]$ git clone --depth 1 
                               --branch v8.1.1 
                               https://github.com/nodejs/node
-bash: git: command not found

Comando não encontrado? Basta instalá-lo usando o yum gerenciador de pacotes:

[[email protected] ~]$ sudo yum install git
[[email protected] ~]$ git clone --depth 1 
                               --branch v8.1.1 
                               https://github.com/nodejs/node && echo ok
[...]
ok
[[email protected] ~]$ sudo mkdir /opt/node-v8.1.1
[[email protected] ~]$ sudo ln -sT node-v8.1.1 /opt/node
[[email protected] ~]$ cd node
[[email protected] 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.

Você adivinhou: NodeJS é escrito usando a linguagem C ++, mas meu sistema não tem o compilador correspondente. Yum para o resgate. Como não sou um usuário regular do CentOS, tive que pesquisar na Internet o nome exato do pacote que contém o compilador g ++. Me levando a essa página: https://superuser.com/questions/590808/yum-install-gcc-g-doesnt-work-anymore-in-centos-6-4

[[email protected] node]$ sudo yum install gcc-c++
[[email protected] node]$ ./configure --prefix=/opt/node-v8.1.1/ && echo ok
[...]
ok
[[email protected] node]$ make -j9 && echo ok
[...]
ok
[[email protected] node]$ sudo make install && echo ok
[...]
ok
[[email protected] node]$ /opt/node/bin/node --version
v8.1.1

Sucesso. De novo.

C. Fazer alterações no software instalado a partir do código-fonte

Você pode instalar um software da fonte porque precisa de uma versão muito específica, não disponível em seu repositório de distribuição. Ou porque você quer modificar esse programa. Para corrigir um bug ou adicionar um recurso. Afinal, o código aberto tem tudo a ver com isso. Portanto, aproveitarei a oportunidade para dar uma amostra do poder que você tem agora que pode compilar seu próprio software.

Aqui, faremos uma pequena alteração nas fontes do NodeJS. E veremos se nossa alteração será incorporada à versão compilada do software:

Abra o arquivo node/src/node.cc no seu favorito editor de texto (vim, nano, gedit, ...). E tente localizar esse fragmento de código:

   if (debug_options.ParseOption(argv[0], arg)) {
      // Done, consumed by DebugOptions::ParseOption().
    } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
      printf("%sn", NODE_VERSION);
      exit(0);
    } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
      PrintHelp();
      exit(0);
    }

É por aí linha 3830 do arquivo. Em seguida, modifique a linha que contém printf para combinar com aquele:

      printf("%s (compiled by myself)n", NODE_VERSION);

Em seguida, volte para o seu terminal. Antes de prosseguir - e para lhe dar mais informações sobre o poder por trás do git - você pode verificar se modificou o arquivo certo:

diff --git a/src/node.cc b/src/node.cc
index 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[0], arg)) {
       // Done, consumed by DebugOptions::ParseOption().
     } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
-      printf("%sn", NODE_VERSION);
+      printf("%s (compiled by myself)n", NODE_VERSION);
       exit(0);
     } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
       PrintHelp();

Você deve ver um “-” (sinal de menos) antes da linha, como estava antes de você alterá-la. E um “+” (sinal de mais) antes da linha após suas alterações.

Agora é hora de recompilar e reinstalar seu software:

make -j9 && sudo make install && echo ok
[...]
ok

Desta vez, o único motivo pelo qual pode falhar é que você cometeu um erro de digitação ao alterar o código. Se for esse o caso, reabra o node/src/node.cc arquivo em seu editor de texto e corrija o erro.

Depois de compilar e instalar a nova versão modificada do NodeJS, você poderá verificar se as modificações foram realmente incorporadas ao software:

[email protected]:~/node$ /opt/node/bin/node --version
v8.1.1 (compiled by myself)

Parabéns! Você fez sua primeira alteração em um programa de código aberto!

D. Deixe o shell localizar nosso software de construção personalizado

Você deve ter notado até agora, eu sempre iniciei meu software NodeJS recém-compilado especificando o caminho absoluto para o arquivo binário.

/opt/node/bin/node

Funciona. Mas isso é irritante, para dizer o mínimo. Na verdade, existem duas maneiras comuns de consertar isso. Mas, para entendê-los, você deve primeiro saber que seu shell localiza os arquivos executáveis ​​procurando por eles apenas nos diretórios especificados pelo PATH variável de ambiente.

[email protected]:~/node$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Aqui, nesse sistema Debian, se você não especificar explicitamente qualquer diretório como parte de um nome de comando, o shell irá primeiro procurar por programas executáveis ​​em /usr/local/bin, então se não for encontrado em /usr/bin, então se não for encontrado em /bin então se não for encontrado em /usr/local/games então se não for encontrado em /usr/games, então, se não for encontrado ... o shell relatará um erro "comando não encontrado".

Dado isso, temos duas formas de tornar um comando acessível ao shell: adicionando-o a um dos já configurados PATH diretórios. Ou adicionando o diretório que contém nosso arquivo executável ao PATH.

Adicionando um link de / usr / local / bin

Somente copiando o executável binário do nó de /opt/node/bin para /usr/local/bin seria uma má ideia, pois, ao fazer isso, o programa executável não seria mais capaz de localizar os outros componentes necessários pertencentes ao /opt/node/ (é uma prática comum para um software localizar seus arquivos de recursos em relação ao seu próprio local).

Portanto, a maneira tradicional de fazer isso é usando um link simbólico:

[email protected]:~/node$ sudo ln -sT /opt/node/bin/node /usr/local/bin/node
[email protected]:~/node$ which -a node || echo not found
/usr/local/bin/node
[email protected]:~/node$ node --version
v8.1.1 (compiled by myself)

Esta é uma solução simples e eficaz, especialmente se um pacote de software for feito de apenas alguns programas executáveis ​​bem conhecidos - já que você precisa criar um link simbólico para cada um dos comandos invocáveis ​​pelo usuário. Por exemplo, se você está familiarizado com NodeJS, você conhece o npm aplicativo complementar que devo criar um link simbólico de /usr/local/bin também. Mas deixo isso para você como um exercício.

Modificando o PATH

Primeiro, se você tentou a solução anterior, remova o link simbólico do nó criado anteriormente para começar de um estado claro:

[email protected]:~/node$ sudo rm /usr/local/bin/node
[email protected]:~/node$ which -a node || echo not found
not found

E agora, aqui está o comando mágico para mudar o seu PATH:

[email protected]:~/node$ export PATH="/opt/node/bin:${PATH}"
[email protected]:~/node$ echo $PATH
/opt/node/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Dito de forma simples, substituí o conteúdo do PATH variável de ambiente por seu conteúdo anterior, mas prefixado por /opt/node/bin. Então, como você pode imaginar agora, o shell vai olhar primeiro para o /opt/node/bin diretório para programas executáveis. Podemos confirmar que usando o which comando:

[email protected]:~/node$ which -a node || echo not found
/opt/node/bin/node
[email protected]:~/node$ node --version
v8.1.1 (compiled by myself)

Considerando que a solução de “link” é permanente assim que você cria o link simbólico em /usr/local/bin, PATH a mudança é efetiva apenas no shell atual. Eu deixo você fazer algumas pesquisas sozinho para saber como fazer alterações no PATH permanentes. A título de dica, tem a ver com o seu “perfil”. Se você encontrar a solução, não hesite em compartilhá-la com os outros leitores usando a seção de comentários abaixo!

E. Como remover o software recém-instalado do código-fonte

Uma vez que nosso software NodeJS compilado personalizado fica completamente no /opt/node-v8.1.1 diretório, remover esse software não é mais trabalhoso do que usar o rm comando para remover esse diretório:

sudo rm -rf /opt/node-v8.1.1

CUIDADO: sudo e rm -rf são um coquetel perigoso! Sempre verifique o seu comando duas vezes antes de pressionar a tecla “enter”. Você não terá nenhuma mensagem de confirmação e nenhum undelete se remover o diretório errado ...

Então, se você modificou seu PATH, você terá que reverter essas alterações. O que não é nada complicado.

E se você criou links de /usr/local/bin você terá que removê-los todos:

[email protected]:~/node$ sudo find /usr/local/bin 
                                 -type l 
                                 -ilname "/opt/node/*" 
                                 -print -delete
/usr/local/bin/node

Espere? Onde estava o inferno da dependência?

Como comentário final, se você leu sobre como compilar seu próprio software personalizado, deve ter ouvido falar sobre o inferno de dependência. Este é um apelido para aquela situação irritante onde antes de ser capaz de compilar um software com sucesso, você deve primeiro compilar uma biblioteca de pré-requisitos, que por sua vez requer outra biblioteca que pode por sua vez ser incompatível com algum outro software que você já instalado.

Parte do trabalho dos mantenedores de pacotes de sua distribuição é resolver realmente esse inferno de dependência e garantir que os vários softwares de seu sistema estejam usando bibliotecas compatíveis e sejam instalados na ordem certa.

Nesse artigo, escolhi propositalmente instalar o NodeJS, pois ele praticamente não tem dependências. Eu disse "virtualmente" porque, na verdade, tem dependências. Mas o código-fonte dessas dependências estão presentes no repositório de origem do projeto (no node/deps subdiretório), para que não seja necessário fazer o download e instalá-los manualmente.

Mas se você estiver interessado em entender mais sobre esse problema e aprender como lidar com ele, deixe-me saber isso usando a seção de comentários abaixo: esse seria um ótimo tópico para um artigo mais avançado!

fonte