From a20c0d0f6792acf532309eee2e9f29120c801ee4 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 7 Apr 2012 02:06:53 +0200 Subject: [PATCH] Build identification strings All client version information is moved to version.cpp, which optionally (-DHAVE_BUILD_INFO) includes build.h. build.h is automatically generated on supporting platforms via contrib/genbuild.sh, using git describe. The git export-subst attribute is used to put the commit id statically in version.cpp inside generated archives, and this value is used if no build.h is present. The gitian descriptors are modified to use git archive instead of a copy, to create the src/ directory in the output. This way, src/src/version.cpp will contain the static commit id. To prevent gitian builds from getting the "-dirty" marker in their git-describe generated identifiers, no touching of files or running sed on the makefile is performed anymore. This does not seem to influence determinism. --- .gitattributes | 1 + .gitignore | 1 + bitcoin-qt.pro | 10 ++++ contrib/gitian-descriptors/gitian-win32.yml | 19 ++++--- contrib/gitian-descriptors/gitian.yml | 6 +-- doc/release-process.txt | 2 +- share/genbuild.sh | 35 ++++++++++++ src/init.cpp | 2 +- src/main.cpp | 5 -- src/main.h | 5 +-- src/makefile.linux-mingw | 10 +++- src/makefile.mingw | 2 + src/makefile.osx | 10 +++- src/makefile.unix | 10 +++- src/qt/aboutdialog.cpp | 2 + src/qt/clientmodel.cpp | 5 ++ src/qt/clientmodel.h | 1 + src/util.cpp | 7 +-- src/version.cpp | 77 +++++++++++++++++++++++++++ src/version.h | 14 +++++ 20 files changed, 193 insertions(+), 31 deletions(-) create mode 100644 .gitattributes create mode 100755 share/genbuild.sh create mode 100644 src/version.cpp create mode 100644 src/version.h diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..26d7549 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +src/version.cpp export-subst diff --git a/.gitignore b/.gitignore index 66f9386..dafbc2b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ src/*.exe src/bitcoin src/bitcoind +src/build.h .*.swp *.*~* *.bak diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro index 8b34d6c..46caa22 100644 --- a/bitcoin-qt.pro +++ b/bitcoin-qt.pro @@ -80,6 +80,15 @@ contains(BITCOIN_NEED_QT_PLUGINS, 1) { # do not enable this on windows, as it will result in a non-working executable! } +# regenerate src/build.h +!windows || contains(USE_BUILD_INFO, 1) { + genbuild.commands = share/genbuild.sh src/build.h + genbuild.target = src/build.h + "src/version.cpp".depends += src/build.h + QMAKE_EXTRA_TARGETS += genbuild + DEFINES += HAVE_BUILD_INFO +} + # disable quite some warnings because bitcoin core "sins" a lot QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wno-strict-aliasing -Wno-invalid-offsetof -Wno-unused-variable -Wno-unused-parameter -Wno-sign-compare -Wno-char-subscripts -Wno-unused-value -Wno-sequence-point -Wno-parentheses -Wno-unknown-pragmas -Wno-switch @@ -161,6 +170,7 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ src/qt/aboutdialog.cpp \ src/qt/editaddressdialog.cpp \ src/qt/bitcoinaddressvalidator.cpp \ + src/version.cpp \ src/util.cpp \ src/netbase.cpp \ src/key.cpp \ diff --git a/contrib/gitian-descriptors/gitian-win32.yml b/contrib/gitian-descriptors/gitian-win32.yml index e929eb8..49bc9c7 100644 --- a/contrib/gitian-descriptors/gitian-win32.yml +++ b/contrib/gitian-descriptors/gitian-win32.yml @@ -45,25 +45,30 @@ script: | # cd bitcoin mkdir -p $OUTDIR/src - cp -a . $OUTDIR/src - rm -rf $OUTDIR/src/.git + git archive HEAD | tar -x -C $OUTDIR/src cp $OUTDIR/src/doc/README_windows.txt $OUTDIR/readme.txt cp $OUTDIR/src/COPYING $OUTDIR/license.txt export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 export FAKETIME=$REFERENCE_DATETIME export TZ=UTC - $HOME/qt/src/bin/qmake -spec unsupported/win32-g++-cross MINIUPNPC_LIB_PATH=$HOME/build/miniupnpc MINIUPNPC_INCLUDE_PATH=$HOME/build/ BDB_LIB_PATH=$HOME/build/db-4.8.30.NC/build_unix BDB_INCLUDE_PATH=$HOME/build/db-4.8.30.NC/build_unix BOOST_LIB_PATH=$HOME/build/boost_1_47_0/stage/lib BOOST_INCLUDE_PATH=$HOME/build/boost_1_47_0 BOOST_LIB_SUFFIX=-mt-s BOOST_THREAD_LIB_SUFFIX=_win32-mt-s OPENSSL_LIB_PATH=$HOME/build/openssl-1.0.0e OPENSSL_INCLUDE_PATH=$HOME/build/openssl-1.0.0e/include QRENCODE_LIB_PATH=$HOME/build/qrencode-3.2.0/.libs QRENCODE_INCLUDE_PATH=$HOME/build/qrencode-3.2.0 USE_QRCODE=1 INCLUDEPATH=$HOME/build DEFINES=BOOST_THREAD_USE_LIB BITCOIN_NEED_QT_PLUGINS=1 QMAKE_LRELEASE=lrelease QMAKE_CXXFLAGS=-frandom-seed=bitcoin QMAKE_LFLAGS=-frandom-seed=bitcoin + $HOME/qt/src/bin/qmake -spec unsupported/win32-g++-cross MINIUPNPC_LIB_PATH=$HOME/build/miniupnpc MINIUPNPC_INCLUDE_PATH=$HOME/build/ BDB_LIB_PATH=$HOME/build/db-4.8.30.NC/build_unix BDB_INCLUDE_PATH=$HOME/build/db-4.8.30.NC/build_unix BOOST_LIB_PATH=$HOME/build/boost_1_47_0/stage/lib BOOST_INCLUDE_PATH=$HOME/build/boost_1_47_0 BOOST_LIB_SUFFIX=-mt-s BOOST_THREAD_LIB_SUFFIX=_win32-mt-s OPENSSL_LIB_PATH=$HOME/build/openssl-1.0.0e OPENSSL_INCLUDE_PATH=$HOME/build/openssl-1.0.0e/include QRENCODE_LIB_PATH=$HOME/build/qrencode-3.2.0/.libs QRENCODE_INCLUDE_PATH=$HOME/build/qrencode-3.2.0 USE_QRCODE=1 INCLUDEPATH=$HOME/build DEFINES=BOOST_THREAD_USE_LIB BITCOIN_NEED_QT_PLUGINS=1 QMAKE_LRELEASE=lrelease QMAKE_CXXFLAGS=-frandom-seed=bitcoin QMAKE_LFLAGS=-frandom-seed=bitcoin USE_BUILD_INFO=1 make $MAKEOPTS cp release/bitcoin-qt.exe $OUTDIR/ # cd src - sed 's/$(DEBUGFLAGS)/-frandom-seed=bitcoin/' -i makefile.linux-mingw export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 export FAKETIME=$REFERENCE_DATETIME export TZ=UTC - make -f makefile.linux-mingw $MAKEOPTS DEPSDIR=$HOME/build bitcoind.exe USE_UPNP=0 + make -f makefile.linux-mingw $MAKEOPTS DEPSDIR=$HOME/build bitcoind.exe USE_UPNP=0 DEBUGFLAGS="-frandom-seed=bitcoin" i586-mingw32msvc-strip bitcoind.exe - makensis ../share/setup.nsi - cp ../share/bitcoin-*-win32-setup.exe $OUTDIR/ mkdir $OUTDIR/daemon cp bitcoind.exe $OUTDIR/daemon + cd .. + mkdir nsis + git archive HEAD | tar -x -C nsis + cd nsis/src + mkdir ../release + cp ../../release/* ../release/ + cp ../../src/*.exe . + makensis ../share/setup.nsi + cp ../share/bitcoin-*-win32-setup.exe $OUTDIR/ diff --git a/contrib/gitian-descriptors/gitian.yml b/contrib/gitian-descriptors/gitian.yml index de622e9..8243c5c 100644 --- a/contrib/gitian-descriptors/gitian.yml +++ b/contrib/gitian-descriptors/gitian.yml @@ -42,13 +42,11 @@ script: | # cd bitcoin mkdir -p $OUTDIR/src - cp -a . $OUTDIR/src - rm -rf $OUTDIR/src/.git + git archive HEAD | tar -x -C $OUTDIR/src cp $OUTDIR/src/doc/README $OUTDIR cp $OUTDIR/src/COPYING $OUTDIR cd src - sed 's/$(DEBUGFLAGS)//' -i makefile.unix - make -f makefile.unix STATIC=1 OPENSSL_INCLUDE_PATH="$INSTDIR/include" OPENSSL_LIB_PATH="$INSTDIR/lib" $MAKEOPTS bitcoind USE_UPNP=0 + make -f makefile.unix STATIC=1 OPENSSL_INCLUDE_PATH="$INSTDIR/include" OPENSSL_LIB_PATH="$INSTDIR/lib" $MAKEOPTS bitcoind USE_UPNP=0 DEBUGFLAGS= mkdir -p $OUTDIR/bin/$GBUILD_BITS install -s bitcoind $OUTDIR/bin/$GBUILD_BITS cd .. diff --git a/doc/release-process.txt b/doc/release-process.txt index 051a215..3f3c6da 100644 --- a/doc/release-process.txt +++ b/doc/release-process.txt @@ -2,7 +2,7 @@ * update (commit) version in sources bitcoin-qt.pro - src/main.h (CLIENT_VERSION : PROTOCOL_VERSION in serialize.h is updated only on protocol changes) + src/version.cpp share/setup.nsi doc/README* diff --git a/share/genbuild.sh b/share/genbuild.sh new file mode 100755 index 0000000..d959877 --- /dev/null +++ b/share/genbuild.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +if [ $# -gt 0 ]; then + FILE="$1" + shift + if [ -f "$FILE" ]; then + INFO="$(head -n 1 "$FILE")" + fi +else + echo "Usage: $0 " + exit 1 +fi + +if [ -e "$(which git)" ]; then + # clean 'dirty' status of touched files that haven't been modified + git diff >/dev/null 2>/dev/null + + # get a string like "v0.6.0-66-g59887e8-dirty" + DESC="$(git describe --dirty 2>/dev/null)" + + # get a string like "2012-04-10 16:27:19 +0200" + TIME="$(git log -n 1 --format="%ci")" +fi + +if [ -n "$DESC" ]; then + NEWINFO="#define BUILD_DESC \"$DESC\"" +else + NEWINFO="// No build information available" +fi + +# only update build.h if necessary +if [ "$INFO" != "$NEWINFO" ]; then + echo "$NEWINFO" >"$FILE" + echo "#define BUILD_DATE \"$TIME\"" >>"$FILE" +fi diff --git a/src/init.cpp b/src/init.cpp index 3f900fc..9d37eb3 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -307,7 +307,7 @@ bool AppInit2(int argc, char* argv[]) if (!fDebug && !pszSetDataDir[0]) ShrinkDebugFile(); printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); - printf("Bitcoin version %s\n", FormatFullVersion().c_str()); + printf("Bitcoin version %s (%s)\n", FormatFullVersion().c_str(), CLIENT_DATE.c_str()); printf("Default data directory %s\n", GetDefaultDataDir().c_str()); if (GetBoolArg("-loadblockindextest")) diff --git a/src/main.cpp b/src/main.cpp index 7c49316..7e257f4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,11 +18,6 @@ using namespace boost; // Global state // -// Name of client reported in the 'version' message. Report the same name -// for both bitcoind and bitcoin-qt, to make it harder for attackers to -// target servers or GUI users specifically. -const std::string CLIENT_NAME("Satoshi"); - CCriticalSection cs_setpwalletRegistered; set setpwalletRegistered; diff --git a/src/main.h b/src/main.h index 6c81aba..1d46851 100644 --- a/src/main.h +++ b/src/main.h @@ -10,6 +10,7 @@ #include "key.h" #include "script.h" #include "db.h" +#include "version.h" #ifdef WIN32 #include /* for _commit */ @@ -30,10 +31,6 @@ class CInv; class CRequestTracker; class CNode; -static const int CLIENT_VERSION = 60099; -static const bool VERSION_IS_BETA = true; -extern const std::string CLIENT_NAME; - static const unsigned int MAX_BLOCK_SIZE = 1000000; static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2; static const int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw index 3f7e611..4922df5 100644 --- a/src/makefile.linux-mingw +++ b/src/makefile.linux-mingw @@ -43,6 +43,7 @@ LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l w HEADERS = $(wildcard *.h) OBJS= \ + obj/version.o \ obj/checkpoints.o \ obj/netbase.o \ obj/addrman.o \ @@ -64,10 +65,14 @@ OBJS= \ all: bitcoind.exe +build.h: FORCE + @../share/genbuild.sh build.h +DEFS += -DHAVE_BUILD_INFO + obj/%.o: %.cpp $(HEADERS) i586-mingw32msvc-g++ -c $(CFLAGS) -o $@ $< -bitcoind.exe: $(OBJS:obj/%=obj/%) +bitcoind.exe: build.h $(OBJS:obj/%=obj/%) i586-mingw32msvc-g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) @@ -85,3 +90,6 @@ clean: -rm -f headers.h.gch -rm -f bitcoind.exe -rm -f test_bitcoin.exe + -rm -f src/build.h + +FORCE: diff --git a/src/makefile.mingw b/src/makefile.mingw index 33cc68b..397fdf4 100644 --- a/src/makefile.mingw +++ b/src/makefile.mingw @@ -41,6 +41,7 @@ LIBS += -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell HEADERS = $(wildcard *.h) OBJS= \ + obj/version.o \ obj/checkpoints.o \ obj/netbase.o \ obj/addrman.o \ @@ -82,3 +83,4 @@ clean: -del /Q obj\test\* -del /Q test\*.o -del /Q headers.h.gch + -del /Q build.h diff --git a/src/makefile.osx b/src/makefile.osx index ed35b33..439d8ef 100644 --- a/src/makefile.osx +++ b/src/makefile.osx @@ -65,6 +65,7 @@ CFLAGS += -Wextra -Wno-sign-compare -Wno-char-subscripts -Wno-invalid-offsetof - $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS) OBJS= \ + obj/version.o \ obj/checkpoints.o \ obj/netbase.o \ obj/addrman.o \ @@ -99,6 +100,10 @@ all: bitcoind -include obj/*.P -include obj-test/*.P +build.h: FORCE + @../share/genbuild.sh build.h +DEFS += -DHAVE_BUILD_INFO + obj/%.o: %.cpp $(CXX) -c $(CFLAGS) -MMD -o $@ $< @cp $(@:%.o=%.d) $(@:%.o=%.P); \ @@ -106,7 +111,7 @@ obj/%.o: %.cpp -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ rm -f $(@:%.o=%.d) -bitcoind: $(OBJS:obj/%=obj/%) +bitcoind: build.h $(OBJS:obj/%=obj/%) $(CXX) $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp)) @@ -127,3 +132,6 @@ clean: -rm -f obj-test/*.o -rm -f obj/*.P -rm -f obj-test/*.P + -rm -f src/build.h + +FORCE: diff --git a/src/makefile.unix b/src/makefile.unix index 1fb8e27..c372736 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -85,6 +85,7 @@ xCXXFLAGS=-pthread -Wextra -Wno-sign-compare -Wno-char-subscripts -Wno-invalid-o $(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS) OBJS= \ + obj/version.o \ obj/checkpoints.o \ obj/netbase.o \ obj/addrman.o \ @@ -111,6 +112,10 @@ all: bitcoind -include obj/*.P -include obj-test/*.P +build.h: FORCE + @../share/genbuild.sh build.h +DEFS += -DHAVE_BUILD_INFO + obj/%.o: %.cpp $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< @cp $(@:%.o=%.d) $(@:%.o=%.P); \ @@ -118,7 +123,7 @@ obj/%.o: %.cpp -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ rm -f $(@:%.o=%.d) -bitcoind: $(OBJS:obj/%=obj/%) +bitcoind: build.h $(OBJS:obj/%=obj/%) $(CXX) $(xCXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp)) @@ -139,3 +144,6 @@ clean: -rm -f obj-test/*.o -rm -f obj/*.P -rm -f obj-test/*.P + -rm -f src/build.h + +FORCE: diff --git a/src/qt/aboutdialog.cpp b/src/qt/aboutdialog.cpp index 08d7774..0b98bef 100644 --- a/src/qt/aboutdialog.cpp +++ b/src/qt/aboutdialog.cpp @@ -2,6 +2,8 @@ #include "ui_aboutdialog.h" #include "clientmodel.h" +#include "version.h" + AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDialog) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 8163da0..284bee0 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -88,3 +88,8 @@ QString ClientModel::formatFullVersion() const { return QString::fromStdString(FormatFullVersion()); } + +QString ClientModel::formatBuildDate() const +{ + return QString::fromStdString(CLIENT_DATE); +} diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 6366b4d..8e7431a 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -37,6 +37,7 @@ public: QString getStatusBarWarnings() const; QString formatFullVersion() const; + QString formatBuildDate() const; private: OptionsModel *optionsModel; diff --git a/src/util.cpp b/src/util.cpp index d55e7ae..7354df6 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1061,12 +1061,7 @@ string FormatVersion(int nVersion) string FormatFullVersion() { - string s = FormatVersion(CLIENT_VERSION); - if (VERSION_IS_BETA) { - s += "-"; - s += _("beta"); - } - return s; + return CLIENT_BUILD; } // Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014) diff --git a/src/version.cpp b/src/version.cpp new file mode 100644 index 0000000..e1be5f4 --- /dev/null +++ b/src/version.cpp @@ -0,0 +1,77 @@ +// Copyright (c) 2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file license.txt or http://www.opensource.org/licenses/mit-license.php. +#include + +#include "version.h" + +// Name of client reported in the 'version' message. Report the same name +// for both bitcoind and bitcoin-qt, to make it harder for attackers to +// target servers or GUI users specifically. +const std::string CLIENT_NAME("Satoshi"); + +// Client version number +#define CLIENT_VERSION_MAJOR 0 +#define CLIENT_VERSION_MINOR 6 +#define CLIENT_VERSION_REVISION 0 +#define CLIENT_VERSION_BUILD 99 +#define CLIENT_VERSION_SUFFIX "-beta" + +const int CLIENT_VERSION = 1000000 * CLIENT_VERSION_MAJOR + + 10000 * CLIENT_VERSION_MINOR + + 100 * CLIENT_VERSION_REVISION + + 1 * CLIENT_VERSION_BUILD; + + + +// The following part of the code determines the CLIENT_BUILD variable. +// Several mechanisms are used for this: +// * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is +// generated by the build environment, possibly containing the output +// of git-describe in a macro called BUILD_DESC +// * secondly, if this is an exported version of the code, GIT_ARCHIVE will +// be defined (automatically using the export-subst git attribute), and +// GIT_COMMIT will contain the commit id. +// * then, three options exist for determining CLIENT_BUILD: +// * if BUILD_DESC is defined, use that literally (output of git-describe) +// * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit] +// * otherwise, use v[maj].[min].[rev].[build]-unk +// finally CLIENT_VERSION_SUFFIX is added + +// First, include build.h if requested +#ifdef HAVE_BUILD_INFO +# include "build.h" +#endif + +// git will put "#define GIT_ARCHIVE 1" on the next line inside archives. $Format:%n#define GIT_ARCHIVE 1$ +#ifdef GIT_ARCHIVE +# define GIT_COMMIT_ID "$Format:%h$" +# define GIT_COMMIT_DATE "$Format:%cD" +#endif + +#define STRINGIFY(s) #s + +#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \ + "v" STRINGIFY(maj) "." STRINGIFY(min) "." STRINGIFY(rev) "." STRINGIFY(build) "-g" commit + +#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) \ + "v" STRINGIFY(maj) "." STRINGIFY(min) "." STRINGIFY(rev) "." STRINGIFY(build) "-unk" + +#ifndef BUILD_DESC +# ifdef GIT_COMMIT_ID +# define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID) +# else +# define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD) +# endif +#endif + +#ifndef BUILD_DATE +# ifdef GIT_COMMIT_DATE +# define BUILD_DATE GIT_COMMIT_DATE +# else +# define BUILD_DATE __DATE__ ", " __TIME__ +# endif +#endif + +const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX); +const std::string CLIENT_DATE(BUILD_DATE); diff --git a/src/version.h b/src/version.h new file mode 100644 index 0000000..c93b28f --- /dev/null +++ b/src/version.h @@ -0,0 +1,14 @@ +// Copyright (c) 2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file license.txt or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_VERSION_H +#define BITCOIN_VERSION_H + +#include + +extern const std::string CLIENT_NAME; +extern const std::string CLIENT_BUILD; +extern const std::string CLIENT_DATE; +extern const int CLIENT_VERSION; + +#endif -- 1.7.1