web-dev-qa-db-fra.com

Puis-je appeler un programme .cpp dans Bash?

Je suis nouveau dans la programmation Bash. Je souhaite appeler mon programme C++ dans un fichier Bash.

Mon programme est myProg.cpp:

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

Et mon fichier bash est myBash.sh. Comment puis-je appeler mon programme ci-dessus .cpp dans le fichier myBash.sh?

4
Prince MUghal

Vous devez d'abord le compiler: commencez par changer le répertoire de travail actuel de Terminal par le chemin de votre fichier source:

cd <path_to_cpp_file>/

Puis compilez le fichier source:

g++ myProg.cpp -o myProg

Vous pouvez ensuite appeler l'exécutable compilé à partir de votre script bash comme suit:

#!/bin/bash

# ...
<path_to_compiled_executable>/myProg
# ...
8
kos

Étant donné que votre objectif réel semble être d'automatiser tout ce qui doit être fait pour exécuter votre programme, je suggère une approche différente. Au lieu d'écrire un script shell, vous pouvez utiliser un makefile . Si vous le souhaitez, vous pouvez écrire une règle dans votre makefile. pour exécuter votre exécutable une fois qu'il est construit. Vous aurez alors deux fichiers - votre fichier de code source C++ et votre fichier makefile - et vous pourrez exécuter une seule commande efficace:

  1. Construit ou reconstruit votre programme C++, si et seulement si nécessaire.
  2. Exécute votre programme.

Les sections suivantes de ce post expliquent pourquoi vous ne pouvez pas appeler directement un fichier .cpp (vous devez d’abord créer un fichier exécutable à partir de celui-ci); comment installer make, comment l'utiliser et ce qu'il fait en coulisse; et comment éviter les pièges courants. Mais si vous voulez avoir une idée de ce à quoi ressemble cette approche avant de plonger dedans, vous lancerez make run après avoir mis ceci 0  dans Makefile:

all: myProg

run: all
    ./myProg

J'aime mieux cela à cet effet qu’un script Shell, et je pense que vous pourriez le faire aussi.

Contexte

Contrairement à certains langages interprétés comme Python et Bash, C++ est un langage compilé . 1  Les programmes écrits en C++ doivent être construits avant leur exécution. (Building est aussi parfois appelé compilation, bien que compilation fasse plus proprement référence à l'une des étapes de la construction.) Vous ne pouvez pas exécuter C++ code source fichier; il doit plutôt être compilé en code objet 2 , dans ce cas langage machine . Les fichiers objets doivent alors être liés ensemble, et même s’il n’en existe qu’un, il doit quand même être lié à n’importe quelle bibliothèques partagées qu’elle utilise. La liaison produit un exécutable qui peut être exécuté.

En bref, vous devez créer votre programme avant de l'exécuter, la première fois. Avant les exécutions suivantes, il n'est pas nécessaire que re soit généré, à moins que vous n'ayez modifié son code source. Dans ce cas, vous devez le reconstruire à nouveau si vous souhaitez que vos modifications soient reflétées dans le programme exécuté. L'utilitaire make est conçu spécifiquement pour ce type de situation, dans lequel on souhaite effectuer des actions conditionnellement ​​en fonction du fait qu'elles ont déjà été effectuées ou non.

Obtenir make

La commande make est peut-être déjà installée; essayez de l'exécuter pour le savoir. S'il est installé, vous verrez quelque chose comme:

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

Pour obtenir vous pouvez installer le makeInstall make paquet, mais je suggère d'installer build-essentialInstall build-essential qui fournit un certain nombre d’outils utiles. (Vous avez peut-être installé build-essentialInstall build-essential pour obtenir g++, ce qui peut être déjà un moyen d'avoir make.) Vous pouvez utiliser le Centre logiciel pour l'installer ou exécuter la commande suivante:

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

make Sans Makefile

Pour voir comment fonctionne make, je suggère de l'exécuter sans makefile, en lui passant le nom de base de votre fichier de code source:

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

Lors des exécutions suivantes, make compare les horodatages de modification ( mtime s) sur les fichiers d'entrée et de sortie et ne reconstruira pas votre programme inutilement:

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

Lorsque vous modifiez myProg.cpp, son horodatage de modification est mis à jour. make saura le reconstruire. (Vous pouvez également mettre à jour l'horodatage d'un fichier à l'aide de la commande touch , si vous souhaitez ou souhaitez forcer la reconstruction de tous les fichiers de sortie qui en dépendent. Et bien sûr, la suppression des fichiers de sortie garantira également qu'ils le soient. reconstruit lorsque vous exécutez make-- ne supprimez pas le mauvais fichier!)

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

Comment make sait-il quoi faire lorsque vous exécutez make myProg?

  • L'argument myProg de make est appelé cible.
  • Les cibles sont souvent, mais pas toujours, les noms des fichiers à créer. Les cibles peuvent être définies explicitement dans un makefile.
  • Lorsqu'une cible n'est pas définie dans le fichier makefile ou (comme dans ce cas), il n'y a pas de fichier makefile, make recherche les fichiers d'entrée (c'est-à-dire le code source) nommés de manière à suggérer qu'ils sont destinés à la construction de la cible.
  • make indique quel utilitaire et quelle syntaxe utiliser pour créer un fichier à partir de son suffixe (dans ce cas, .cpp).

Tout cela peut être personnalisé, mais dans des cas simples, ce n'est souvent pas nécessaire.

Création d'un Makefile pour automatiser la construction et l'exécution de votre programme

Pour automatiser des tâches plus complexes que la création d'un programme à partir d'un seul fichier de code source, par exemple s'il existe plusieurs fichiers d'entrée ou des actions (plus applicables pour vos besoins immédiats) que vous souhaitez effectuer en plus de l'exécution du compilateur, vous pouvez créer un fichier makefile pour définir des cibles. pour make et spécifier comment ils dépendent d'autres cibles.

La première cible définie dans un makefile est la cible par défaut: il s'agit de ce que make tente de générer lorsqu'il est exécuté sans argument de ligne de commande (c'est-à-dire lorsque vous exécutez uniquement make et non quelque chose comme make myProg).

La méthode habituelle d'utilisation de makefiles est de créer un répertoire contenant tous les fichiers de code source (et tous les autres fichiers) utilisés pour générer votre programme, ainsi que le fichier Make, généralement appelé Makefile. Par ce nom, make le trouvera automatiquement.

Pour créer un fichier makefile, exécutez myProg et le créera automatiquement d’abord en cas de besoin, mettez myProg.cpp dans un nouveau répertoire, sinon vide. Créez un autre fichier texte dans ce répertoire appelé Makefile.

Vous pouvez utiliser n'importe quel éditeur de texte pour cela, mais la recette d'une règle (les commandes répertoriées sous celle-ci qui seront exécutées pour créer sa cible) doit être indentée avec tabs plutôt que espaces. 3  Donc, si votre éditeur de texte est actuellement configuré pour mettre en retrait avec des espaces lorsque vous appuyez sur Tab, vous devriez changer cela.

Par exemple, dans Gedit ou Pluma, vous devez entrer dans Édition> Préférences, cliquer sur l'onglet Éditeur et vous assurer que Insérer des espaces au lieu des onglets est décoché:

Screenshot showing the Preferences dialog box in Pluma--whose interface is essentially the same as in Gedit--indicating the location of the Insert spaces instead of tabs checkbox near the top of the Editor tab

De nombreux éditeurs utilisent par défaut des tabulations et non des espaces. Par conséquent, si vous n'avez pas modifié ce paramètre auparavant, il est peut-être déjà défini correctement pour les fichiers Make.

Une fois que vous êtes dans votre éditeur et (si nécessaire) configuré pour mettre en retrait avec des tabulations, mettez ceci dans:

all: myProg

run: all
    ./myProg

Si vous copiez et collez ceci, ce sera faux car des espaces seront copiés même si votre éditeur de texte ne les crée pas lorsque vous appuyez sur Tab. (Cela concerne la manière dont Ask Ubuntu affiche le code.) Mais vous pouvez simplement supprimer les quatre espaces précédant ./myProg et appuyer sur Tab faire un onglet à leur place.

Certains éditeurs de texte affichent par défaut un onglet sous forme de 8 espaces ou un autre nombre. C'est très bien.

Ce que Makefile fait et comment l'utiliser

Utilisez la commande:

  • make, pour construire le programme sauf s’il est déjà construit et que l’exécutable est à jour par rapport au code source. Ou,
  • make run, pour exécuter le programme, le construisant d’abord, si nécessaire (c’est-à-dire s’il n’existe aucun exécutable en cours).

Ce fichier make définit deux cibles: all et run.

  • La cible all n'a pas de recette propre, mais dépend de la cible myProg. Cette cible n'est pas explicitement définie. Elle indique donc implicitement à make d'essayer de générer myProg à partir des fichiers de code source disponibles dans le répertoire en cours. (Voir la section make Sans un Makefile ci-dessus pour plus de détails.)

    Étant donné que all est la première cible explicitement définie dans Makefile, il sera créé lorsque make sera exécuté à partir du répertoire dans lequel réside Makefile. Ainsi, nous avons mis les choses en place. Exécuter make équivaut à exécuter make all.

  • La cible run exécute le programme. Sa recette comprend la commande qui le fait, ./myProg. run déclare la cible all comme dépendance. Ainsi, lorsque vous exécutez make run, myProg est reconstruit si l'exécutable actuel myProg n'est pas à jour (ou n'existe pas encore).

    Nous aurions tout aussi bien pu faire que run dépende de myProg plutôt que de all, mais nous aurions quand même eu besoin de la cible explicite all (ou d'une cible équivalente d'un nom différent) pour éviter que run ne soit la cible par défaut. Bien sûr, si vous voulez que votre programme soit construit et exécutez même lorsque vous exécutez make par lui-même, vous pouvez le faire.

    Le fait de dépendre de la cible all offre un autre avantage, au cas où il y aurait plus d'actions à entreprendre avant que votre programme ne soit exécuté. Vous pouvez ensuite ajouter une recette à la règle pour all.

Utiliser le makefile pour exécuter le programme ressemble à ceci, s'il doit être construit:

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

Ou ceci, s'il n'a pas besoin d'être construit:

$ make run
./myProg
Salam! World

Et si vous voulez juste vous assurer que le programme est construit (puisque le fichier de code source a été modifié pour la dernière fois) sans exécuter le programme, exécutez simplement make sans argument:

$ 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 myProg fonctionnera toujours aussi.)

Un raffinement: les drapeaux de compilation personnalisés

make est un outil extrêmement puissant, utile pour des applications simples comme celle-ci, mais également bien adapté aux grands projets complexes. Tenter de détailler tout ce que vous pouvez faire avec make serait un livre entier (en particulier, celui-ci ).

Mais je me suis dit que vous voudriez peut-être voir les avertissements du compilateur, quand quelque chose n'empêche pas la construction de se terminer mais reste une erreur potentielle. Ceux-ci ne détectent pas tous les bogues des programmes que vous écrivez, mais ils peuvent en détecter beaucoup.

Lorsque vous utilisez GCC (comme avec la commande g++), je recommande de transmettre au moins -Wall au compilateur. En fait, cela n'active pas les avertissements all, mais vous pouvez activer la plupart des autres avec -Wextra. Parfois, vous voudrez peut-être aussi -pedantic. (Voir man gcc et .8 Options permettant de demander ou de supprimer des avertissements dans le manuel de référence GCC .)

Pour appeler g++ manuellement avec ces indicateurs, vous devez exécuter:

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

Pour que make appelle le compilateur C++ (g++) avec les indicateurs -Wall, -Wextra et -pedantic, ajoutez une ligne CXXFLAGS= avec eux en haut de Makefile.

CXXFLAGS=-Wall -Wextra -pedantic

all: myProg

run: all
    ./myProg

Même si myProg existe toujours et est plus récent que myProg.cpp, l'exécution de make ou make run après la modification de Makefile continuera à générer le programme, car Makefile est désormais plus récent que myProg. C'est une bonne chose car:

  • Dans ce cas, la reconstruction de l'exécutable vous fait voir des avertissements s'il y en a (ce qui ne devrait pas être le cas pour ce programme particulier).
  • Plus généralement, parfois, lorsque vous éditez un fichier Make, c'est parce que vous voulez que différents fichiers soient produits, ou avec un contenu différent. (Par exemple, si vous aviez ajouté l'indicateur -O3 pour les optimisations lourdes ou -g pour que le compilateur génère des symboles de débogage, l'exécutable myProg résultant serait différent.)

Lectures complémentaires

Notes

0 : Je recommande de lire plus loin pour voir comment faire fonctionner ce travail. Mais au cas où vous voudriez essayer d’abord vous-même: vous devez mettre en retrait les lignes avec des tabulations plutôt que des espaces.

1 : À proprement parler, n'importe quel langage de programmation peut être interprété ou compilé en fonction de ce que implémentations ont été écrits. Des interprètes et des compilateurs existent pour certaines langues. Cependant, interprété en C++ est rare - bien que pas inouï .

2 : division du bâtiment en compilation et lien, et appel de la traduction d'un code source C++ fichier (.cc/.cpp/.cxx/.C) en code objet compiler, n’est pas l’ensemble de l’histoire. Les programmes en C et C++ (et quelques autres langages) sont les premiers prétraités . Dans votre programme, le préprocesseur C remplace #include<iostream> par le contenu du fichier d'en-tête <iostream> avant le début de la compilation. Et dans le sens le plus étroit, la compilation convertit le code source en langage d'assemblage plutôt que le code objet. De nombreux compilateurs (tels que GCC/g++) peuvent combiner compilation et Assembly en une seule étape et ne produisent pas de code Assembly à moins d'y être invités.

Bien que le prétraitement soit une étape distincte, GCC et d’autres compilateurs exécutent automatiquement le préprocesseur. De même, ils peuvent exécuter automatiquement l’éditeur de liens, ce qui explique la séquence complète de prétraitement , compilation , Assembly , et lien est parfois appelé "compiler" plutôt que "construire". (Notez également que la construction peut contenir plus que ces étapes - par exemple, elle peut impliquer de générer des fichiers de ressources, en cours d'exécution n script permettant de configurer le mode de construction , etc.).

3 : Vous devez seulement mettre en retrait avec des onglets dans le fichier makefile lui-même. L'utilisation d'un fichier makefile n'impose aucune exigence quant à la manière dont vous écrivez vos fichiers de code source C++ eux-mêmes. N'hésitez pas à remettre l'indentation des onglets en espaces lorsque vous travaillez sur d'autres fichiers. (Et si vous vraiment ​​n'aiment pas l'indentation avec des tabulations dans un fichier makefile, vous pouvez définir le .RECIPEPREFIXvariable spéciale .)

4
Eliah Kagan

Voici un exemple: from myBash.sh

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