私は 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 つのファイルが作成され、次の単一のコマンドを効率的に実行できるようになります。
- C++プログラムをビルドまたは再構築します。必要な場合のみ。
- プログラムを実行します。
この投稿の以降のセクションでは、ファイルを直接呼び出すことができない理由.cpp
(ただし、最初に実行ファイルを作成する必要がある)、インストール方法make
、使用方法、舞台裏で何が行われているか、よくある落とし穴を避ける方法について説明します。ただし、このアプローチがどのようなものかを知るために、make run
これを実行してください。0でMakefile
:
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
make
Makefileなし
どのように動作するかを確認するには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
場合) にビルドを試みるものです。make
make myProg
makefile を使用する通常の方法は、プログラムのビルドに使用されるすべてのソース コード ファイル (およびその他のファイル) と、通常は と呼ばれる makefile を含むディレクトリを作成することですMakefile
。その名前で、make
はそれを自動的に見つけます。
myProg
を実行して、必要に応じて最初に自動的にビルドするmakefile を作成するには、 をmyProg.cpp
新しい、それ以外の場合は空のディレクトリに配置します。そのディレクトリに という別のテキスト ファイルを作成しますMakefile
。
これには任意のテキストエディタを使用できますが、ルールのレシピ(その下にリストされ、そのターゲットを作成するために実行されるコマンド)は、次のようにインデントする必要があります。タブそれよりもスペース。3したがって、テキスト エディターが現在、 を押すとスペースでインデントするように設定されている場合Tab、これを変更する必要があります。
例えば、GeditやPlumaでは、編集 > 環境設定、 クリック編集者タブをクリックして、タブの代わりにスペースを挿入するチェックが外れています:
多くのエディターでは、デフォルトでスペースではなくタブを使用してインデントが設定されているため、この設定を以前に変更したことがない場合は、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
。(make
Makefileなし詳細については上記のセクションを参照してください。all
は で明示的に定義された最初のターゲットであるため、 が存在するディレクトリから を実行するMakefile
と がビルドされます。したがって、を単独で実行することが を実行することと同等になるように設定されています。make
Makefile
make
make all
ターゲットはプログラムを実行します。そのレシピは、
run
それを実行するコマンドで構成されています。ターゲットを依存関係として宣言します。これにより、 を実行すると、現在の実行ファイルが最新でない (またはまだ存在しない)場合は、が再構築されます。./myProg
run
all
make run
myProg
myProg
を ではなく
run
に依存させることもできますが、デフォルトのターゲットにならないようにするには、明示的なターゲット(または別の名前の同等のターゲット)が必要になります。もちろん、プログラムをビルドしたい場合は、myProg
all
all
run
そして走る単独で実行する場合でも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
は非常に強力なツールで、このような単純な目的には便利ですが、大規模で複雑なプロジェクトにも適しています。これを使ってできることをすべて詳しく説明しようとすると、make
1冊の本になってしまいます(具体的には、これです)。
しかし、ビルドの完了を妨げないが、依然として潜在的なエラーがある場合、コンパイラからの警告を確認したい場合があることに気付きました。これにより、作成したプログラムのすべてのバグが検出できるわけではありませんが、多くのバグが検出できる可能性があります。
GCCを使用する場合(コマンドの場合g++
)、少なくとも-Wall
コンパイラに渡すことをお勧めします。これは実際には有効になりません。全て警告は表示されませんが、残りのほとんどは で有効にできます-Wextra
。 も必要な場合があります-pedantic
。(man gcc
そして3.8警告を要求または抑制するオプションの中にGCC リファレンスマニュアル。
これらのフラグを使用して手動で呼び出すにはg++
、次を実行します。
g++ -Wall -Wextra -pedantic -o myProg myProg.cpp
、、およびフラグを使用してmake
C++ コンパイラ ( g++
)を呼び出すには、それらの行を の先頭に追加します。-Wall
-Wextra
-pedantic
CXXFLAGS=
Makefile
CXXFLAGS=-Wall -Wextra -pedantic
all: myProg
run: all
./myProg
myProg
がまだ存在し、 よりも新しい場合でもmyProg.cpp
、編集後にmake
またはを実行すると、が よりも新しくなったため、プログラムが再度ビルドされます。これは、次の理由から良いことです。make run
Makefile
Makefile
myProg
- この場合、実行可能ファイルを再構築すると、警告があれば表示されます (その特定のプログラムでは警告は表示されないはずです)。
- より一般的には、makefile を編集するのは、異なるファイルを生成したい場合や、異なる内容で生成したい場合です。(たとえば、
-O3
高度な最適化のフラグを追加した場合や、-g
コンパイラにデバッグ シンボルを生成させたい場合、結果として得られるmyProg
実行可能ファイルは異なります。)
参考文献
- 演習 2: Make は Python ですで難しい方法でCを学ぶによるゼッド・ショー。
- のGNU Make マニュアル、 特に2.1ルールとは。
- 簡単な Makefile チュートリアルによるブルース・A・マクスウェル他の使用方法については、 を参照してください
make
。 - 「Makefileの使用」(p. 15)および「Makefileとシェルスクリプト」(p. 62)21世紀Cによるベン・クレメンスページ番号は初版のものです。(第2版の方が良いかもしれませんが、私が持っているのは第1版だけです。)
ノート
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