Warum verwenden Build-Tools eine andere Skriptsprache als die zugrunde liegende Programmiersprache?

23

Ich habe kürzlich einige Build-Tools für ein Nodejs-Projekt verwendet, als ich feststellte, dass das Hauptbuild-Tool / -System der meisten Sprachen eine andere Sprache als die zugrunde liegende Programmiersprache selbst verwendet.

Beispielsweise verwendet make weder C noch C ++ zum Schreiben von Skripten, und ant (noch Maven) verwendet Java nicht als Skriptsprache.

Neuere Sprachen wie Ruby verwenden dieselbe Sprache für Build-Tools wie Rake , was für mich sinnvoll ist. Aber warum war das nicht immer so? Was ist der Vorteil eines Build-Tools, das eine andere Sprache als die zugrunde liegende Sprache verwendet?

joshin4colours
quelle
14
Vielleicht ist die Allzwecksprache nicht gut genug für den speziellen Gebrauch des Tools? Zum Beispiel würde ich keine make-Dateien in C schreiben wollen! Manchmal ist ein DSL besser.
Andres F.
13
Betrachten Sie es aus einem anderen Blickwinkel: Verwenden Sie make zum Schreiben von Anwendungssoftware.
Whatsisname
4
Dieser Artikel befasst sich hauptsächlich mit dem, was Lisp nach Meinung des Autors großartig macht, enthält jedoch einige relevante Informationen darüber, warum Ant XML anstelle von Java verwendet.
8bittree,
6
Wenn Sie ein Programm in C schreiben wollten, das das Erstellen von C-Programmen automatisiert, würden Sie dann nicht einfach wieder schreiben make(was in C sowieso implementiert ist)?
Brandin
6
@ joshin4colours make ist in C geschrieben. Die Sprache, die make verwendet, ist jedoch eine deklarative Sprache, die die Shell nach Bedarf aufruft.

Antworten:

36

Die Wahl der Programmiersprache, die verwendet werden soll, um etwas zu erledigen, muss von den spezifischen Merkmalen dieses Ziels und nicht von den anderen Aufgaben im Zusammenhang mit diesem Projekt abhängen.

Ein Build-Tool erledigt eine ganz bestimmte Aufgabe, und unabhängig davon, welche Sprache Sie für das Hauptprojekt verwenden, ist ein Build-Tool eine Software für sich.

Der Versuch, das Hauptprojekt und sein Build-Tool miteinander zu verknüpfen, könnte eine sehr schlechte Entscheidung sein. Was Sie mit einem Build-Tool benötigen sollten, ist hauptsächlich ein schneller Prozess einfacher Regeln mit einer schnellen Verwaltung von Dateien und E / A.

Wenn Sprachen wie Ruby sich selbst verwenden, um ihr Build-Tool zu implementieren, hängt dies mehr mit den Funktionen dieser Sprache zusammen als mit der Annahme, dass alles in derselben Sprache geschrieben bleiben muss.

Nicolás
quelle
18

Es ist nicht unmöglich, ein Build-Tool zu schreiben, das eine Sprache wie C oder Java als Skriptsprache verwendet. Build-Tools profitieren jedoch von der Verwendung deklarativerer Skriptsprachen. Stellen Sie sich vor, wie schwierig es ist, ein Makefile (oder build.xml oder was auch immer) in C zu schreiben.

Build-Tools profitieren von der Verwendung von DSLs, eine Aufgabe, für die C keine besonders gute Wahl ist. C ist zu allgemein für ein Build-Tool und zu sehr mit fehleranfälligen Details befasst. Sie möchten sich beispielsweise nicht mit expliziter Speicherverwaltung in einem Build-Tool befassen! Selbst wenn Sie eine C-ähnliche Syntax verwenden, würden Sie wahrscheinlich Garbage Collection in Ihrem Skript-Tool verwenden. Warum sollten Sie dann nicht einfach ein dediziertes DSL verwenden?

Es ist sinnvoll, dass Ruby dafür verwendet werden kann, da es eine übergeordnete, deklarativere Sprache als C oder Java ist. Siehe auch: Gradle, sbt.

Andres F.
quelle
13
Imagine the pain and boilerplate of writing a makefile (or build.xml, or whatever) in C.Stellen Sie sich vor, wie schwierig es ist, nicht-triviale bedingte Logik (Sie wissen, Standard-Imperative) in einem deklarativen XML-Skript auszudrücken. Oh, warte, du musst es dir nicht vorstellen. Sie mussten sich wahrscheinlich damit auseinandersetzen, und es war wahrscheinlich eineinhalb Chaos, nicht wahr? Builds sind eine der schlechtesten Möglichkeiten für eine deklarative Skriptsprache, da schwerwiegende Probleme schnell an die Grenzen der Deklarativität stoßen und diejenigen, die nicht einfach genug sind, um kein Build-Tool zu benötigen.
Mason Wheeler
7
@MasonWheeler Es gibt Fälle, in denen mich die vorhandenen Build-Tools in Mitleidenschaft gezogen haben, ja. Keiner von ihnen wäre durch die Verwendung einer einfachen C-ähnlichen imperativen Sprache geholfen worden. Ich halte etwas wie Ruby für wahrscheinlich ideal: deklarativ und imperativ genug, je nach Bedarf. C würde mir Albträume für diese Aufgabe geben. Für mich sind Build-Systeme ein guter Anwendungsfall für (meistens) deklarative DSLs: Sie kümmern sich darum, was zu tun ist, und nicht darum, wie (meistens).
Andres F.
2
Meinetwegen. Ich habe immer gedacht, dass C eine dieser Technologien ist, um ganz ehrlich zu sein, "wenn X die Antwort ist, stellst du die falsche Frage". Es ist nur so, dass die Arbeit mit XML- "Skripten" jedes Mal ein Albtraum war, wenn ich mich mit einem befassen musste. Ich stimme zu, dass eine übergeordnete imperative Sprache mit DSL-Fähigkeiten ideal wäre.
Mason Wheeler
@AndresF .: Zum Erstellen von Dateien sind verschiedene Ansätze erforderlich. Der gewünschte Ausgangszustand wird deklarativ angegeben, die zur Erreichung dieses Zustands erforderlichen Maßnahmen sind jedoch zwingend vorgeschrieben.
Supercat
1
@MasonWheeler Ich denke, das ist genauso ein Problem der Leute, die die Konfigurationssprache entworfen haben, wie XML selbst. Der häufige Fehler von Autoren solcher Sprachen ist die Annahme, dass etwas, das sich in XML befindet, automatisch von Menschen gelesen werden kann. (Ich weiß, dass ich diesen Fehler öfter gemacht habe, als ich mag. Er ist so verlockend.) Eine gut gestaltete und schlanke Konfigurationssprache funktioniert genauso gut über XML wie in jeder anderen Form.
Biziclop
12

Lassen Sie uns Ihnen ein reales Beispiel geben.

Vor ungefähr 15 Jahren arbeitete ich an der Portierung eines großen Systems, das in C von Unix auf Windows geschrieben wurde. Das waren ungefähr 3 Millionen Codezeilen. Um Ihnen eine Vorstellung von der Skalierung zu geben, dauerte das Kompilieren auf einigen unserer Unix-Systeme (RS6000) über 24 Stunden. Windows konnte das System in etwa 4 Stunden kompilieren.

(Wir hatten auch 2 Millionen Codezeilen in unserer eigenen interpretierten Sprache, entschieden uns jedoch, unsere Sprache nicht für die Build-Systeme zu verwenden, da sie niemals für die Dateiverarbeitung entwickelt wurde. Außerdem benötigten wir ein Build-System, um den C-Code zu kompilieren, der unsere Sprache implementierte .)

Zu der Zeit, als das Build-System in einer Mischung aus Shell-Skripten und Make-Dateien geschrieben wurde, waren diese nicht auf Windows übertragbar - daher entschieden wir uns, unser eigenes Build-System zu schreiben.

Wir hätten C verwenden können, aber wir haben uns für Python entschieden, es gab nur wenige Gründe. (Gleichzeitig haben wir unser Quellcodeverwaltungssystem in Python umgeschrieben. Dies war eng mit dem Build-System verknüpft, sodass die Entwickler die Objektdateien für die eingecheckten Module gemeinsam nutzen konnten.)

  • Der größte Teil unseres Codes kann mit ein paar einfachen Regeln erstellt werden (nur ein paar tausend Zeilen Python für alle Plattformen, Windows, VMS und 6 Versionen von Unix), die von den Namenskonventionen der Dateien abgeleitet wurden.

  • Zu der Zeit, als RegEx zwischen C-Systemen auf verschiedenen Plattformen kein Standard war, hatte Python RegEx eingebaut.

  • Für einige Module waren benutzerdefinierte Erstellungsschritte erforderlich. In Python konnten Klassendateien dynamisch geladen werden. Wir erlaubten die Verwendung einer benutzerdefinierten Klasse zum Erstellen eines Moduls (lib), basierend auf der Python-Datei mit einem magischen Namen im Ordner. Dies war der Mördergrund für die Verwendung von Python.

  • Wir haben Java in Betracht gezogen, aber es wurde zu diesem Zeitpunkt noch nicht auf allen Plattformen ausgeliefert.

(Die Benutzeroberfläche für unser Quellcodeverwaltungssystem verwendete einen Webbrowser, der plattformübergreifend portabel war. Dies war 6 Monate, bevor wir eine Internetverbindung hatten. Wir mussten den Browser über X25 herunterladen!)

Ian
quelle
Nachdem ich an mehreren großen Systemen gearbeitet habe, habe ich manchmal das Gefühl, einen Überblick darüber zu haben, wie die Entwicklung skaliert. Dann lese ich solche Geschichten. Meine Güte.
dmckee
@immibis Das war vor 15 Jahren in Mode. Diese Vorgehensweise wurde sogar von den führenden Unix-Anbietern (insbesondere SGI und DEC, aber auch IBM) befürwortet und gefördert.
Oakad
1
Die Leute neigen dazu zu vergessen, dass Unix "teuer" bedeutete. Windows hat den Desktop / Workstation-Krieg gewonnen, indem es billiger war. Aus dem gleichen Grund hat Linux später den Serverkrieg gewonnen.
Slebetman
1
Wenn ich möchte, dass ein Computer Software ausführt, die ich selbst geschrieben habe, dann möchte ich, dass er flexibel ist und über 101 Optionen zum Kompilieren des Kernels usw. verfügt. Wenn ich jedoch Software verkaufe, die auf dem Computer des Kunden installiert werden soll, möchte ich, dass der Kunde es ist ein Betriebssystem laufen zu lassen, das nicht flexibel ist, so dass ich weiß, dass es auf ihrem Computer funktioniert, wenn es auf meinem funktioniert. Das war ein wichtiger Faktor, wenn man Linux als Softwareanbieter ansieht - der Support sah einfach zu teuer aus. Linux hat die gehosteten Server-Software-Kriege gewonnen, bei denen der Server vom Softwarehersteller bereitgestellt wird - z. B. die meisten im Web bereitgestellten Software.
Ian
3
@slebetman Es ist nur fair - Unix hat den vorherigen "Krieg" gewonnen, indem es billiger war (im Vergleich zu LISPMs und ähnlichen Maschinen). Es war absolut schrecklich, schrecklich designt und stürzte ständig ab (aber es bootet so viel schneller als ein LISPM!: P), wobei C als primäre Programmiersprache verwendet wurde (ziemlich viel weniger als LISP und ähnliches), aber es war viel billiger. Tatsächlich haben viele es übernommen, weil es kostenlos war (es gab viele freie Mutationen lange vor Linux). Tatsächlich habe ich viele LISPer der alten Schule getroffen, die MS-DOS Unixen der Zeit vorzogen. Ja, das ist schrecklich.
Luaan,
3

Die kurze Antwort auf diese Frage lautet, dass dies ein Build-Tool ist . Ein Tool, das die Verwendung anderer Tools automatisiert, um aus einigen Quelldateien ein Endprodukt zu erstellen. Wenn wir das Build-Skript in derselben Sprache wie das Produkt selbst schreiben, befinden wir uns im Bereich der sprachspezifischen Tools, die nicht auf die gleiche Weise als Build-Tools betrachtet werden.

Dies wirft die Frage auf: Warum stellen Compiler nicht die Art von Build-Automatisierung bereit, die wir von Tools wie make gewohnt sind? Auf die lautet die Antwort einfach, weil make existiert . Die Unix-Philosophie "Mach eins und mach es gut" legt nahe, dass es nicht in der Verantwortung des Compilers liegt, dies bereitzustellen *. Das heißt, ich habe persönlich meinen Teil der Kopfschmerzen miterlebt und wäre daran interessiert, einen Compiler zu testen, der ein eigenes "natives" Build-System ohne Anführungszeichen bereitstellt.

Ein Beispiel für einen so gestalteten Compiler finden Sie in Jon Blow 's (noch unveröffentlichtem) Jai, einer Sprache, die als C ++ - Ersatz gedacht ist. Links zu Vorträgen und Demos des Compilers werden gesammelt hier . Diese Sprache wird in Bytecode kompiliert, der im Compiler ausgeführt wird. Die Kompilierung in Binärcode ist eine Standardfunktion der Bibliothek, auf die über den Bytecode zugegriffen werden kann. Die Absicht ist, sowohl Build-Automatisierung als auch Meta-Programmierung innerhalb der nativen Syntax der Sprache zu ermöglichen.

* Ein Blick auf Microsoft Visual Studio zeigt Ihnen ein Beispiel für die entgegengesetzte Philosophie. :)

Haddon CD.
quelle
2

Das Build-Tool ist in erster Linie ein Tool, genau wie 'gcc', 'ls', 'awk' oder 'git'. Sie geben dem Tool eine Eingabe (Dateiname, Parameter usw.) und es wird einige Dinge entsprechend tun.

Mit all diesen Tools können Sie Ihre Eingaben so weitergeben, dass sie einfach zu schreiben und zu verstehen sind. Im speziellen Fall von Build-Tools ist die Eingabe eine Rezeptdatei, eine Datei, die beschreibt, wie Ihr Projekt von den Quelldateien bis zum fertigen Produkt verläuft.

Wenn Ihr Rezept so einfach ist wie das Übergeben des Ordners, der das zu verwendende Projekt und den Compiler enthält, ist eine deklarative "Sprache" ausreichend. Sobald das Rezept immer komplizierter und logischer wird, wird es schwierig, es mit deklarativen Sprachen zu handhaben, und es werden allgemeinere Sprachen verwendet.

Es sollte jetzt offensichtlich sein, dass es keinen Zusammenhang zwischen der Sprache, in der Ihre Build-Rezepte geschrieben wurden, und den Sprachen, in denen Ihr Produktcode geschrieben wurde, gibt, nur weil sie unterschiedliche Zwecke und Anforderungen haben. Es besteht kein Zusammenhang zwischen der Sprache, in der das Build-Tool geschrieben ist, und der "Sprache", in der die Build-Rezepte geschrieben werden sollen. Verwenden Sie immer das beste Tool für den Job!

Tibos
quelle