Bash で .cpp プログラムを呼び出すことはできますか?

Bash で .cpp プログラムを呼び出すことはできますか?

私は Bash プログラミングの初心者です。Bash ファイルで C++ プログラムを呼び出したいです。

私のプログラムは次のとおりですmyProg.cpp:

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

私の bash ファイルは次のとおりです。ファイルmyBash.sh内で上記の .cpp プログラムを呼び出すにはどうすればよいでしょうか?myBash.sh

答え1

まずコンパイルする必要があります。まず、ターミナルの現在の作業ディレクトリをソース ファイルのパスに変更します。

cd <path_to_cpp_file>/

次にソースファイルをコンパイルします。

g++ myProg.cpp -o myProg

次に、次のようにスクリプトからコンパイルされた実行可能ファイルを呼び出すことができますbash

#!/bin/bash

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

答え2

あなたの本当の目標プログラムを実行するために必要なことをすべて自動化することが目的のようですが、私は別のアプローチを提案します。シェルスクリプトを書く代わりに、メイクファイル必要に応じて、ビルド後に実行可能ファイルを実行するためのルールを makefile に記述できます。そうすると、C++ ソース コード ファイルと makefile の 2 つのファイルが作成され、次の単一のコマンドを効率的に実行できるようになります。

  1. C++プログラムをビルドまたは再構築します。必要な場合のみ
  2. プログラムを実行します。

この投稿の以降のセクションでは、ファイルを直接呼び出すことができない理由.cpp(ただし、最初に実行ファイルを作成する必要がある)、インストール方法make、使用方法、舞台裏で何が行われているか、よくある落とし穴を避ける方法について説明します。ただし、このアプローチがどのようなものかを知るために、make runこれを実行してください。0Makefile

all: myProg

run: all
    ./myProg

この目的にはシェル スクリプトよりもその方が適していると思いますし、あなたもそう思うかもしれません。

背景

一部の通訳言語PythonやBashと同様に、C++はコンパイル言語1C++で書かれたプログラムは建てられた実行する前に構築する必要があります。(建物はコンパイル、 けれどコンパイルより正確には、ビルドのステップの1つを指します。)C++を実行することはできません。ソースコードファイル。代わりにコンパイルする必要がありますオブジェクトコード2、 この場合機械語オブジェクトファイルは互いにリンクされなければならず、たとえ1つしかない場合でも、共有ライブラリリンクすると、実行可能実行できる可能性があります。

つまり、プログラムを実行する前にビルドする必要があります。初めて以降の実行前にソース コードを変更しない限り、プログラムはビルドされません。ソース コードを変更した場合は、実行するプログラムに変更を反映させるには、再度ビルドする必要があります。ユーティリティmakeアクションを実行したいこのような状況のために特別に設計されています条件付きですでに実行されているかどうか、またいつ実行されているかによって異なります。

取得make

すでにmakeコマンドがインストールされている可能性があります。確認するには、実行してみてください。インストールされている場合は、次のような画面が表示されます。

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

makeを入手するには、作る インストールパッケージですが、インストールすることをお勧めしますビルド必須 ビルド必須をインストールする他にも便利なツールが多数用意されています。(インストールしたかもしれませんビルド必須 ビルド必須をインストールするを取得するには、ソフトウェア センターを使用するか、g++次のコマンドを実行します。make

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

makeMakefileなし

どのように動作するかを確認するにはmake、まず makefile なしで実行し、ソース コード ファイルのベース名を渡すことをお勧めします。

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

以降の実行では、make変更タイムスタンプ(時間入力ファイルと出力ファイルに次の変更を加え、プログラムを不必要に再構築しないようにします。

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

を変更するとmyProg.cpp、その変更タイムスタンプが更新されるので、make再構築する必要があることがわかります。(ファイルのタイムスタンプをtouchコマンドに依存する出力ファイルを強制的に再構築する必要がある場合、または再構築したい場合は、出力ファイルを削除してください。もちろん、出力ファイルを削除しても、実行時に確実に再構築されますmake。ただし、間違ったファイルを削除しないでください。

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

make実行するときに何をすべきかをどのように知るのでしょうかmake myProg?

  • myProgへの引数make目標
  • ターゲットは、多くの場合、作成されるファイルの名前ですが、常にそうであるとは限りません。ターゲットは、makefile で明示的に定義できます。
  • ターゲットが makefile で定義されていない場合、または (この場合のように) makefile が存在しない場合は、makeターゲットのビルドを目的としていることを示唆するような名前が付けられた入力 (つまり、ソース コード) ファイルを検索します。
  • makeファイルのサフィックス (この場合は.cpp) から、ファイルの構築に使用するユーティリティと構文を推測します。

これらはすべてカスタマイズできますが、このような単純なケースではカスタマイズする必要はほとんどありません。

プログラムのビルドと実行を自動化するための Makefile の作成

複数の入力ファイルがある場合や、(より当面のニーズに当てはまるように) コンパイラの実行以外に実行したいアクションがある場合など、単一のソース コード ファイルからプログラムを構築するよりも複雑なタスクを自動化するには、makefile を作成してターゲットを定義しmake、それらが他のターゲットにどのように依存するかを指定します。

makefile で定義される最初のターゲットはデフォルトのターゲットです。これは、コマンドライン引数なしで実行された場合 (つまり、 のみを実行し、 のようなものを実行しないmake場合) にビルドを試みるものです。makemake myProg

makefile を使用する通常の方法は、プログラムのビルドに使用されるすべてのソース コード ファイル (およびその他のファイル) と、通常は と呼ばれる makefile を含むディレクトリを作成することですMakefile。その名前で、makeはそれを自動的に見つけます。

myProgを実行して、必要に応じて最初に自動的にビルドするmakefile を作成するには、 をmyProg.cpp新しい、それ以外の場合は空のディレクトリに配置します。そのディレクトリに という別のテキスト ファイルを作成しますMakefile

これには任意のテキストエディタを使用できますが、ルールのレシピ(その下にリストされ、そのターゲットを作成するために実行されるコマンド)は、次のようにインデントする必要があります。タブそれよりもスペース3したがって、テキスト エディターが現在、 を押すとスペースでインデントするように設定されている場合Tab、これを変更する必要があります。

例えば、GeditやPlumaでは、編集 > 環境設定、 クリック編集者タブをクリックして、タブの代わりにスペースを挿入するチェックが外れています:

Pluma の環境設定ダイアログボックスを示すスクリーンショット(インターフェイスは基本的に Gedit と同じ)には、エディタタブの上部近くにあるタブの代わりにスペースを挿入するチェックボックスの位置が示されています。

多くのエディターでは、デフォルトでスペースではなくタブを使用してインデントが設定されているため、この設定を以前に変更したことがない場合は、makefile に対してすでに正しく設定されている可能性があります。

エディターに入り、(必要な場合は)タブでインデントするように設定したら、次のように入力します。

all: myProg

run: all
    ./myProg

これをコピーして貼り付けると間違いになりますを押してもテキスト エディターがスペースを作成しない場合でも、スペースがコピーされるためですTab。(これは Ask Ubuntu がコードを表示する方法に関係しています。) ただし、前の 4 つのスペースを削除して を./myProg押すと、Tabその場所にタブが作成されます。

一部のテキスト エディターでは、タブがデフォルトで 8 個のスペース、または他の数値として表示されます。これは問題ありません。

Makefile の機能とその使い方

次のコマンドを使用します:

  • make、プログラムがすでにビルドされておらず、実行可能ファイルがソース コードに対して最新である場合を除き、プログラムをビルドします。または、
  • make runプログラムを実行するには、必要であれば最初に構築する(つまり、現在実行可能なファイルがない場合)。

この makefile は、allと の2 つのターゲットを定義しますrun

  • ターゲットallには独自のレシピはなく、myProgターゲットに依存します。このターゲットは明示的に定義されていないため、現在のディレクトリにあるソースコードファイルからmakeビルドを試行するように暗黙的に指示しますmyProg。(makeMakefileなし詳細については上記のセクションを参照してください。

    allは で明示的に定義された最初のターゲットであるため、 が存在するディレクトリから を実行するMakefileと がビルドされます。したがって、を単独で実行することが を実行することと同等になるように設定されています。makeMakefilemakemake all

  • ターゲットはプログラムを実行します。そのレシピは、runそれを実行するコマンドで構成されています。ターゲットを依存関係として宣言します。これにより、 を実行すると、現在の実行ファイルが最新でない (またはまだ存在しない)場合は、が再構築されます。./myProgrunallmake runmyProgmyProg

    を ではなくrunに依存させることもできますが、デフォルトのターゲットにならないようにするには、明示的なターゲット(または別の名前の同等のターゲット)が必要になります。もちろん、プログラムをビルドしたい場合は、myProgallallrunそして走る単独で実行する場合でもmake、これを行うことができます。

    ターゲットに依存するもう 1 つの利点allは、後でプログラムを実行する前に実行する必要があるアクションがさらにある場合です。その場合は、 のルールにレシピを追加できますall

プログラムをビルドする必要がある場合、makefile を使用してプログラムを実行すると次のようになります。

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

または、構築する必要がない場合は、次のようになります。

$ make run
./myProg
Salam! World

そして、プログラムがビルドされていることを確認したいだけなら(ソースコードファイルが最後に変更されてから)、プログラムを実行せずにmake引数なしで実行するだけです:

$ 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それでも動作します。)

改良: カスタムコンパイラフラグ

makeは非常に強力なツールで、このような単純な目的には便利ですが、大規模で複雑なプロジェクトにも適しています。これを使ってできることをすべて詳しく説明しようとすると、make1冊の本になってしまいます(具体的には、これです)。

しかし、ビルドの完了を妨げないが、依然として潜在的なエラーがある場合、コンパイラからの警告を確認したい場合があることに気付きました。これにより、作成したプログラムのすべてのバグが検出できるわけではありませんが、多くのバグが検出できる可能性があります。

GCCを使用する場合(コマンドの場合g++)、少なくとも-Wallコンパイラに渡すことをお勧めします。これは実際には有効になりません。全て警告は表示されませんが、残りのほとんどは で有効にできます-Wextra。 も必要な場合があります-pedantic。(man gccそして3.8警告を要求または抑制するオプションの中にGCC リファレンスマニュアル

これらのフラグを使用して手動で呼び出すにはg++、次を実行します。

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

、、およびフラグを使用してmakeC++ コンパイラ ( g++)を呼び出すには、それらの行を の先頭に追加します。-Wall-Wextra-pedanticCXXFLAGS=Makefile

CXXFLAGS=-Wall -Wextra -pedantic

all: myProg

run: all
    ./myProg

myProgがまだ存在し、 よりも新しい場合でもmyProg.cpp、編集後にmakeまたはを実行すると、が よりも新しくなったため、プログラムが再度ビルドされます。これは、次の理由から良いことです。make runMakefileMakefilemyProg

  • この場合、実行可能ファイルを再構築すると、警告があれば表示されます (その特定のプログラムでは警告は表示されないはずです)。
  • より一般的には、makefile を編集するのは、異なるファイルを生成したい場合や、異なる内容で生成したい場合です。(たとえば、-O3高度な最適化のフラグを追加した場合や、-gコンパイラにデバッグ シンボルを生成させたい場合、結果として得られるmyProg実行可能ファイルは異なります。)

参考文献

ノート

0: これを機能させる方法については、さらに読み進めることをお勧めします。ただし、最初に自分で試してみたい場合は、行をスペースではなくタブでインデントする必要があります。

1: 厳密に言えば、事実上あらゆるプログラミング言語は、実装言語によっては、インタプリタとコンパイラの両方が存在する。しかし、インタプリタ型のC++は一般的ではない。聞いたことがないわけではない

2: 建物を分割するコンパイルそしてリンク、C++ソースコードファイル(.cc/.cpp/.cxx/.C)をオブジェクトコードに変換するコンパイル、それだけではありません。CとC++(および他の言語)のプログラムは、まず前処理済みあなたのプログラムでは、Cプリプロセッサ#include<iostream>実際のコンパイルが始まる前に、ヘッダーファイルの内容に置き換えます<iostream>。そして、最も狭い意味では、コンパイルはソースコードをアセンブリ言語オブジェクト コードではなく、アセンブリ コードを生成します。多くのコンパイラ (GCC/ などg++) は、コンパイルとアセンブリを 1 つのステップで組み合わせることができ、要求されない限りアセンブリ コードを生成しません。

前処理は別のステップですが、GCCや他のコンパイラは自動的に前処理を実行します。同様に、リンカーも自動的に実行できるため、前処理コンパイル組み立て、 そしてリンケージ「ビルド」ではなく「コンパイル」と呼ばれることもあります。(ビルドには、リソースファイルの生成、実行など、これらの手順以外にもさまざまな手順が含まれる場合があります。どのように構築するかを設定するスクリプトなど)

3: タブでインデントする必要があるのは、makefile自体だけです。makefileを使用することで、C++ソースコードファイル自体の記述方法に制約が課されることはありません。他のファイルで作業しているときに、インデントをタブからスペースに戻してもかまいません。(そして、本当にメイクファイルでタブを使ってインデントするのが好きではない場合は、.RECIPEPREFIX 特殊変数

答え3

以下は例です: myBash.shより

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

関連情報