Kann ich in Bash ein .cpp-Programm aufrufen?

Kann ich in Bash ein .cpp-Programm aufrufen?

Ich bin neu in der Bash-Programmierung. Ich möchte mein C++-Programm in einer Bash-Datei aufrufen.

Mein Programm ist myProg.cpp:

#include<iostream>
using namespace std;
int main()
{
   cout<<"Salam! World"<<endl;
return 0;
}

Und meine Bash-Datei ist myBash.sh. Wie kann ich mein obiges .cpp-Programm in der Datei aufrufen myBash.sh?

Antwort1

Sie müssen es zuerst kompilieren: Ändern Sie zuerst das aktuelle Arbeitsverzeichnis des Terminals in den Pfad Ihrer Quelldatei:

cd <path_to_cpp_file>/

Kompilieren Sie dann die Quelldatei:

g++ myProg.cpp -o myProg

Anschließend können Sie die kompilierte ausführbare Datei aus Ihrem bashSkript wie folgt aufrufen:

#!/bin/bash

# ...
<path_to_compiled_executable>/myProg
# ...

Antwort2

Da Ihrwahres ZielEs scheint darin zu bestehen, alles zu automatisieren, was zur Ausführung Ihres Programms getan werden muss. Ich schlage einen anderen Ansatz vor.Anstatt ein Shell-Skript zu schreiben, können Sie einMake-Datei.Wenn Sie möchten, können Sie in Ihr Makefile eine Regel für die Ausführung Ihrer ausführbaren Datei schreiben, sobald diese erstellt ist. Sie haben dann zwei Dateien – Ihre C++-Quellcodedatei und Ihr Makefile – und können einen einzigen Befehl effizient ausführen:

  1. Erstellt oder erstellt Ihr C++-Programm neu,genau dann, wenn es nötig ist.
  2. Führt Ihr Programm aus.

Die folgenden Abschnitte dieses Beitrags erklären, warum Sie eine .cppDatei nicht direkt aufrufen können (sondern zuerst eine ausführbare Datei daraus erstellen müssen); wie Sie sie installieren make, wie Sie sie verwenden und was sie im Hintergrund tut; und wie Sie häufige Fehler vermeiden. Aber falls Sie erst einmal ein Gefühl dafür bekommen möchten, wie dieser Ansatz aussieht, bevor Sie sich damit befassen, werden Sie make runnach dem Einfügen dieses0In Makefile:

all: myProg

run: all
    ./myProg

Mir gefällt das für diesen Zweck besser als ein Shell-Skript und ich denke, Ihnen geht es vielleicht genauso.

Hintergrund

Anders als einigegedolmetschte SprachenWie Python und Bash ist C++ einkompilierte Sprache.1In C++ geschriebene Programme müssengebautbevor sie ausgeführt werden. (Building wird manchmal auchKompilieren, obwohlKompilierenbezieht sich genauer auf einen der Schritte des Erstellens.) Sie können kein C++QuellcodeDatei; es muss stattdessen kompiliert werden inObjektcode2, in diesem FallMaschinensprache. Die Objektdateien müssen dann miteinander verknüpft werden, und selbst wenn es nur eine gibt, muss sie dennoch mit allengemeinsam genutzte Bibliothekenes verwendet. Durch Verknüpfen entsteht einausführbardie ausgeführt werden können.

Kurz gesagt, Sie müssen Ihr Programm erstellen, bevor Sie es ausführen.das erste MalVor nachfolgenden Läufen muss es nichtReerstellt, es sei denn, Sie haben den Quellcode geändert. In diesem Fall müssen Sie es erneut erstellen, wenn Ihre Änderungen im ausgeführten Programm berücksichtigt werden sollen.Das makeDienstprogrammist speziell für solche Situationen konzipiert, in denen man Aktionen ausführen möchtebedingtabhängig davon, ob und wann sie bereits erledigt wurden.

Bekommenmake

Möglicherweise ist der makeBefehl bereits installiert. Führen Sie ihn aus, um dies herauszufinden. Wenn er installiert ist, wird Folgendes angezeigt:

$ make
make: *** No targets specified and no makefile found.  Stop.

Um make zu erhalten, können Sie diemachen Installieren Sie makePaket, aber ich schlage vor, zu installierenBuild-Essential Installieren Sie build-essentialdas eine Reihe weiterer praktischer Tools bietet. (Vielleicht haben SieBuild-Essential Installieren Sie build-essentialum zu erhalten g++. Dies ist eine Möglichkeit, wie Sie möglicherweise bereits haben make.) Sie können es über das Software Center installieren oder den folgenden Befehl ausführen:

sudo apt-get update && sudo apt-get install build-essential

makeOhne Makefile

Um zu sehen, wie makees funktioniert, schlage ich vor, es zuerst ohne Makefile auszuführen und ihm den Basisnamen Ihrer Quellcodedatei zu übergeben:

$ make myProg
g++     myProg.cpp   -o myProg
$ ./myProg
Salam! World

Vergleicht bei nachfolgenden Ausführungen makedie Änderungszeitstempel (mZeits) auf den Eingabe- und Ausgabedateien und erstellt Ihr Programm nicht unnötig neu:

$ make myProg
make: 'myProg' is up to date.

Wenn Sie ändern myProg.cpp, wird der Änderungszeitstempel aktualisiert, sodass makeSie wissen, dass die Datei neu erstellt werden muss. (Sie können den Zeitstempel einer Datei auch mit demtouchBefehl, wenn Sie den Neuaufbau von davon abhängigen Ausgabedateien erzwingen müssen oder wollen. Und natürlich stellt das Löschen der Ausgabedateien auch sicher, dass sie beim Ausführen neu aufgebaut werden make– löschen Sie nur nicht die falsche Datei!)

$ touch myProg.cpp
$ make myProg
g++     myProg.cpp   -o myProg

Woher makeweiß ich, was zu tun ist, wenn ich laufe make myProg?

  • Das myProgArgument zu makeheißt aZiel.
  • Ziele sind oft, aber nicht immer, die Namen der zu erstellenden Dateien. Ziele können explizit in einem Makefile definiert werden.
  • Wenn in der Make-Datei kein Ziel definiert ist oder (wie in diesem Fall) keine Make-Datei vorhanden ist, makewird nach Eingabedateien (d. h. Quellcodedateien) gesucht, deren Namen darauf schließen lassen, dass sie zum Erstellen des Ziels bestimmt sind.
  • makeleitet aus der Endung einer Datei (in diesem Fall ) ab, welches Dienstprogramm und welche Syntax zum Erstellen einer Datei zu verwenden sind .cpp.

All dies kann angepasst werden, aber in einfachen Fällen wie diesem ist das oft nicht nötig.

Erstellen eines Makefiles zum Automatisieren des Erstellens und Ausführens Ihres Programms

Um komplexere Aufgaben als das Erstellen eines Programms aus einer einzelnen Quellcodedatei zu automatisieren, z. B. wenn mehrere Eingabedateien vorhanden sind oder (was für Ihre unmittelbaren Anforderungen eher zutrifft) Aktionen, die Sie neben der Ausführung des Compilers ausführen möchten, können Sie ein Makefile erstellen, um Ziele zu definieren makeund anzugeben, wie diese von anderen Zielen abhängen.

Das erste in einem Makefile definierte Ziel ist das Standardziel: Es wird makeversucht, es zu erstellen, wenn es ohne Befehlszeilenargumente ausgeführt wird (d. h., wenn Sie nur makeund nicht etwas wie ausführen make myProg).

Normalerweise verwendet man Makefiles, indem man ein Verzeichnis erstellt, das alle Quellcodedateien (und alle anderen Dateien) enthält, die zum Erstellen des Programms verwendet werden, sowie das Makefile, das normalerweise heißt Makefile. Unter diesem Namen makewird es automatisch gefunden.

Um ein Makefile zu erstellen, können Sie es ausführen myProgund es wird bei Bedarf automatisch zuerst erstellt. Legen Sie es myProg.cppin ein neues, ansonsten leeres Verzeichnis. Erstellen Sie in diesem Verzeichnis eine weitere Textdatei mit dem Namen Makefile.

Sie können hierfür jeden beliebigen Texteditor verwenden, aber das Rezept für eine Regel - die darunter aufgelisteten Befehle, die ausgeführt werden, um das Ziel zu erreichen - muss eingerückt werden mitRegisterkartenstattRäume.3Wenn Ihr Texteditor derzeit so konfiguriert ist, dass beim Drücken von die Einrückung mit Leerzeichen erfolgt Tab, sollten Sie dies ändern.

In Gedit oder Pluma würden Sie beispielsweise Folgendes eingeben:Bearbeiten > Voreinstellungen, drücke denEditorund stellen Sie sicher,Leerzeichen statt Tabulatoren einfügenist nicht aktiviert:

Screenshot des Dialogfelds „Einstellungen“ in Pluma – dessen Benutzeroberfläche im Wesentlichen der von Gedit entspricht – mit Angabe der Position des Kontrollkästchens „Leerzeichen statt Tabulatoren einfügen“ oben auf der Registerkarte „Editor“

Viele Editoren verwenden standardmäßig Tabulatoren und keine Leerzeichen zum Einrücken. Wenn Sie diese Einstellung also vorher nicht geändert haben, ist sie für Makefiles möglicherweise bereits richtig eingestellt.

Wenn Sie in Ihrem Editor sind und ihn (falls nötig) für die Einrückung mit Tabulatoren konfiguriert haben, geben Sie Folgendes ein:

all: myProg

run: all
    ./myProg

Wenn Sie dies kopieren und einfügen, wird es falsch seinweil Leerzeichen eingefügt werden, obwohl Ihr Texteditor sie beim Drücken von nicht erstellt Tab. (Das hängt mit der Art und Weise zusammen, wie Ask Ubuntu Code anzeigt.) Sie können aber einfach die vier vorangehenden Leerzeichen entfernen ./myProgund drücken, Tabum an ihrer Stelle einen Tabulator zu erstellen.

Einige Texteditoren zeigen einen Tabulator standardmäßig als 8 Leerzeichen oder eine andere Zahl an. Das ist in Ordnung.

Was dieses Makefile macht und wie man es benutzt

Verwenden Sie den Befehl:

  • make, um das Programm zu erstellen, sofern es nicht bereits erstellt ist und die ausführbare Datei dem Quellcode entspricht.Oder,
  • make run, um das Programm auszuführen,Bauen Sie es ggf. zuerst(d. h. wenn keine aktuelle ausführbare Datei vorhanden ist).

Dieses Makefile definiert zwei Ziele: allund run.

  • Das allZiel hat kein eigenes Rezept, sondern hängt vom myProgZiel ab. Dieses Ziel ist nicht explizit definiert, daher weist es implizit an, makeden Build myProgaus den Quellcodedateien zu versuchen, die im aktuellen Verzeichnis dafür verfügbar sind. (Siehe diemakeOhne MakefileWeitere Einzelheiten finden Sie im Abschnitt oben.)

    Da alldas erste in explizit definierte Ziel ist Makefile, wird es erstellt, wenn makeaus dem Verzeichnis ausgeführt wird, in dem Makefilees sich befindet. Daher haben wir alles so eingerichtet, dass das makealleinige Ausführen dem Ausführen von entspricht make all.

  • Das runZiel führt das Programm aus. Das Rezept besteht aus dem Befehl, der dies tut ./myProg. rundeklariert das allZiel als Abhängigkeit. Dadurch wird beim Ausführen neu erstellt make run, myProgwenn die aktuelle myProgausführbare Datei nicht aktuell ist (oder noch nicht existiert).

    Wir hätten genauso gut rundepend on myProgstatt on machen können all, aber wir hätten trotzdem das explizite allZiel (oder ein gleichwertiges Ziel mit einem anderen Namen) benötigt, um zu verhindern, rundass es das Standardziel ist. Wenn Sie möchten, dass Ihr Programm erstellt wird,und Rennselbst wenn Sie makealleine laufen, könnten Sie dies tun.

    Ein weiterer Vorteil der Zielabhängigkeit allbesteht darin, dass später weitere Aktionen ausgeführt werden müssen, bevor Ihr Programm ausgeführt werden soll. Sie können der Regel dann ein Rezept für hinzufügen all.

Die Verwendung des Makefiles zum Ausführen des Programms sieht folgendermaßen aus, wenn es erstellt werden muss:

$ cd myProg/
$ make run
g++     myProg.cpp   -o myProg
./myProg
Salam! World

Oder dies, wenn es nicht gebaut werden muss:

$ make run
./myProg
Salam! World

Und wenn Sie nur sicherstellen möchten, dass das Programm erstellt wurde (seit der letzten Änderung der Quellcodedatei)ohne das Programm auszuführen, führen Sie es einfach makeohne Argumente aus:

$ make      # Here, I run make and myProg isn't current.
g++     myProg.cpp   -o myProg
$ make      # Running "make" again after "make" or "make run" does nothing.
make: Nothing to be done for 'all'.

( make myProgwird auch weiterhin funktionieren.)

Eine Verfeinerung: Benutzerdefinierte Compiler-Flags

makeist ein extrem leistungsfähiges Werkzeug, das für einfache Zwecke wie diesen praktisch ist, sich aber auch für große, komplexe Projekte eignet. Der Versuch, alle Funktionen im Detail zu beschreiben, makewürde ein ganzes Buch füllen (insbesondereDieses hier).

Aber mir ist aufgefallen, dass Sie vielleicht Warnungen vom Compiler sehen möchten, wenn etwas den Abschluss des Builds nicht verhindert, aber dennoch ein potenzieller Fehler vorliegt. Diese werden zwar nicht alle Fehler in den von Ihnen geschriebenen Programmen aufdecken, aber sie könnten viele davon aufdecken.

Wenn Sie GCC verwenden (wie bei dem g++Befehl), empfehle ich, zumindest -Wallan den Compiler zu übergeben. Dies ermöglicht eigentlich nichtalleWarnungen, aber den Großteil der übrigen können Sie mit aktivieren -Wextra. Manchmal möchten Sie vielleicht auch -pedantic. (Sieheman gccUnd3.8Optionen zum Anfordern oder Unterdrücken von WarnungenimGCC-Referenzhandbuch.)

Um diese Flags manuell aufzurufen g++, führen Sie Folgendes aus:

g++ -Wall -Wextra -pedantic -o myProg myProg.cpp

Um makeden C++-Compiler ( g++) mit den Flags -Wall, -Wextra, und aufzurufen -pedantic, fügen Sie CXXFLAGS=oben von eine Zeile mit ihnen hinzu Makefile.

CXXFLAGS=-Wall -Wextra -pedantic

all: myProg

run: all
    ./myProg

Auch wenn myPrognoch vorhanden und neuer als ist myProg.cpp, wird das Programm beim Ausführen makeoder make runnach der Bearbeitung Makefiletrotzdem erneut erstellt, da Makefilejetzt neuer als ist myProg. Das ist gut, denn:

  • In diesem Fall werden Ihnen beim Neuerstellen der ausführbaren Datei Warnungen angezeigt, sofern welche vorhanden sind (bei diesem bestimmten Programm sollte dies nicht der Fall sein).
  • Allgemeiner gesagt: Manchmal bearbeiten Sie ein Makefile, weil Sie möchten, dass unterschiedliche Dateien erstellt werden oder dass diese unterschiedliche Inhalte haben. (Wenn Sie beispielsweise das -O3Flag für umfangreiche Optimierungen oder -gzum Generieren von Debugsymbolen durch den Compiler hinzugefügt hätten, myProgwäre die resultierende ausführbare Datei anders.)

Weitere Informationen

Anmerkungen

0: Ich empfehle, weiterzulesen, um zu erfahren, wie das funktioniert. Aber falls Sie es zuerst selbst versuchen möchten: Sie müssen Zeilen mit Tabulatoren statt mit Leerzeichen einrücken.

1: Streng genommen könnte praktisch jede Programmiersprache entweder interpretiert oder kompiliert werden, je nachdem, wasImplementierungendafür wurden geschrieben. Für einige Sprachen gibt es sowohl Interpreter als auch Compiler. Interpretiertes C++ ist jedoch ungewöhnlich - obwohlnicht unbekannt.

2: Gebäude aufteilen inKompilierenUndVerlinkungund Aufruf der Übersetzung einer C++-Quellcodedatei (.cc/.cpp/.cxx/.C) in ObjektcodeKompilieren, ist nicht die ganze Geschichte. Programme in C und C++ (und einigen anderen Sprachen) sind zunächstvorverarbeitet. In Ihrem ProgrammC-Präprozessorersetzt #include<iostream>durch den Inhalt der <iostream>Header-Datei, bevor die eigentliche Kompilierung beginnt. Und im engsten Sinne wandelt die Kompilierung den Quellcode inAssemblersprachestatt Objektcode. Viele Compiler (wie GCC/ g++) können Kompilierung und Assembly in einem einzigen Schritt kombinieren und erzeugen keinen Assemblercode, wenn sie nicht dazu aufgefordert werden.

Während die Vorverarbeitung ein separater Schritt ist, führen GCC und andere Compiler den Präprozessor automatisch aus. Ebenso können sie den Linker automatisch ausführen, weshalb die gesamte Sequenz vonVorverarbeitung,Zusammenstellung,Montage, UndVerknüpfungwird manchmal als "Kompilieren" statt als "Erstellen" bezeichnet. (Beachten Sie auch, dass das Erstellen mehr als diese Schritte umfassen kann - es kann beispielsweise das Generieren von Ressourcendateien, das Ausführen vonein Skript zur Konfiguration der Erstellung, usw.)

3: Sie müssen nur im Makefile selbst mit Tabulatoren einrücken. Die Verwendung eines Makefiles stellt keine Anforderungen an die Art und Weise, wie Sie Ihre C++-Quellcodedateien selbst schreiben. Sie können die Einrückung jederzeit wieder von Tabulatoren auf Leerzeichen umstellen, wenn Sie an anderen Dateien arbeiten. (Und wenn SieWirklichWenn Sie Einrückungen mit Tabulatoren in einem Makefile nicht mögen, können Sie die.RECIPEPREFIX spezielle Variable.)

Antwort3

Hier ist ein Beispiel: von myBash.sh

#!/bin/sh
g++ myProg.cpp -o myProg
./myProg

verwandte Informationen