Resumo: Este detalhado guia explica como instalar um programa 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 novos softwares 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, para compilar algum software é quando preciso executar uma versão muito específica ou modificar o código-fonte usando algumas opções de compilação sofisticadas.
Se suas necessidades pertencem à última categoria, é provável que você já saiba o que fazer. Mas, para a grande maioria dos usuários do Linux, compilar e instalar software a partir do código-fonte 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 um lugar de prestígio em uma comunidade privilegiada.
A. Instalação de software a partir do código-fonte no Linux
E é exatamente isso que faremos aqui. Para o propósito deste artigo, digamos que eu precise instalar o NodeJS 8.1.1 em 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
Agora, instalar NodeJs no Ubuntu ou Debian é muito simples se você fizer isso com o gerenciador de pacotes. Mas vamos fazer isso por meio do código-fonte.
Etapa 1: Obtendo 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á.
Git ou qualquer outro sistema de controle de versão digno de menção, 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 as 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 de ramificação 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 manter o controle de eventos importantes no histórico do projeto, como quando eles começam a trabalhar em um novo recurso ou quando publicam um lançamento. Não vou entrar em detalhes aqui, tudo que você precisa saber é que estou procurando a versão marcada v8.1.1
Depois de ter escolhido a tag v8.1.1, a página é atualizada, a alteração 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 de NodeJS 8.1.1. Você não pode perder o grande botão azul sugerindo baixar o arquivo ZIP do projeto. Quanto a mim, irei baixar e extrair o ZIP da linha de comando para fins de explicação. Mas se você preferir usar uma ferramenta GUI, 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 a ferramenta git
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 um problema, considere a primeira parte deste artigo como uma introdução geral. Posteriormente, eu tenho explicações mais detalhadas para distribuições baseadas em Debian e RedHat para ajudá-lo a solucionar problemas comuns.
De qualquer forma, sempre que você baixou o código-fonte usando git
ou como um arquivo ZIP, agora você deve ter exatamente os mesmos arquivos-fonte 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 sistema de compilação 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í.
O NodeJS usa um sistema de compilação no estilo GNU, é 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 compilação é uma tarefa bastante complexa, mas para o usuário final, os sistemas de compilação no estilo GNU facilitam a tarefa usando duas ferramentas: configure
e make
.
O arquivo configure
é 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, atendendo eventualmente às especificidades da plataforma atual.
Uma parte importante de um trabalho configure
típico é construir o Makefile
. Esse é o arquivo que contém as instruções necessárias para construir o projeto com eficácia.
A ferramenta make
, por outro lado, é uma ferramenta POSIX disponível em qualquer sistema semelhante ao Unix. Ele lerá o Makefile
específico do projeto e executará as operações necessárias para construir e instalar seu programa.
Mas, como sempre no mundo Linux, você ainda tem certa tolerância em personalizar a construção de acordo com suas necessidades específicas.
./configure --help
O comando configure -help
mostrará 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 compreender totalmente o significado de cada opção de configuração.
Mas há pelo menos uma opção GNU Autotools padrão que você deve saber: a opção --prefix
. Isso está relacionado à hierarquia do sistema de arquivos e ao local em que o software será instalado.
Etapa 3: O FHS
A hierarquia do sistema de arquivos Linux em uma distribuição típica está em conformidade com o Filesystem Hierarchy Standard (FHS)
Esse padrão explica a finalidade dos vários diretórios de 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 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 durante a instalaçã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 hierarquia /usr/local
de alguma forma replica o diretório raiz e você encontrará /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 a árvore /usr/local
para a 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 a qual arquivo exatamente /usr/local/bin
e /usr/local/lib
pertence a qual software. Isso não vai causar nenhum problema ao sistema. Afinal, /usr/bin
é praticamente 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 na subárvore /opt
. Mais uma vez, para citar a ESF:
opt
é reservado para a instalação de pacotes de software de aplicativos complementares.
Um pacote a ser instalado em/opt deve localizar seus arquivos estáticos em uma árvore de diretórios /opt/pacote
ou /opt/provedor
separada, onde pacote
é um nome que descreve o pacote de software e provedor
é o nome registrado do provedor.
Portanto, criaremos um subdiretório /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
# -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 após o comando make
ser concluído significaria que houve um erro durante o processo de compilação. Como executamos uma compilação paralela por causa da opção -j
, 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 um problema, basta reiniciar make
, mas sem a opção -j
desta vez. E o erro deve aparecer próximo ao final da saída:
make
Finalmente, uma vez que a compilação tenha chegado ao fim, você pode instalar o software em seu local executando o comando:
sh$ sudo make install
E teste:
terminalcard('sh$ /opt/node/bin/node --version') }}
v8.1.1
B. E se algo der 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 das fontes, pode valer a pena investigar alguns problemas comuns. Então, farei todo o procedimento novamente, mas desta vez de um sistema Debian 9.0 e CentOS 7.0 novo e mínimo para que você possa ver os erros que encontrei e como os resolvi.
Do Debian 9.0 Stretch
$ 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 pacote git
:
sudo apt-get install git
git clone --depth 1--branch v8.1.1 https://github.com/nodejs/node
sudo mkdir /opt/node-v8.1.1
sudo ln -sT node-v8.1.1 /opt/node
Nenhum problema aqui.
~/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 a linguagem C ++, precisamos de um compilador C ++. Aqui, instalarei o g ++
, o compilador GNU C ++ para esse propósito:
~/node$ sudo apt-get install g++
[email protected]:~/node$ ./configure --prefix=/opt/node-v8.1.1/ && echo ok
[...]
ok
make -j9 && echo ok
-bash: make: command not found
Uma outra ferramenta ausente. Mesmos sintomas. Mesma solução:
[sudo apt-get install make
make -j9 && echo ok
sudo make install
/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 informações sobre o 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 pacote build-essentials para esse propósito. E nas distribuições baseadas no Red Hat, esse será o grupo Ferramentas de Desenvolvimento .
Do CentOS 7.0
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 gerenciador de pacotes yum
:
sudo yum install git
git clone --depth 1 --branch v8.1.1 https://github.com/nodejs/node && echo ok
[...]
ok
sudo mkdir /opt/node-v8.1.1
sudo ln -sT node-v8.1.1 /opt/node
cd 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 foi 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 comum 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
sudo yum install gcc-c++
./configure --prefix=/opt/node-v8.1.1/ && echo ok
[...]
ok
make -j9 && echo ok
ok
sudo make install && echo ok
ok
/opt/node/bin/node --version
v8.1.1
Sucesso. Novamente.
C. Fazer alterações no software instalado a partir do código-fonte
Você pode instalar o 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 deseja modificar o programa para corrigir um bug ou adicionar um recurso. Afinal, o código aberto trata de fazer modificações. Portanto, aproveitarei esta oportunidade para lhe dar uma amostra do poder que você tem em mãos agora que é capaz de 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
em seu editor de texto favorito (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("%s\n", NODE_VERSION);
exit(0);
} else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
PrintHelp();
exit(0);
}
É cerca de linha 3830 do arquivo. Em seguida, modifique a linha que contém printf
para corresponder àquela:
printf("%s (compiled by myself)\n", NODE_VERSION);
Em seguida, volte para o seu terminal. Antes de prosseguir - e para lhe dar mais uma ideia do 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("%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();
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, a única razão pela qual pode falhar é que você cometeu um erro de digitação ao alterar o código. Nesse caso, reabra o arquivo node/src/node.cc
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:
~/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 que eu sempre lancei 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.
Na verdade, existem duas maneiras comuns de corrigir o problema irritante de especificar o caminho absoluto para os arquivos binários, mas, para compreendê-los, você deve primeiro saber que seu shell localiza os arquivos executáveis procurando por eles apenas nos diretórios especificados por PATH variável de ambiente.
~/node$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
Aqui, naquele sistema Debian, se você não especificar explicitamente qualquer diretório como parte de um nome de comando, o shell irá primeiro procurar os 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 não encontrado em /usr/local/games
então se não for encontrado em /usr/games
, então se não for encontrado ... o shell irá relatar um erro comando não encontrado .
Dado isso, temos duas maneiras de tornar um comando acessível ao shell: adicionando-o a um dos diretórios PATH
já configurados. Ou adicionando o diretório que contém nosso arquivo executável ao PATH
.
Adicionando um link de/usr/local/bin
Apenas copiar 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 a /opt/node/
(é uma prática comum para software localizar seu recurso arquivos relativos à sua própria localização).
Portanto, a maneira tradicional de fazer isso é usando um link 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 --version
v8.1.1 (compiled by myself)
Esta é uma solução simples e eficaz, especialmente se um pacote de software é feito de apenas alguns programas executáveis bem conhecidos - uma vez que você precisa criar um link simbólico para cada comando invocável pelo usuário. Por exemplo, se você está familiarizado com o NodeJS, você conhece o aplicativo complementar npm
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:
~/node$ sudo rm /usr/local/bin/node
~/node$ which -a node || echo not found
not found
E agora, aqui está o comando mágico para alterar seu 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
Simplesmente dito, substituí o conteúdo da variável de ambiente PATH
por seu conteúdo anterior, mas prefixado por /opt/node/bin
. Então, como você pode imaginar agora, o shell irá procurar primeiro no diretório /opt/node/bin
programas executáveis. Podemos confirmar isso usando o comando which
:
~/node$ which -a node || echo not found
/opt/node/bin/node
~/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
, a mudança PATH
é efetiva apenas no shell atual. Vou deixar você fazer algumas pesquisas sobre como fazer alterações nas permanentes PATH
. Como 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
Como nosso software NodeJS compilado personalizado fica completamente no diretório /opt/node-v8.1.1
, a remoção desse software não requer mais esforço do que usar o comando rm 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 seu comando duas vezes antes de pressionar a tecla Enter. Você não terá nenhuma mensagem de confirmação e nenhuma restauração se remover o diretório errado ...
Então, se você modificou seu PATH
, terá que reverter essas alterações, o que não é nada complicado.
E se você criou links de /usr/local/bin
, terá que removê-los todos:
~/node$ sudo find /usr/local/bin \
-type l \
-ilname "/opt/node/*" \
-print -delete
/usr/local/bin/node
Esperar? 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 do pacote de sua distribuição é realmente resolver 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.
Para este artigo, optei, propositalmente, por instalar o NodeJS, pois ele praticamente não possui dependências. Eu disse virtualmente porque, na verdade, ele tem dependências. Mas o código-fonte dessas dependências está presente no repositório de origem do projeto (no subdiretório node/deps
), então você não precisa fazer o download e instalá-los manualmente com antecedência.
Mas se você estiver interessado em entender mais sobre esse problema e aprender como lidar com ele, deixe-me saber que usando a seção de comentários abaixo: seria um ótimo tópico para um artigo mais avançado!