Как сохранить номер версии в статической библиотеке? - PullRequest
8 голосов
/ 28 октября 2009

Как мне сохранить номер версии в статической библиотеке (file.a) и позже проверить его версию в Linux?

P.S. Мне нужна возможность проверить версию файла в любое время без какого-либо специального исполняемого файла, используя только утилиты оболочки.

Ответы [ 5 ]

10 голосов
/ 28 октября 2009

В дополнение к предоставлению статической строки, как упомянуто 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 я предполагаю, что вы хотите конкретную большую и меньшую обороты, которые больше или равны требуемой версии. Измените, как требуется для вашего приложения.

Затем используйте его из вызывающего приложения, например:

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 в вашей библиотеке. Вы можете использовать это для дальнейшей проверки, создав функции внутри вашей библиотеки и получив доступ к ним из вызывающего приложения и т. Д.

9 голосов
/ 28 октября 2009

Может быть, вы могли бы создать строку с такой версией:

char* library_version = { "Version: 1.3.6" };

и чтобы проверить его из оболочки, просто используйте:

strings library.a | grep Version | cut -d " " -f 2
3 голосов
/ 28 октября 2009

Создание нового ответа на основе вашего редактирования ... Просто, чтобы избежать путаницы:)

Если вы ищете некодовый способ решения проблемы, вы можете попробовать это. Это (еще раз) альтернатива подходу strings, определенному Puppe.

Может быть, вы можете просто коснуться файла с именем version_1.2.3 и добавить его в архив. Затем вы можете определить версию, выполнив поиск файла версии с помощью команды ar:

ar t libmylib.a | grep 'version_' | sed -e 's/^version_//'

Я не уверен, что это даст вам то, что вам нужно, но стандартного метода для встраивания подобных метаданных в архив нет. Возможно, вы найдете другую информацию, которую хотите сохранить в этом «метафайле» для архива.

0 голосов
/ 02 июня 2016

Если вы используете 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 (это также исключит комментарии версии компилятора из скомпилированных объектов)

0 голосов
/ 02 июня 2016

Несколько раз man 1 ident было упомянуто, так что здесь подробно об использовании этого метода.

ident - это команда, которая поставляется с RCS (Revision Control System), но может также быть доступна, если вы используете CVS (Concurrent Versions System) или Subversion.

Вы бы использовали это так (клонировано со страницы руководства):

#include <stdio.h>
static char const rcsid[] =
    "$Id: f.c,v 5.4 1993/11/09 17:40:15 eggert Exp $";
int main() { return printf("%s\n", rcsid) == EOF; }

и f.c компилируется в f.o, затем команда

ident 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 $

Если ваш f.o был добавлен в статическую библиотеку f.a, тогда ident f.a должен показать аналогичный вывод. Если в вашем az.a есть несколько одинаково собранных [a-z].o, вы должны найти все их строки в файле az.a.

CAVEAT: То, что они находятся в файле .a, не означает, что они будут включены в файл вашей программы. Если программа не ссылается на них, компоновщик не видит необходимости включать их. Поэтому в каждом модуле обычно требуется метод для возврата строки, и приложение должно вызывать этот метод. Есть способы убедить большинство компоновщиков, что это обязательный символ, без фактической ссылки на него, но это зависит от компоновщика и выходит за рамки этого ответа.

Если вместо этого вы знакомы с SCCS (системой управления исходным кодом), то вместо этого вы должны использовать man 1 what, и это будет выглядеть так (сделано с макросами, чтобы показать доступную гибкость):

#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.c компилируется в f.o, затем команда

what 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: $ эквивалент? , хотя хэш не совпадает с номером версии. :)

...