Perché i makefile dovrebbero avere un obiettivo di "installazione"?


18

Provenendo dal mondo di C e C ++, la maggior parte dei sistemi di compilazione ha un installtarget, in particolare Makefile (dove è raccomandato da GNU per esempio) o CMake . Questa destinazione copia i file di runtime (eseguibili, librerie, ...) nel sistema operativo (ad esempio, C:\Program Files\su Windows).

Questo sembra davvero disordinato, dal momento che per me non è responsabilità del sistema di compilazione installare programmi (che in realtà è la responsabilità del sistema operativo / gestore di pacchetti). Significa anche che il sistema di compilazione o lo script di compilazione devono conoscere l'organizzazione dei programmi installati, con variabili di ambiente, variabili di registro, collegamenti simbolici, autorizzazioni, ecc.

Nella migliore delle ipotesi, i sistemi di compilazione dovrebbero avere una releasedestinazione che produrrà un programma installabile (ad esempio .debo .msi), quindi chiedere gentilmente al sistema operativo di installare quel programma. Consentirebbe inoltre all'utente di disinstallare senza dover digitare make uninstall.

Quindi, la mia domanda: perché il sistema di build di solito consiglia di avere un installobiettivo?


7
La tua argomentazione secondo cui "make install" non rientra nella responsabilità di un sistema di compilazione, ma lo è la responsabilità più implicita e specifica della piattaforma di creare un pacchetto installabile.
pmf

2
In ogni caso: a volte si desidera installare un'applicazione che non è gestita dal sistema operativo / gestore pacchetti (perché ha dipendenze che potrebbero causare conflitti impossibili da risolvere utilizzando il gestore pacchetti ecc.). make installdi solito si installa in /usr/local(o anche /opt) che sono directory non gestite dal "sistema operativo core / sistema di gestione dei pacchetti". Non ho idea se Windows abbia qualche convenzione simile però.
Bakuriu,

11
"Questo sembra davvero confuso." Bene, cosa ti aspettavi dal mondo del C / C ++? ;-)
Mason Wheeler il

1
Nota che make installnon ha senso quando parliamo di cross-compilation
Hagen von Eitzen,

1
@HagenvonEitzen lo fa con DESTDIR.
Nax 'vi-vim-nvim'

Risposte:


23

Molti script di compilazione o Makefile hanno una destinazione di installazione perché sono stati creati prima dell'esistenza dei gestori di pacchetti e perché ancora oggi molti sistemi non dispongono di gestori di pacchetti. Inoltre, ci sono sistemi in cui èmake install effettivamente il modo preferito di gestire i pacchetti.


Sono curioso di sapere dove make installsono i sistemi preferiti. A parte ciò, intendevo il responsabile del programma quando ho detto che i makefile dovrebbero creare pacchetti installabili. Penso che quasi tutti i sistemi operativi abbiano un modo di gestire i programmi installati? Ad esempio, Windows non ha un gestore di pacchetti (a parte l'archivio) ma ha ancora un modo per gestire i programmi installati (tramite .msipacchetti per esempio)
Synxis

2
@Synxis BSD, Linux, Unix usano tutti i makefile. Se è preferito usarli per l'installazione, non lo so, ma spesso hai quella capacità di usare make install.
Rob,

1
In debian almeno è preferito usare checkinstallsopra make installper due motivi: "Si può facilmente rimuovere il pacchetto con un passo" e "È possibile installare il pacchetto risultante su più macchine." - poiché checkinstall crea un .deb e lo installa, utilizza il gestore pacchetti ...
Aaron Hall

1
@Synxis - Esistono diverse distribuzioni di Linux (spesso chiamate distro sorgente) in cui il gestore pacchetti installa i programmi scaricando un file tar, decomprimendolo e quindi eseguendolomake install
slebetman

1
@AaronHall Correggimi se sbaglio, ma ho avuto l'impressione che checkinstallun'invocazione effettivamente utilizzerà make install e monitorerà le sue azioni per la creazione di pacchetti.
cmaster - ripristina monica il

5

A makefilepotrebbe non avere una installdestinazione e, cosa più importante, è possibile avere programmi che non dovrebbero nemmeno essere installabili (ad esempio perché dovrebbero essere eseguiti dalla loro directory di generazione o perché possono essere installati ovunque). L' installobiettivo è solo una convenzione per i soliti makefile.

Tuttavia, molti programmi richiedono l'esecuzione di risorse esterne (ad esempio: caratteri, database, file di configurazione, ecc.). E il loro eseguibile spesso fa delle ipotesi su queste risorse. Ad esempio, la bashshell in genere legge alcuni file di inizializzazione da /etc/bash.bashrcecc. Queste risorse si trovano generalmente nel file system (consultare hier (7) per le convenzioni sulla gerarchia dei file) e il percorso del file predefinito viene creato nell'eseguibile.

Prova a usare stringhe (1) sulla maggior parte degli eseguibili del tuo sistema. Scoprirai quali percorsi di file sono noti ad esso.

A proposito, per molti programmi GNU che utilizzi autoconf, potresti eseguire make install DESTDIR=/tmp/destdir/senza essere root. Quindi /tmp/destdir/viene riempito con i file che dovrebbero essere successivamente impacchettati.

FWIW, tendo a credere che il mio programma bismon (licenza GPLv3 +) (descritto nel mio rapporto bismon-chariot-doc.pdf ) non possa essere "installato"; Non sono sicuro di essere in grado di dimostrarlo, e non riesco a immaginare come potrei rendere quel programma installabile.


2
DESTDIR o altri prefissi sono troppo spesso dimenticati. Non appena sono coinvolte risorse esterne come le librerie dinamiche, non è possibile creare il software senza sapere dove verrà installato . Ottimo anche per l'installazione in posizioni non standard, ad es. /optO in $HOME. L'unico modo per evitare prefissi diversi è utilizzare i contenitori, ma questa è ovviamente una soluzione specifica per Linux.
amon,

2
Ho visto più di un pacchetto che se si provasse DESTDIR = / tmp / destdir non funzionerebbe più tardi se installato nella posizione normale perché DESTDIR è stato usato nella generazione del percorso.
Giosuè,

@amon: non sono sicuro che caratterizzerei i container come specifici di Linux. Linux può essere una piattaforma target comune per la containerizzazione, ma esiste una qualche forma di tecnologia container nella maggior parte dei sistemi operativi moderni.
Kevin,

1
@Joshua Non dovrebbe, DESTDIR dovrebbe essere rilevante solo durante la fase di installazione. Dovresti essere in grado di fare: ./configure --prefix="/opt/foo" && make && DESTDIR=/tmp/foo make install ed essere in grado di spostare il pacchetto /opt/foosenza alcun problema.
Nax 'vi-vim-nvim'

3

Ci sono diverse ragioni che mi vengono in mente.

  • Molti software per la creazione di pacchetti - ad esempio il sistema di compilazione Debian e anche il rpm IIRC - si aspettano già dallo script di costruzione di "installare" il programma in una sottodirectory speciale. Quindi è guidato dalla retrocompatibilità in entrambe le direzioni.
  • Un utente potrebbe voler installare il software in uno spazio locale, come nella $HOMEdirectory. Non tutti i gestori di pacchetti lo supportano.
  • Potrebbero esserci ancora ambienti che non hanno pacchetti.

Ho riformulato la domanda un po ', intendevo il responsabile del programma quando ho detto che i makefile dovrebbero creare pacchetti installabili.
Synxis,

1

Un motivo non menzionato è che ci sono molte volte in cui non si utilizza la versione corrente del software o si utilizza una versione modificata del software. Cercare di creare un pacchetto personalizzato non è solo più lavoro, ma può entrare in conflitto con i pacchetti attualmente creati e distribuiti. Nel codice open source ciò accade molto, soprattutto se vengono introdotte modifiche non significative nelle versioni future che si stanno utilizzando.

Supponiamo che tu stia utilizzando il progetto open source FOO che è attualmente nella versione 2.0.1 e stai utilizzando la versione 1.3.0. Non vuoi usare nulla di sopra perché la versione 2.0.0 è incompatibile con quello che stai facendo, ma c'è una singola correzione di bug in 2.0.1 di cui hai disperatamente bisogno. Avere l' make installopzione ti consente di installare il software 1.3.0 modificato senza doversi preoccupare di creare un pacchetto e installarlo sul tuo sistema.


1

Le distribuzioni Linux generalmente separano la manutenzione dei programmi dalla manutenzione dei pacchetti. Un sistema di build che integri la generazione di pacchetti costringerebbe i manutentori del programma a eseguire anche la manutenzione dei pacchetti.

Questa è di solito una cattiva idea. Le distribuzioni hanno molte infrastrutture per verificare la coerenza interna, fornire binari per più piattaforme target, eseguire piccole modifiche per integrarsi meglio con il resto del sistema e fornire un'esperienza coerente agli utenti che segnalano bug.

Per generare pacchetti direttamente da un sistema di generazione, è necessario integrare o ignorare tutta questa infrastruttura. Integrarlo sarebbe molto lavoro a beneficio discutibile, e bypassarlo darebbe un'esperienza utente peggiore.

Questo è uno dei problemi "top della catena alimentare" tipici dei sistemi multipartitico. Se hai più sistemi complessi, deve esserci una chiara gerarchia di quale sistema è responsabile del coordinamento di tutti gli altri.

Nel caso della gestione dell'installazione del software, questo è il gestore dei pacchetti, che eseguirà il sistema di compilazione del pacchetto, quindi prenderà l'output attraverso una comoda interfaccia ("file in una directory dopo una fase di installazione"), genererà un pacchetto e preparerà per il caricamento su un repository.

Il gestore dei pacchetti si trova nel mezzo tra il sistema di compilazione e il repository qui ed è nella posizione migliore per integrarsi bene con entrambi.

Potresti aver notato che ci sono solo alcuni dei pacchetti JavaScript disponibili npmanche disponibili anche attraverso apt- questo principalmente perché le persone JavaScript hanno deciso che npmil repository associato sarebbe stato il top della loro catena alimentare, il che ha reso quasi impossibile spedire questi pacchetti come pacchetti Debian.

Con il mio cappello da sviluppatore Debian attivo: se rilasci software open source, lascia la confezione ai manutentori della distribuzione. Risparmia molto lavoro a te e a noi.


Non hai detto nulla sul perché esiste un target di installazione, e mi sembra che la maggior parte di ciò che hai scritto si applicherebbe anche ad esso ...
curiousdannii

1
@curiousdannii, ci deve essere una certa interfaccia tra sistema di generazione e gestore di pacchetti, e questo sembra essere il più semplice, così ha vinto.
Simon Richter,

1

Bene, gli sviluppatori di applicazioni sono quelli che sanno dove dovrebbe andare ogni file. Potrebbero lasciarlo nella documentazione e fare in modo che i manutentori dei pacchetti lo leggessero e creassero uno script per ciascun pacchetto. Forse i manutentori del pacchetto interpreteranno erroneamente la documentazione e dovranno eseguire il debug dello script fino a quando non funziona. Questo è inefficiente. È meglio che lo sviluppatore dell'applicazione scriva uno script per installare correttamente l'applicazione che ha scritto.

Poteva scrivere uno script di installazione con un nome arbitrario o forse renderlo parte della procedura di qualche altro script. Tuttavia, avendo un comando di installazione standard, make install(una convenzione che precede i gestori di pacchetti), è diventato davvero semplice creare pacchetti. Se guardi il modello PKGBUILD per creare pacchetti Archlinux , puoi vedere che la funzione che effettivamente include i pacchetti fa semplicemente un make DESTDIR="$pkgdir/" install. Questo probabilmente funziona per la maggior parte dei pacchetti e probabilmente di più con una piccola modifica. Grazie al fatto che make(e gli autotools) sono standard, il packaging è davvero molto semplice.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.