Макрос C для преобразования ревизии SVN в целое число - PullRequest
1 голос
/ 02 декабря 2009

Я ищу макрос C / C ++, который может преобразовать случайную версию SVN, такую ​​как "$ Revision: 9 $" или "$ Revision: 9999999 $", в целое число или строку.

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

Я хочу написать что-то вроде: unsigned int rev = SVN_TO_INT("$Revision$");

Ответы [ 7 ]

6 голосов
/ 02 декабря 2009

Я согласен, что вы не можете работать со строками во время компиляции через макросы или шаблоны. Так что .... не используйте строки.

Это безобразный хак, но я думаю, что он отвечает всем вашим требованиям. Я не рекомендую это.

#define $Revision struct REV_STR { unsigned foo
#define $ * 64; };

$Revision: 4521 $

enum { REV = sizeof(REV_STR) / 8 };

#undef $Revision
#undef $

#include <iostream>
int main()
{
   std::cout << REV << std::endl;
   return 0;
}

// $ g++ -Wall -Wextra revision.cpp && ./a.exe
// revision.cpp:4: warning: width of `REV_STR::foo' exceeds its type
// 4521
2 голосов
/ 14 марта 2012

Мое решение

#define $Revision (false?1
#define $ +0)

int codeRevision() { return $Revision: $; }

#undef $Revision
#undef $
2 голосов
/ 02 декабря 2009

Вы не можете делать то, что вам нужно во время компиляции, с помощью препроцессора C (макросы) или с помощью шаблонов (C ++). Вам нужно будет использовать внешнюю утилиту или скрипт, который вы можете вызвать из процесса сборки.

Некоторые утилиты / скрипты / код, которые могут вам помочь:

2 голосов
/ 02 декабря 2009

Я относительно уверен, что это невозможно с макросом.

Это может быть возможно с метапрограммированием шаблона, но я никогда не подходил к нему.

Это также возможно при использовании сценария предварительной сборки, который заменяет SVN_TO_INT на нужный текст.

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

1 голос
/ 03 декабря 2009

Если у вас есть система сборки на основе makefile, вы можете создать специальное правило, которое создает файл каждый make раз.

.PHONY: svn_revision.c

svn_revision.c:
        echo -n "int svn_revision = " > svn_revision.c
        svn info | grep Revision | cut -f2 -d" " >> svn_revision.c
        echo ";"  >> svn_revision.c

svn_revision.o: svn_revision.c
1 голос
/ 03 декабря 2009

Я согласен, что с макросами это невозможно, однако я нашел хитрость с помощью оптимизации компилятора. В результате выражение JL_SvnRevToInt («$ Revision: 12345 $») сводится к одному целому числу без знака: 12345

inline unsigned int JL_SvnRevToInt(const char *r) {


    if ( r == NULL || r[0] == '\0' || r[10] == '\0' || r[11] == '\0' || r[12] == '\0' || r[13] == '\0' )
    return 0;

    const unsigned int count = 
          r[11] == ' ' ? 1
        : r[12] == ' ' ? 10
        : r[13] == ' ' ? 100
        : r[14] == ' ' ? 1000
        : r[15] == ' ' ? 10000
        : r[16] == ' ' ? 100000
        : r[17] == ' ' ? 1000000
        : r[18] == ' ' ? 10000000
        : r[19] == ' ' ? 100000000
        : 0;

    return
        (r[11] == ' ' ? 0 : (r[11]-'0') * (count/10) +
        (r[12] == ' ' ? 0 : (r[12]-'0') * (count/100) + 
        (r[13] == ' ' ? 0 : (r[13]-'0') * (count/1000) + 
        (r[14] == ' ' ? 0 : (r[14]-'0') * (count/10000) + 
        (r[15] == ' ' ? 0 : (r[15]-'0') * (count/100000) +
        (r[16] == ' ' ? 0 : (r[16]-'0') * (count/1000000) +
        (r[17] == ' ' ? 0 : (r[17]-'0') * (count/10000000) +
        (r[18] == ' ' ? 0 : (r[18]-'0') * (count/100000000) +
        (r[19] == ' ' ? 0 : (r[19]-'0') * (count/1000000000) +
        0)))))))));
}

Он поддерживает 9-значный номер ревизии, NULL и пустые строки и строки "$ Revision $".

1 голос
/ 02 декабря 2009

Вы не можете полностью работать со строками во время предварительной обработки или во время компиляции - но почему бы не использовать что-то вроде:

int svn_version() 
{
     static const int v = extract_svn_version(REVISION);
     return v;
}
...