これは、Ubuntu Online、Fedora Online、Windows オンライン エミュレーター、MAC OS オンライン エミュレーターなど、複数の無料オンライン ワークステーションのいずれかを使用して、OnWorks 無料ホスティング プロバイダーで実行できるコマンド makepp_scanning です。
プログラム:
NAME
makepp_scanning -- makepp がインクルード ファイルやその他の隠れた依存関係を見つける方法
DESCRIPTION
Makepp は、認識している特定のコマンドの追加の依存関係またはターゲットを決定できます。
についての何か。 これは、C/C++ コンパイルでは特に重要です。
特定のソース ファイルが依存するすべてのインクルード ファイルを手動で一覧表示するとエラーが発生しやすくなります。
コンパイル コマンドとソース ファイル自体を見ると、makepp は次のことができます。
一部のインクルード ファイルが変更された場合に、どのオブジェクト ファイルを再構築する必要があるかを正確に判断します。
例: 与えられたルール
foo.o: # 通常は %.o: %.c、説明のため
time -p /bin/libtool -bar /usr/bin/cc -c -I どこか foo.c
makepp は、「time」と「libtool」をスキップする必要があり、「cc」が実際のコマンドであることを認識しています。
ここで解析されます。 それはわかる foo.c は入力ファイルであり、したがって依存関係です
このルール。 さらに、インクルードステートメントを探してそのファイルをスキャンします。
ディレクトリにジョブを開始します。 どこかコマンドオプションを理解したからです。
実際には、歴史的にスキャンと呼ばれるものには XNUMX つのステップがあります。
1. ルール アクションは行に分割されます (継続行は XNUMX 行としてカウントされます)。 各行
(ビルトインと Perl ブロックを除く) は 字句的に 分析 XNUMX つまたは複数のシェル コマンドとして。
リダイレクトは、このルールへの入力または出力として認識されます。 それぞれの最初の言葉
コマンドが検索されます (そのディレクトリ部分が検索されますが、見つからない場合は検索されません)。
そのためのパーサーを見つけてください。 これらはオプションの依存関係になり、可能であれば構築されます。
しかし、見つからない場合は無視されます。makepp は複雑なコマンドのどの部分が正しいかを認識できないためです。
実際に走る。
逆引用符で囲まれたコマンドは分析されますが、実行されません。 (多くの場合、実行は重要ですが、
しかし、これは makepp による大きな干渉になります。) それらを避ける方が良いスタイルです。
代わりに、次の特別な方法で割り当てて、makepp にコマンドを最大 XNUMX 回実行させます。
XYZFLAGS ;= $(シェル pkg-config --cflags xyz)
現在、Bourne Shell を理解する lexer クラスは XNUMX つしかありません。 より良いものに
C Shell または "command.com" を処理すると、サブクラスが作成される場合があります。 ただし、多くの構文は
これを保証しないほど似ています。 貢献したい場合は、連絡を取ってください。
2. 既知のコマンドについては、対応する command パーサー (単にパーサーとも呼ばれます)
重要なオプションと引数を分析します。 利用可能なものを以下に説明します。
特殊なパーサーが見つからなかった場合でも、一般的なパーサーがコマンドを実行可能にします
このルールの入力。 --no-path-executable-dependencies でそれを変更できます
コマンドオプション。
3. パーサーが入力ファイルを認識した場合、それらは スキャナー によって選ばれた
パーサー。 「#include」または同等のステートメントを探すことで、さらに入力を見つけます。
これは最も高価なステップです。 繰り返しを避けるために、すべての結果がキャッシュされます
不必要に。
makepp が C/C++ ソースをコンパイルしていると判断してもパーサーが見つからない場合、
知らせる警告メッセージ。 これは通常、コンパイラ コマンドを埋め込んだことを意味します。
アクションに深く入り込みすぎて makepp がそれを見つけることができません。 たとえば、次のようなルールを見てきました。
%.o: %.c
@echo コンパイル中 $< now; obscure_wrapper gcc -c $< $(CFLAGS) -o $@
ここでのアクションの最初の単語は、"echo" と "obscure_wrapper" です。
パーサーがないため、この場合、makepp はインクルード ファイルをスキャンしません。 を無視できます。
接頭辞付きのコマンド:
レジスターパーサー obscure_wrapper スキップワード
次のセクションでは、組み込みのパーサーとスキャナーについて説明します。 できる名前で
「-」は「_」と同じ意味で使用します。
スキャナー (パーサー)
さまざまなスキャナーは、括弧内に示されているコマンド パーサーによって選択する必要があります。
C / C ++ 編集 (c-コンパイル、 gcc-コンパイル)
C/C++ スキャナーは、両方の言語を無差別に処理します。 実際、それは
プリプロセッサ ステートメントが含まれているため、かなりの数の言語で使用できます。 そのパーサーは
アクティブ化すると、gcc の多くのオプションの特別なバリアントがあり、
コマンド名に文字列「gcc」または g++ が含まれています。 C を使用する他の言語のコンパイラの場合
プリプロセッサが C コンパイラと同じオプション (少なくとも "-I") を使用すると、このパーサーが機能します
細かいです。
インクルード パスを指定する「-Idir」オプションまたは「-Ldir」オプションのコマンドを調べます。
リンクパスを指定します。 次に、ソース ファイルをスキャンして「#include」ディレクティブを探します。
また、コマンドラインを調べて、言及されているソースファイルまたはライブラリがあるかどうかを確認します
依存関係としてリストされていません。 これらは拡張子によって認識されます。
このスキャナーは、「#include "file.h"」で含まれるファイルが含まれていない場合、警告メッセージを表示します。
インクルード パス、または
「#include」されているファイル、または / usr / include. ファイルが含まれている場合、警告は表示されません
"#include " が見つかりません。Makepp は、何らかのシステム インクルードにあると想定しています。
コンパイラが認識しているディレクトリ、およびシステム内のファイルにディレクトリが含まれている
変わりません。
さらに、 / usr / include, / usr / local / include, /usr/X11R6/インクルード、およびその他
書き込み可能でないディレクトリは、何が含まれているかを確認するためにスキャンされません。 Makepp が想定する
これらのファイルは変更されません。 (root として実行している場合、書き込み可能性テストは
makepp を実行したディレクトリの UID と GID で実行されます。 これはとてもコンパイルされています
通常のユーザーとしてプログラムを実行し、ルートとして「makepp install」を実行しても、余分な問題は発生しません
ディレクトリがスキャンされます)。
これはかなり単純なスキャナーです。 次のようなことをすると混乱します。
#ifdef INCLUDE_THIS
#include "this.h"
#endif
プリプロセッサの条件について知らないためです。 これは通常無害です。 それ
追加の余分なファイルが依存関係としてラベル付けされる可能性があります (時折、
そうしないと、インクルード ファイルが正しくないことを makepp が警告する可能性があります。
見つかった。 警告メッセージを無視するか、空のファイル「this.h」を出力することができます
そこにmakeppをシャットダウンします。
コンパイラに面白い名前が付いている場合は、次のいずれかを言うことができます
レジスターパーサー obscure_c_compiler c-compilation
レジスターパーサー obscure_gcc_alias gcc-compilation
組み込み SQL C / C ++ 編集 (esql コンパイル)
これらのコマンドは、さまざまなデータベースに付属しており、特別なセクションを前処理します。
それ以外の場合は、C/C++ に似たソースであり、C/C++ ヘッダーとソースを生成します。 これはEXEC SQLを見つけます
INCLUDE "filename" または $INCLUDE "filename" ディレクティブ。
次のプリプロセッサが認識されます: Altibase APRE*C/C++ (apre)、CASEMaker DBMaster
(dmppcc)、Firebird / InterBase (グプレ)、IBM DB2 (db2 プリコンパイル、 db2 準備) & Informix
ESQL/C (esql)、イングレス(esqlc)、マイマー (esql)、オラクル (PROC)、PostgreSQL (ECPG) & ヤード
(ヤードpc)。 プリプロセッサが認識されない場合は、次のように言うことができます
register-parser obscure_esqlc_preprocessor esql-compilation
ただし、これは Informix などに共通のスタイルのみを処理します。 コマンド引数
「.ec」で終わるファイルはスキャン対象のファイルです。「-I」はインクルード パスと EXEC SQL を定義します。
サフィックスのない INCLUDE ディレクティブには、「.h」が追加されます。
スウィッグ (スウィグ)
Swig (簡略化されたラッパーとインターフェイス ジェネレーター、 http://www.swig.org/) は、
C/C++ ヘッダー ファイルを、コードを呼び出し可能にするために必要なラッパー関数に変換します
Perl、Python、Tcl、C#、Ruby、OCaml、および
おそらく私が知らない他のいくつか。
Makepp は swig コマンド ラインを理解して解析し、"-I" および "-l" オプションを探します。
また、swig のインターフェイス定義ファイルをスキャンする方法も知っています (.i ファイル) を探しています
%include、%import、および「-includeall」が有効な場合は「#include」。
あなたの小枝に面白い名前が付いている場合は、次のように言うことができます
レジスターパーサー obscure_swig_alias swig
Vera ベリログ (vcs_compilation)
ハードウェアを設計する場合、これは便利です。
無視できる ラッパー (スキップワード、 シェル)
Makepp は次のコマンド ワードを認識し、それらをスキップします。
正しいスキャナーの検索で適切に: "condor_compile", "distcc",
「ignore_error」、「libtool」、「noecho」、「purify」。
これには、"sh -c 'command1;
command2'".
そのようなコマンドが他にもある場合は、次のように言うことができます
レジスタ パーサー コマンド スキップ ワード
libtool
Libtool は非常に巧妙なコンパイル システムであり、共有の作成を大幅に簡素化します。
システムに依存するすべての詳細をシェル スクリプトに隠すことでライブラリを作成します。 唯一の
問題は、ライブラリのバイナリ ファイルが実際には同じディレクトリに格納されていないことです。
出力ファイルとして --libtool は実際にサブディレクトリ「.libs」を作成します。
実際のファイル。 これは通常は問題になりませんが、makepp は実際の
バイナリは、リポジトリからリンクする場合です。 現時点では、libtool ライブラリ
(「.la」ファイル) はリポジトリからリンクされていません。 必要に応じて常に再構築されます。
また、現時点では makepp は保存されている依存情報を使用できません。
「.la」ファイル自体の中にあります。 これはすぐに変更されることを願っています。
抑制 スキャン (なし)
ルールや特定のコマンドを解析したくない場合があります。 オフにすることができます
解析し、それによってスキャンする
レジスターパーサー cc なし
関連 OPTIONS
クイックスキャン スマートスキャン
":quickscan" および ":smartscan" ルール オプションは、該当する場合、ファイルの処理方法に影響します。
スキャンされます。
":quickscan" モード (デフォルト) では、すべての include ディレクティブがアクティブであると見なされます。 これにより、
非常に効率的なスキャンのために。
":smartscan" モードでは、マクロと式を解釈しようとします。
非アクティブな include ディレクティブは無視されます。 たとえば、によって生成された実行可能ファイル
次のCプログラムをコンパイルする必要があります 拠り所にする ふー。:
#0の場合
#include "foo.h"
#endif
int main() { 0 を返す; }
CUSTOM スキャナー
":parser foo" のようなルール オプションで、または以下を使用して、独自のパーサーを指定できます。
「register_parser」または「register_command_parser」ステートメント。
いずれにせよ、「register_parser」で説明されているように、直接的または間接的に必要です。
(クラスを介して) パーサー オブジェクトを作成する関数を指定します。 通常、このオブジェクトは
ファイルのスキャナーオブジェクトを作成し、コマンドラインからの結果をフィードします
オプション。 これら XNUMX つのオブジェクトは、パーサーの「add_*_dependency」メソッドを呼び出します。
やや複雑な "Mpp::Lexer::add_*_dependency" に情報を転送します
ユーティリティ関数。
ただし、単純なケースでは、パーサー関数自体がこの作業を行うこともできます。 あります
この関数がパーサー オブジェクトを返さない場合のいくつかの特別な戻り値:
「undef」
スキャン情報はキャッシュ可能ではないため、次回ルールのターゲットで再計算する必要があります
構築する必要があります。
「p_none、p_skip_word」または「p_shell」
これらは実際には数値定数であり、レクサーにこれらの作業を行うように指示します
疑似パーサー。
"\1" などの任意の参照
これは、「Mpp::CommandParser」ベースのパーサー オブジェクトを返すことと同じです。
これは、コマンド実行可能ファイル自体を依存関係にするだけです。
ほとんどの場合、「Mpp::CommandParser」タイプのオブジェクトは、少なくとも XNUMX つのオブジェクトをインスタンス化する必要があります。
タイプ "Mpp::Scanner" の。 「Mpp::Scanner」基本クラスが区別を処理します
クイックスキャンとスマートスキャンの間。 "Mpp::Scanner" の動作が著しく不安定になる可能性があることに注意してください。
この区別の影響を受けますが、派生クラスに対して透過的である必要があります。
整形式。 新しい派生 "Mpp::Scanner" クラスは、両方のモードでテストする必要があります。
独自の "Mpp::Scanner" クラスを作成する場合は、再スキャンの決定にも基づいてください。
ビルド情報「RESCAN」について。 これは、ファイルに署名せずに「makeppreplay」によって設定されます。
走査。 そのため、署名が一貫していても、再スキャンが必要です。 もしも
あなたの "Mpp::Scanner" は、継承された "scan_file1" メソッドを使用しています。おそらく問題ありません。
詳細については、各クラスのドキュメントを参照してください。 例については、を参照してください。
「Mpp::CommandParser::Gcc」と「Mpp::CommandParser::Vcs」。 の「p_」関数を見てください
Mpp/Subs.pm ロード時に「factory」としてそれぞれのクラスにエイリアスされます。
キャッシング スキャナー info
スキャナーの重要な副作用のすべてがメソッドの呼び出しによって影響を受ける場合
「Mpp::CommandParser」基本クラスの場合、これらの副作用はビルドにキャッシュできます
info ファイルに保存されているため、後で makepp を呼び出しても再生できます。
コストのかかるすべてのスキャン作業を行っています。 これにより、特に時間を大幅に節約できます。
スマートスキャンモード。
スキャナに他の重要な副作用がある場合は、「Rule」オブジェクトの
mark_scaninfo_uncacheable メソッド。 それ以外の場合、ビルドから取得したスキャナー情報
info が不正確である可能性があり、ビルド結果が不正確になる可能性があります。 この方法は
%parsers ハッシュからの値が型のオブジェクトを返さない場合に自動的に呼び出されます
「Mpp::CommandParser」、またはパーサーがルール オプションと「p_*」で指定されている場合
ルーチンは、タイプ「Mpp::CommandParser」のオブジェクトを返しません。
キャッシュされたスキャン情報は、いつ決定するために使用されるものと同様の基準を使用して無効にされます
ターゲットは古くなっています。 同様に、次を使用してリポジトリから取得できます
ターゲットがいつからリンクできるかを決定するために使用されるものと同様の基準
リポジトリ。
「--force-rescan」オプションを使用すると、makepp にキャッシュされたスキャナー情報を強制的に無視させることができます。
これは、壊れたスキャナーが原因で誤ったスキャナー情報がキャッシュされた可能性がある場合に役立ちます。
Ad ホック スキャナー
多くの場合、依存情報を含むファイルが XNUMX つまたは数個しかありません。 あなたはそうしない
これをメイクファイルに重複して書きたい (冗長性は後でしばしば
XNUMX つの更新が忘れられると不整合が発生します)。 しかし、あなたも書きたくない
Mpp::スキャナ? 回避策として、オンザフライでインクルード ファイルを生成できます。 例えば
Qtには .qrc 次のようなファイル:
abc
xyz
...
上記のレイアウトに従えば、関連する行を makepp に変換できます。
インクルードすることで自動的に作成されるインクルードファイル。
%.qrc.makepp: %.qrc
&grep の! \n!$(stem).cc:! || ! * ! ! && s! \n!!' $(入力) -o $(出力)
include $(wildcard *.qrc) # .makepp は自動的に追加されます
これのいくつかの変形がクックブックに記載されています。 欠点は、あなたが始めることです
makefile を読みながらビルドします。 したがって、 --loop コマンド オプションはあまり役に立ちません。
最初の繰り返しで。
onworks.net サービスを使用してオンラインで makepp_scanning を使用する