Perché gli strumenti di compilazione usano un linguaggio di scripting diverso dal linguaggio di programmazione sottostante?


23

Recentemente ho usato alcuni strumenti di costruzione per un progetto Nodejs al lavoro quando mi sono reso conto che lo strumento / sistema di costruzione principale della maggior parte delle lingue usa un linguaggio diverso rispetto al linguaggio di programmazione stesso.

Ad esempio, make non usa C o C ++ per scrivere script e ant (né Maven) non usa Java come linguaggio per gli script.

Le lingue più recenti come Ruby usano la stessa lingua per costruire strumenti come rake , il che ha senso per me. Ma perché non è sempre stato così? Qual è il vantaggio di avere uno strumento di costruzione che utilizza una lingua diversa dalla lingua sottostante?


14
Forse il linguaggio generico non è abbastanza adatto per l'uso specialistico dello strumento? Ad esempio, non vorrei scrivere file make in C! A volte un DSL è meglio.
Andres F.,

13
Guardalo da un'altra prospettiva: perché non usare make per scrivere software applicativo?
whatsisname

4
Questo articolo riguarda principalmente ciò che l'autore crede rende Lisp eccezionale, ma contiene alcune informazioni rilevanti sul perché Ant utilizza XML anziché Java.
8

6
Se volessi scrivere un programma in C che automatizzi la costruzione di programmi in C, non finiresti per scrivere di makenuovo (che è comunque implementato in C)?
Brandin,

6
@ joshin4colours make è scritto in C. Il linguaggio che fa uso, tuttavia, è un linguaggio dichiarativo che invoca la shell secondo necessità.

Risposte:


36

La scelta del linguaggio di programmazione da utilizzare per eseguire qualsiasi operazione deve dipendere dalle caratteristiche specifiche di tale obiettivo e non dalle altre attività correlate a quel progetto.

Uno strumento di compilazione svolge un lavoro molto specifico e, indipendentemente dalla lingua utilizzata per il progetto principale, uno strumento di compilazione è un software da solo.

Cercare di legare il progetto principale e il suo strumento di costruzione potrebbe essere una pessima decisione. Ciò di cui dovresti avere bisogno con uno strumento di compilazione è principalmente un processo rapido di regole semplici, con una gestione rapida di file e IO.

Se lingue come Ruby si usano per implementare il loro strumento di costruzione, è più correlato alle caratteristiche di quella lingua che alla presunta necessità di mantenere tutto scritto con la stessa lingua.


18

Non è impossibile scrivere uno strumento di compilazione che utilizza un linguaggio come C o Java come linguaggio di scripting. Tuttavia, gli strumenti di costruzione traggono vantaggio dall'uso di linguaggi di scripting più dichiarativi . Immagina il dolore e lo scaldabagno di scrivere un makefile (o build.xml, o qualsiasi altra cosa) in C.

Gli strumenti di costruzione traggono vantaggio dall'uso di DSL, un'attività per la quale C non è una scelta particolarmente buona. C è troppo generico per uno strumento di compilazione e troppo interessato ai dettagli soggetti a errori e di basso livello. Ad esempio, non vuoi preoccuparti della gestione esplicita della memoria in uno strumento di compilazione! Quindi, anche se usi una sintassi simile a C, probabilmente useresti la garbage collection nel tuo strumento di scripting, a quel punto perché non usare semplicemente un DSL dedicato?

Ha senso che Ruby possa essere usato per questo, dal momento che è un linguaggio di livello superiore, più dichiarativo di C o Java. Vedi anche: Gradle, sbt.


13
Imagine the pain and boilerplate of writing a makefile (or build.xml, or whatever) in C.Immagina il dolore e il disordine di provare a esprimere una logica condizionale non banale (sai, roba imperativa standard) in uno script XML dichiarativo. Oh, aspetta, non devi immaginare; probabilmente hai dovuto affrontarlo, ed è stato probabilmente un casino e mezzo, no? Le build sono una delle peggiori scelte possibili per un linguaggio di scripting dichiarativo, perché i problemi seri finiscono rapidamente per confrontarsi con i limiti della dichiarazione dichiarativa e quelli che non sono abbastanza semplici da non aver bisogno di uno strumento di build.
Mason Wheeler,

7
@MasonWheeler Ci sono casi in cui gli strumenti di costruzione esistenti mi hanno fatto soffrire, sì. Nessuno di loro sarebbe stato aiutato usando un linguaggio imperativo di tipo C di basso livello. Vedo qualcosa come Ruby probabilmente ideale: abbastanza dichiarativo e imperativo, se necessario. C mi darebbe incubi per questo compito. Per me i sistemi di compilazione sono un buon caso d'uso per i DSL dichiarativi (principalmente): ti preoccupi di cosa fare, non di come farlo (il più delle volte).
Andres F.,

2
Giusto. Ho sempre pensato che C fosse una di quelle tecnologie "se X è la risposta che stai ponendo la domanda sbagliata", a dire il vero; è solo che lavorare con gli "script" XML è stato un incubo ogni volta che ho dovuto immergermi in uno. Concordo sul fatto che un linguaggio imperativo di livello superiore con funzionalità DSL sarebbe l'ideale.
Mason Wheeler,

@AndresF .: Cose come creare file richiedono una combinazione di approcci. Lo stato di uscita desiderato è specificato in modo dichiarativo, ma le azioni necessarie per raggiungere tale stato sono specificate in modo imperativo.
supercat,

1
@MasonWheeler Penso che sia tanto un problema per le persone che hanno progettato il linguaggio di configurazione che lo stesso XML. L'errore comune degli autori di tali linguaggi è quello di presumere che solo perché qualcosa è in XML, sarà automaticamente leggibile dall'uomo. (So ​​di aver fatto questo errore più volte di quanto non mi senta a mio agio. È così allettante.) Un linguaggio di configurazione ben progettato e snello può funzionare su XML come in qualsiasi altra forma.
biziclop,

12

Diamo un esempio del mondo reale.

Circa 15 anni fa ho lavorato sul porting di un grande sistema scritto in C da Unix a Windows, che era di circa 3 milioni di righe di codice. Per darti un'idea della scala, ci sono voluti più di 24 ore per compilare su alcuni dei nostri sistemi unix (RS6000), Windows poteva compilare il sistema in circa 4 ore.

(Avevamo anche 2 milioni di righe di codice nel nostro linguaggio interpretato, ma abbiamo deciso di non usare il nostro linguaggio per i sistemi di compilazione poiché non è mai stato progettato per l'elaborazione dei file. Inoltre, avevamo bisogno di un sistema di compilazione per compilare il codice C che implementava il nostro linguaggio .)

All'epoca il sistema di compilazione era scritto in un mix di script di shell e creava file, questi non erano portabili su Windows, quindi abbiamo deciso di scrivere il nostro sistema di compilazione.

Avremmo potuto usare C, tuttavia abbiamo deciso di usare Python, c'erano poche ragioni. (Abbiamo anche riscritto il nostro sistema di controllo del codice sorgente in Python allo stesso tempo, questo è stato molto intergradato con il sistema di compilazione, quindi i file oggetto per i moduli archiviati potrebbero essere condivisi dagli sviluppatori.)

  • La maggior parte del nostro codice potrebbe essere costruita con poche semplici regole (solo poche migliaia di righe di Python per tutte le piattaforme, Windows, VMS e 6 versioni di Unix) che sono state guidate dalle convenzioni di denominazione dei file.

  • All'epoca RegEx non era molto standard tra i sistemi C su piattaforme diverse, Python aveva incorporato RegEx.

  • Alcuni moduli richiedevano passaggi di creazione personalizzati, Python consentiva il caricamento dinamico dei file di classe. Abbiamo permesso di utilizzare una classe personalizzata per creare un modulo (lib), basato sull'avere il file python con un nome magico nella cartella. Questa era la ragione killer per usare Python.

  • Abbiamo considerato Java, ma a quel punto non era disponibile su tutte le piattaforme.

(L'interfaccia utente per il nostro sistema di controllo del codice sorgente utilizzava un browser Web portatile su tutta la piattaforma. Questo era 6 mesi prima che avessimo una connessione a Internet. Dovevamo scaricare il browser su X25!)


Avendo lavorato su diversi sistemi bigish, a volte mi sento in grado di capire come si sviluppa lo sviluppo. Poi ho letto storie come questa. Sheesh.
dmckee,

@immibis Questa era la cosa alla moda da fare 15 anni fa. Ancor di più, questa pratica è stata effettivamente sostenuta e incoraggiata dai principali fornitori di Unix (SGI e DEC in particolare, ma anche IBM).
Oakad,

1
Le persone tendono a dimenticare che Unix significava "costoso". Windows ha vinto la guerra desktop / workstation essendo più economico. È per lo stesso motivo che in seguito Linux vinse la guerra dei server.
Slebetman,

1
Se voglio che un computer esegua il software che ho scritto da solo, allora voglio che sia flessibile e abbia 101 opzioni su come vengono compilati i kernel ecc. Tuttavia, se vendo software da installare sul computer del cliente, voglio che il cliente sia eseguire un sistema operativo non flessibile, quindi so che funzionerà sul loro computer se funziona sul mio. Questo è stato un grande fattore quando si considerava Linux come un fornitore di software: il supporto sembrava troppo costoso. Linux ha vinto le guerre di software del server ospitato , in cui il server è fornito dal fornitore del software, ad esempio la maggior parte dei software distribuiti sul web.
Ian,

3
@slebetman È giusto - Unix ha vinto la precedente "guerra" essendo più economico (rispetto ai LISPM e macchine simili). È stato assolutamente orribile, progettato in modo terribile e si è schiantato costantemente (ma si avvia molto più velocemente di un LISPM!: P), usando C come linguaggio di programmazione principale (una caduta piuttosto alta da LISP e simili), ma era molto più economico. In effetti, molti l'hanno adottato perché era gratuito (ci sono state molte mutazioni libere molto prima di Linux). In effetti, ho incontrato molti LISPer della vecchia scuola che preferivano MS-DOS agli unixes del tempo. Sì, quella orribile.
Luaan,

3

La risposta breve a questa domanda è che questo è uno strumento di costruzione . Uno strumento che automatizza l'uso di altri strumenti, con l'obiettivo di creare un prodotto finale da alcuni file di origine. Se stiamo scrivendo lo script di build nella stessa lingua del prodotto stesso, ci troviamo nei regni di strumenti specifici della lingua, che non verrebbero considerati strumenti di compilazione allo stesso modo.

Ciò solleva la domanda: perché i compilatori non forniscono il tipo di automazione di build a cui siamo abituati da strumenti come make? A cui la risposta è semplicemente perché make esiste . La filosofia Unix di "fai una cosa e fallo bene" suggerisce che non è responsabilità del compilatore fornire questo *. Detto questo, sono stato personalmente attraverso la mia parte di mal di testa e sarei interessato a provare un compilatore che fornisce il proprio sistema di build "nativo" senza virgolette.

Per un esempio di compilatore progettato in questo modo, vedere il Jai di Jon Blow (non ancora pubblicato), un linguaggio inteso come sostituto del C ++. I collegamenti ai discorsi e alle dimostrazioni del compilatore sono raccolti qui . Questo linguaggio viene compilato in codice byte che viene eseguito all'interno del compilatore, con la compilazione in binario come funzione standard fornita dalla libreria, accessibile dal codice byte. L'intenzione è consentire l'automazione della compilazione e la meta-programmazione all'interno della sintassi nativa del linguaggio.

* Uno sguardo a Visual Studio di Microsoft ti mostrerà un esempio della filosofia opposta. :)


2

Lo strumento di compilazione è innanzitutto uno strumento, proprio come 'gcc', 'ls', 'awk' o 'git'. Dai allo strumento un input (nome file, parametri, ecc.) E farà alcune cose di conseguenza.

Tutti questi strumenti ti consentono di trasmettere i tuoi input in modi che dovrebbero essere abbastanza semplici da scrivere e capire. Nel caso particolare degli strumenti di compilazione, l'input è un file di ricetta, un file che descrive come il progetto passa dai file di origine al prodotto finito.

Se la tua ricetta è semplice come passare nella cartella che contiene il progetto e il compilatore da usare, allora è sufficiente una "lingua" dichiarativa. Una volta che la ricetta diventa sempre più complicata, con più logica, diventa problematico gestirla con linguaggi dichiarativi e vengono utilizzate lingue più generiche.

Ora dovrebbe essere evidente che non esiste alcuna connessione tra la lingua utilizzata per scrivere le ricette di compilazione e le lingue utilizzate per scrivere il codice del prodotto semplicemente perché hanno scopi e requisiti diversi. Non esiste alcuna connessione anche tra la lingua in cui è scritto lo strumento di compilazione e la "lingua" in cui devono essere scritte le ricette di compilazione. Utilizzare sempre lo strumento migliore per il lavoro!

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.