静的ライブラリにバージョン番号を保存する方法は?
-
08-07-2019 - |
質問
静的ライブラリ(file.a)にバージョン番号を保存し、後でLinuxでそのバージョンを確認するにはどうすればよいですか
PSシェルユーティリティのみで使用する特別な実行可能ファイルがなくても、いつでもファイルのバージョンをチェックする可能性が必要です。
解決
たぶん、次のようなバージョンの文字列を作成できます:
char* library_version = { "Version: 1.3.6" };
そしてシェルからチェックできるようにするには、次を使用します:
strings library.a | grep Version | cut -d " " -f 2
他のヒント
Puppeが言及した静的な文字列を提供することに加えて、互換性のためにバージョンチェックを取得するマクロを提供するのが一般的です。たとえば、次のマクロを使用できます(ライブラリで使用するヘッダーファイルで宣言されます):
#define MYLIB_MAJOR_VERSION 1
#define MYLIB_MINOR_VERSION 2
#define MYLIB_REVISION 3
#define MYLIB_VERSION "1.2.3"
#define MYLIB_VERSION_CHECK(maj, min) ((maj==MYLIB_MAJOR_VERSION) && (min<=MYLIB_MINOR_VERSION))
MYLIB_CHECK_VERSION
マクロに関する注意、特定のメジャーrevとマイナーrevが目的のバージョン以上であることを前提としています。アプリケーションの必要に応じて変更します。
次に、次のような呼び出し側アプリケーションから使用します。
if (! MYLIB_VERSION_CHECK(1, 2)) {
fprintf(stderr, "ERROR: incompatible library version\n");
exit(-1);
}
このアプローチにより、バージョン情報はインクルードヘッダーファイルから取得されます。さらに、呼び出し側アプリケーションのコンパイル時に最適化されます。もう少し作業を行うと、ライブラリ自体から抽出できます。続きを読む...
Puppeが述べたように、この情報を使用して、ライブラリ内に保存された静的文字列を作成することもできます。ライブラリ内に次のようなものを配置します。
struct {
const char* string;
const unsigned major;
const unsigned minor;
const unsigned revision;
} mylib_version = {
MYLIB_VERSION, MYLIB_MAJOR_VERSION, MYLIB_MINOR_VERSION, MYLIB_REVISION
};
これにより、ライブラリに mylib_version
という構造体が作成されます。これを使用して、ライブラリ内に関数を作成し、呼び出し元のアプリケーションなどからそれらにアクセスすることで、さらに検証を行うことができます。
編集に基づいて新しい回答を作成しています...混乱を避けるためだけに:)
問題を解決するためのコード以外の方法を探している場合は、これを試すことができます。これは(まだ)Puppeによって定義された strings
アプローチの代替です。
version_1.2.3
というファイルをタッチして、アーカイブに追加することができます。次に、arコマンドを使用してバージョンファイルを検索することにより、バージョンを判別できます。
ar t libmylib.a | grep 'version_' | sed -e 's/^version_//'
それで必要なものが得られるかどうかはわかりませんが、このようなメタデータをアーカイブに埋め込む標準的な方法はありません。この「メタファイル」に保存したい他の情報が見つかるかもしれません。アーカイブ用。
man 1 ident
が何度か言及されているので、その方法の使用方法について詳しく説明します。
ident
はRCS(Revision Control System)に付属するコマンドですが、CVS(Concurrent Versions System)またはSubversionを使用している場合にも使用できる場合があります。
次のように使用します(manページから複製):
#include <stdio.h>
static char const rcsid[] =
"$Id: f.c,v 5.4 1993/11/09 17:40:15 eggert Exp ident f.c f.o
quot;;
int main() { return printf("%s\n", rcsid) == EOF; }
そしてf.cはf.oにコンパイルされ、その後コマンド
f.c:
$Id: f.c,v 5.4 1993/11/09 17:40:15 eggert Exp $
f.o:
$Id: f.c,v 5.4 1993/11/09 17:40:15 eggert Exp $
出力します
#include <stdio.h>
#define VERSION_STR "5.4"
#define CONFIG "EXP"
#define AUTHOR "eggert"
static char const sccsid[] =
"@(#) " CONFIG " v " VERSION_STR " " __DATE__ " " __TIME__ " " AUTHOR;
int main() { return printf("%s\n", sccsid) == EOF; }
f.o
が静的ライブラリ f.a
に追加された場合、 ident f.a
は同様の出力を表示するはずです。 az.a
に同様にビルドされた [az] .o
がいくつかある場合は、すべての文字列を az.a
ファイルで見つける必要があります。
警告:.aファイルにあるからといって、プログラムファイルに含まれるわけではありません。プログラムがそれらを参照しない限り、リンカーはそれらを含める必要がないと見なします。そのため、通常は各モジュールに文字列を返すメソッドが必要であり、アプリはそのメソッドを呼び出す必要があります。ほとんどのリンカーに、実際に参照せずに必要なシンボルであることを納得させる方法がありますが、それはリンカーに依存し、この答えの範囲を超えています。
SCCS(ソースコード管理システム)に精通している場合は、代わりに man 1 what
を使用すると、次のようになります(利用可能な柔軟性を示すためにマクロを使用します)。
what f.c f.o
そしてf.cはf.oにコンパイルされ、その後コマンド
f.c:
@(#) EXP v 5.4 1993/11/09 17:40:15 eggert
f.o:
@(#) EXP v 5.4 1993/11/09 17:40:15 eggert
出力します
<*> PS: ident
と what
は、特定の集中ソース管理システムに付属するコマンドです。分散ソース管理システム(gitなど)を使用している場合、コンセプト全体が意味をなさない場合があります。 git
を使用するいくつかのアイデアについては、次のスレッドを参照してください。移動元CVSからgit:$ Id:$と同等ですか?ハッシュはバージョン番号と同じではありませんが。 :)
gccを使用している場合、#identディレクティブを使用できます
#ident "Foo Version 1.2.3.4"
void foo(void){ /* foo code here */ }
バージョンを取得するには、次のいずれかを使用します。
strings -a foo.o | grep "Foo Version"
strings -a foo.a | grep "Foo Version"
strings -a foo.so | grep "Foo Version"
これにより、バージョンをライブラリにコンパイルして、後で strip -R .comment your_file
を使用して削除したり、 -fno-ident <を渡して完全に省略したりできます。 / code>(これにより、コンパイルされたオブジェクトからコンパイラバージョンのコメントも省略されます)