各C / C ++ソースファイルを登録して、使用されるソースのランタイムリストを作成する
-
03-07-2019 - |
質問
デバッグおよびロギングライブラリの場合、実行時に、プロジェクトがコンパイルおよびリンクしたすべてのソースファイルのリストを検索できるようにします。私は各ソースファイルに何らかの種類のヘッダーを含めると仮定し、プリプロセッサ__FILE__マクロはそのファイルの文字定数を与えることができるので、どういうわけか<!> quot; broadcast <!> quot;ランタイム関数によって収集される各ファイルの情報。
問題は、これをエレガントに行う方法であり、特にC ++ではなくCから実行できる場合です。 C ++では、おそらくファイル名のリストを保持するために、静的ストレージを持つクラスを作成しようとします。各ヘッダーファイルは、そのクラスのファイルローカルな静的インスタンスを作成し、作成時にFILEポインターなどをクラスの静的データメンバーに、おそらくリンクリストとして追加します。
しかし、これはCでは動作しないと思います。C++でも、各要素が作成されることが保証されているかどうかはわかりません。
解決
この種のことは、コード内で直接行いません。プロジェクトファイル(vcproj、makefile、またはプロジェクトディレクトリをスキャンして* .c *ファイルを検索する)を解析し、ある種の事前のすべてのソースファイルの名前を含む追加のCソースファイルを生成するツール初期化されたデータ構造。
このツールをビルドプロセスの一部にして、ビルドを行うたびにこれがすべて自動的に行われるようにします。実行時に行う必要があるのは、構築されたデータ構造を読み取ることだけです。
他のヒント
Ferruccioに同意します。これを行う最善の方法は、コード自体ではなく、ビルドシステム内です。彼のアイデアの拡張として、ファイルのリスト(とにかく知っていなければならない)を文字列または文字列の配列としてCファイルにダンプするビルドシステムにターゲットを追加し、このファイルをソースにコンパイルします。これにより、ソースでの多くの複雑さを回避し、ソースコード管理システムからのバージョン番号、実行可能ファイルの作成者などの追加情報を追加する場合に拡張可能です。
UNIXおよびLinuxには標準的な方法があります-ident
。すべてのソースファイルに対してIDタグを作成します。通常、バージョン管理システムによって割り当てられます。 SVNキーワード 。
次に、各ソースファイルの名前とリビジョンを確認するには、<=>コマンドを使用します。実行時に実行する必要がある場合は、<=>の実行方法を確認してください。ソースは自由に利用できるようにしてください。
Cでそれを行う方法はありません。C++では、次のようなクラスを作成できます。
struct Reg {
Reg( const char * file ) {
StaticDictionary::Register( file );
};
StaticDictionaryは、すべてのファイル名のシングルトンコンテナーです。次に、各ソースファイルで:
static Reg regthisfile( __FILE__ );
辞書をマイヤーシングルトンにより、作成順序の問題を回避します。
<!> quot; passive <!> quot;で輪郭を描く方法でこれを行うことはできないと思います。モード。つまり、レジストリに追加する各ソースファイルのコードを何らかの方法で実行しようとしているので、自動的に発生させるのは困難です。
もちろん、マクロを使用してそのコードを非常に目立たなくすることができます。 <!> quot; entrypoint <!> quot;を持たないCソースファイルでは問題が発生する可能性があります。そのため、コードがまだ<!> quot; modules <!> quot;として構成されていない場合は、各モジュールのinit()
関数、それは難しいかもしれません。静的な初期化コードが可能かもしれませんが、物事が初期化される順序がここで問題を引き起こすかどうか私は100%確信していません。
レジストリモジュールでstatic
ストレージを使用するのは素晴らしいアイデアのように思えます。プロジェクトに汎用ユーティリティライブラリが含まれていない場合は、プレーンリンクリストまたは単純なハッシュテーブルを実装するのに十分簡単です。
C ++では、ソリューションが機能します。保証されています。
編集:頭の中で解決策を見つけた:makefileのルールを変更して追加する '-include <!> quot; cfiles_register.h <!> quot;'各「g ++ file.cpp」に。
%.o : %.cpp
$(CC) -include 'cfiles_register.h' -o $@ $<
その「cfiles_register.h」への質問実装に提案を入れてください。
C ++で静的インスタンスを使用すると問題なく動作します。
Cでもこれを実行できますが、ランタイム固有の機能を使用する必要があります。MSVCCRTについては、 http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c6945/
Cの場合-マクロを使用して実行できます-ファイルに対応する名前の変数を定義すると、アイデアとして実行可能ファイルのシンボルをスキャンできます:
#define TRACK_FILE(name) char _file_tracker_##name;
my_c_file.cで次のように使用します:
TRACK_FILE(my_c_file_c)
そしてgrepよりも、このようなバイナリからのすべてのファイル/変数名
nm my-binary | grep _file_tracker
あまり良くないが......
恐ろしいアイデア、私は確信していますが、シングルトンを使用します。そして、各ファイルで次のようなことをします
Singleton.register(__FILE__);
グローバルスコープ。ただし、cppファイルでのみ機能します。 私はこの数年前に初心者として何かをしましたが、うまくいきました。しかし、私はそれを今やろうとします。ビルドステップを追加します。
実行時にこれを行わない方が良いと言う人々に同意しますが、Cでは、関数呼び出しで静的変数を初期化できます。つまり、すべてのファイルで:
static int doesntmatter = register( __FILE__);