我正在尋找一個C/C++宏,它可以將一個隨機的SVN版本(如「$ Revision:9 $」或「$ Revision:9999999 $」)轉換爲整數或串。C宏將SVN修訂版本轉換爲整數
我知道存在簡單的函數來實現這一點,但我希望這是在編譯時進行的。
我的願望是寫的東西,如:unsigned int rev = SVN_TO_INT("$Revision$");
我正在尋找一個C/C++宏,它可以將一個隨機的SVN版本(如「$ Revision:9 $」或「$ Revision:9999999 $」)轉換爲整數或串。C宏將SVN修訂版本轉換爲整數
我知道存在簡單的函數來實現這一點,但我希望這是在編譯時進行的。
我的願望是寫的東西,如:unsigned int rev = SVN_TO_INT("$Revision$");
我同意它不可用宏,但是,我發現使用編譯器優化技巧。 其結果是,表達JL_SvnRevToInt(「$修訂: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)))))))));
}
它supports9位修訂號,NULL和空和「$修訂$」的字符串。
我是比較肯定,這是不可能的宏。
模板metaprogramming可能是可能的,但我從來沒有走近它。
也可以使用預編譯腳本將預期文本替換爲SVN_TO_INT。
雖然我不明白你爲什麼要這樣做,因爲在編譯時知道它的版本號會很容易。
你不能完全在預處理處理字符串或編譯的時間 - 但爲什麼不使用的東西是這樣的:
int svn_version()
{
static const int v = extract_svn_version(REVISION);
return v;
}
我想避免將修訂字符串存儲在我的二進制文件(「$ Revision:XXXX $」)中 – 2009-12-02 15:28:21
然後,您必須在源代碼之外完成並在構建環境中對其進行定義 - 即使在C++ 0x似乎有編譯時字符串處理(在此之前沒有),我想仍然不能保證字符串文字將從二進制中消除 - 編譯器可能會或可能不會這樣做。 – 2009-12-02 15:32:40
爲什麼你不需要它在你的二進制文件?我們曾經使用過(在CVS中),我們可以在二進制文件中找到構建信息。一旦二進制文件發送給客戶,我們無法控制他們去哪裏,並且知道某個客戶系統運行的版本有時是非常有用的。 – 2009-12-02 16:03:28
你不能做你想要的那種字符串操作在編譯時與C預處理器(宏)或模板(C++)。您需要使用可從構建過程中調用的外部實用程序或腳本。
有些工具/腳本/代碼,可以幫助你:
我同意,你不能在編譯字符串工作時間通過宏或模板。所以....不要使用字符串。
這是一個醜陋的黑客,但我認爲它滿足您的所有要求。我不推薦它。
#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
如果您有基於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
我的解決辦法是
#define $Revision (false?1
#define $ +0)
int codeRevision() { return $Revision: $; }
#undef $Revision
#undef $
與編譯器的好處是,他們實際上可以用所得到的值替換函數調用,如果你只使用編譯時間常數。當我想比較幾種交換價值的方式時,VC曾經這樣做過;生成的彙編代碼(帶/ O2)根本不包含任何函數調用;只有常數。 – Joey 2009-12-02 14:59:44
如果您想自動將修訂號嵌入到可執行文件中,我認爲您的路徑錯誤,因爲通過svn關鍵字嵌入的修訂版號僅在提交*修改的文件*時纔會更改。因此,您無法確定帶有SVN_TO_INT宏的文件將始終反映您項目的修訂版。 – 2009-12-02 15:11:10
我同意你的評論,但是,每個文件修訂版本系統適合我的使用(每個文件一個類和每個類一個修訂版) – 2009-12-02 15:37:03