Por que os makefiles devem ter um destino de "instalação"?

18

Vindo do mundo de C e C ++, a maioria dos sistemas de compilação tem um installalvo, principalmente Makefiles (onde é recomendado pelo GNU, por exemplo) ou CMake . Esse destino copia os arquivos de tempo de execução (executáveis, bibliotecas, ...) no sistema operacional (por exemplo, no C:\Program Files\Windows).

Isso parece muito hacky, pois para mim não é responsabilidade do sistema de compilação instalar programas (que é realmente responsabilidade do sistema operacional / gerenciador de pacotes). Também significa que o sistema ou script de construção deve conhecer a organização dos programas instalados, com variáveis ​​de ambiente, variáveis ​​de registro, links simbólicos, permissões, etc.

Na melhor das hipóteses, os sistemas de compilação devem ter um releasedestino que produza um programa instalável (por exemplo .debou .msi) e, em seguida, solicite ao sistema operacional que instale esse programa. Também permitiria ao usuário desinstalar sem precisar digitar make uninstall.

Então, minha pergunta: por que o sistema de compilação geralmente recomenda ter um installalvo?

Synxis
fonte
7
Seu argumento de que "make install" não é de responsabilidade de um sistema de construção, mas a responsabilidade muito mais envolvida e específica da plataforma de criar um pacote instalável.
Pmf #
2
De qualquer forma: às vezes você deseja instalar um aplicativo que não é tratado pelo gerenciador de SO / pacotes (porque ele possui dependências que causariam conflitos impossíveis de resolver usando o gerenciador de pacotes etc). make installgeralmente instala sob /usr/local(ou mesmo /opt) diretórios não tratados pelo "sistema principal de gerenciamento de SO / pacotes". Não faço ideia se o Windows tem alguma convenção semelhante.
Bakuriu 23/11/19
11
"Isso parece realmente hacky." Bem, o que você esperava do mundo do C / C ++? ;-)
Mason Wheeler
1
Note-se que make installnão faz sentido quando falamos de compilação cruzada
Hagen von Eitzen
1
@HagenvonEitzen faz com DESTDIR.
Nax 'vi-vim-nvim'

Respostas:

23

Muitos scripts de construção ou Makefiles têm um destino de instalação porque foram criados antes da existência dos gerenciadores de pacotes e porque até hoje muitos sistemas não têm gerenciadores de pacotes. Além disso, existem sistemas onde make installrealmente é a maneira preferida de gerenciar pacotes.

Jörg W Mittag
fonte
Estou curioso sobre os sistemas onde make installé preferido. Além disso, eu quis dizer gerente de programa quando disse que makefiles deveriam criar pacotes instaláveis. Eu acho que quase todos os sistemas operacionais vêm com uma maneira de gerenciar os programas instalados? Por exemplo, o Windows não tem gerenciador de pacotes (para além da loja), mas ainda tem uma forma de gerenciar os programas instalados (via .msipacotes para exemplos)
Synxis
2
O @Synxis BSD, Linux, Unix usa makefiles. Se é preferível usá-los para instalação, não sei, mas você costuma usar essa capacidade make install.
Rob
1
No debian, pelo menos, é preferível usar checkinstallmais make installpor duas razões: "Você pode remover facilmente o pacote com uma etapa." e "Você pode instalar o pacote resultante em várias máquinas". - como checkinstall constrói um .deb e instala-lo, ele usa o gerenciador de pacotes ...
Aaron Hall
1
@Synxis - Existem várias distribuições Linux (muitas vezes chamado de distros de origem), onde o gerenciador de pacotes instalar programas por download de um arquivo tar, descompactá-lo em seguida, executarmake install
slebetman
1
@AaronHall Corrija-me se estiver errado, mas tive a impressão de que uma checkinstallchamada realmente usará make install e monitorará suas ações para a criação de pacotes.
cmaster - reinstate monica
5

A makefilepode não ter um installdestino e, mais importante, você pode ter programas que nem deveriam ser instaláveis ​​(por exemplo, porque eles devem ser executados a partir do diretório de compilação ou porque podem ser instalados em qualquer lugar). O installalvo é apenas uma convenção para o habitual makefile-s.

No entanto, muitos programas exigem a execução de recursos externos (por exemplo: fontes, bancos de dados, arquivos de configuração etc.). E seus executáveis ​​geralmente fazem algumas hipóteses sobre esses recursos. Por exemplo, seu bashshell geralmente lê alguns arquivos de inicialização de /etc/bash.bashrcetc ... Esses recursos geralmente estão no sistema de arquivos (consulte hier (7) para convenções sobre a hierarquia de arquivos) e o caminho padrão do arquivo é construído em seu executável.

Tente usar as strings (1) na maioria dos executáveis ​​do seu sistema. Você descobrirá quais caminhos de arquivo são conhecidos por ele.

BTW, para muitos programas GNU usando autoconf, você pode executar make install DESTDIR=/tmp/destdir/sem ser root. Em seguida, /tmp/destdir/é preenchido com os arquivos que devem ser empacotados posteriormente.

FWIW, acredito que meu programa bismon (licenciado pela GPLv3 +) (descrito no meu relatório bismon-chariot-doc.pdf ) não pode ser "instalado"; Não tenho certeza se posso provar isso e não consigo imaginar como poderia tornar esse programa instalável.

Basile Starynkevitch
fonte
2
DESTDIR ou outros prefixos são frequentemente esquecidos. Assim que recursos externos, como bibliotecas dinâmicas, estão envolvidos, não é possível criar o software sem saber onde ele será instalado . Também é ótimo para instalar em locais fora do padrão, por exemplo, /optou no $HOME. A única maneira de evitar prefixos diferentes é usar contêineres, mas é claro que é uma solução específica para Linux.
amon
2
Eu já vi mais de um pacote que, se você tentasse DESTDIR = / tmp / destdir, não funcionaria mais tarde quando instalado no local normal porque o DESTDIR foi usado na geração do caminho.
Joshua
@ amon: Não tenho certeza se caracterizaria os contêineres como específicos do Linux. O Linux pode ser uma plataforma de destino comum para conteinerização, mas existe alguma forma de tecnologia de contêiner na maioria dos sistemas operacionais modernos.
23718 Kevin
1
@ Joshua Não deveria, DESTDIR deve ser relevante apenas durante a etapa de instalação. Você deve conseguir: ./configure --prefix="/opt/foo" && make && DESTDIR=/tmp/foo make install e realocar o pacote para /opt/foosem problemas.
Nax 'vi-vim-nvim'
3

Existem várias razões que vêm à mente.

  • Muitos softwares de criação de pacotes - o sistema de construção Debian por exemplo, e também o IIRC rpm - já esperam que o script de construção "instale" o programa em algum subdiretório especial. Por isso, é impulsionado pela compatibilidade com versões anteriores em ambas as direções.
  • Um usuário pode querer instalar o software em um espaço local, como no $HOMEdiretório Nem todos os gerenciadores de pacotes o suportam.
  • Ainda pode haver ambientes que não possuem pacotes.
max630
fonte
Eu reformulei a pergunta um pouco, eu quis dizer gerente de programa quando disse que makefiles deveriam criar pacotes instaláveis.
Synxis
1

Um motivo não mencionado é que muitas vezes você não está usando a versão atual do software ou uma versão modificada do software. Tentar criar um pacote personalizado não é apenas mais trabalho, mas pode entrar em conflito com os pacotes atualmente criados e distribuídos. No código-fonte aberto, isso acontece muito, especialmente se alterações recentes forem introduzidas em versões futuras que você estiver usando.

Digamos que você esteja usando o projeto de código aberto FOO, que está atualmente na versão 2.0.1 e você está usando a versão 1.3.0. Você não deseja usar nada acima disso porque a versão 2.0.0 é incompatível com o que você está fazendo no momento, mas há uma única correção de bug na versão 2.0.1 que você precisa desesperadamente. Tendo a make installopção, você pode instalar o software 1.3.0 modificado sem ter que se preocupar em criar um pacote e instalá-lo no seu sistema.

Dom
fonte
1

As distribuições Linux geralmente separam a manutenção do programa da manutenção de pacotes. Um sistema de construção que integra a geração de pacotes forçaria os mantenedores do programa a também realizar a manutenção do pacote.

Isso geralmente é uma má ideia. As distribuições têm muita infraestrutura para verificar a consistência interna, fornecer binários para várias plataformas de destino, realizar pequenas alterações para melhor integrar-se ao restante do sistema e fornecer uma experiência consistente para os usuários que relatam bugs.

Para gerar pacotes diretamente de um sistema de construção, você teria que integrar ou ignorar toda essa infraestrutura. Integrá-lo seria muito trabalhoso para um benefício questionável, e ignorá-lo daria uma experiência pior ao usuário.

Esse é um dos problemas "principais da cadeia alimentar", típicos dos sistemas multipartidários. Se você possui vários sistemas complexos, é necessário haver uma hierarquia clara de qual sistema é responsável por coordenar todos os outros.

No caso do gerenciamento de instalação de software, o gerenciador de pacotes é esse componente e ele executa o sistema de compilação do pacote, em seguida conduz a saída por uma interface conveniente ("arquivos em um diretório após uma etapa de instalação"), gera um pacote e prepara para upload para um repositório.

O gerenciador de pacotes fica no meio entre o sistema de compilação e o repositório aqui, e está na melhor posição para integrar-se bem a ambos.

Você deve ter notado que existem apenas alguns pacotes JavaScript disponíveis por npmmeio deles apt- principalmente porque o pessoal do JavaScript decidiu isso npme o repositório associado seria o topo de sua cadeia alimentar, o que tornava quase impossível enviar esses pacotes como pacotes Debian.

Com meu chapéu de desenvolvedor Debian ativado: se você lançar um software de código aberto, deixe a embalagem para os mantenedores da distribuição. Isso poupa muito trabalho a você e a nós.

Simon Richter
fonte
Você não disse nada sobre por que há uma meta de instalar, e parece-me que a maioria do que você escreveu se aplicaria a ela também ...
curiousdannii
1
@curiousdannii, precisa haver alguma interface entre o sistema de compilação e o gerenciador de pacotes, e essa é a mais simples, por isso ganhou.
Simon Richter
1

Bem, os desenvolvedores de aplicativos são os que sabem onde cada arquivo deve ir. Eles podem deixar isso na documentação e fazer com que os mantenedores do pacote leiam isso e criem um script para cada pacote. Talvez os mantenedores de pacotes interpretem mal a documentação e precisem depurar o script até que funcione. Isso é ineficiente. É melhor para o desenvolvedor do aplicativo escrever um script para instalar corretamente o aplicativo que ele escreveu.

Ele poderia escrever um script de instalação com um nome arbitrário ou talvez fazer parte do procedimento de outro script. No entanto, com um comando de instalação padrão make install(uma convenção anterior aos gerenciadores de pacotes), ficou muito fácil criar pacotes. Se você observar o modelo PKGBUILD para criar pacotes do Archlinux , poderá ver que a função que realmente empacota simplesmente executa um make DESTDIR="$pkgdir/" install. Isso provavelmente funciona para a maioria dos pacotes e provavelmente mais com uma pequena modificação. Graças a make(e as ferramentas automáticas) ser padrão, a embalagem é muito, muito fácil.

JoL
fonte