diff --git a/SConstruct b/SConstruct index 5dae17718..dc7bbe2c4 100644 --- a/SConstruct +++ b/SConstruct @@ -46,48 +46,16 @@ TODO import collections import os -import platform import subprocess import sys import textwrap -import time import SCons.Action sys.path.append(os.path.join('src', 'beast', 'site_scons')) import Beast -#------------------------------------------------------------------------------ - -def get_platform(): - plat = platform.system().upper() - if plat == 'LINUX': - plat = platform.linux_distribution()[0].upper() - return plat - -def parse_time(t): - return time.strptime(t, '%a %b %d %H:%M:%S %Z %Y') - -CHECK_PLATFORMS = 'DARWIN', 'DEBIAN', 'UBUNTU' -CHECK_COMMAND = 'openssl version -a' -CHECK_LINE = 'built on: ' -BUILD_TIME = 'Mon Apr 7 20:33:19 UTC 2014' -OPENSSL_ERROR = ( - 'Your openSSL was built on %s but we need a version on or after %s.') - -def check_openssl(platform): - if platform in CHECK_PLATFORMS: - for line in subprocess.check_output(CHECK_COMMAND.split()).splitlines(): - if line.startswith(CHECK_LINE): - line = line[len(CHECK_LINE):] - if parse_time(line) < parse_time(BUILD_TIME): - raise Exception(OPENSSL_ERROR % (line, BUILD_TIME)) - else: - break - else: - raise Exception("Didn't find any '%s' line in '$ %s'" % - (CHECK_LINE, CHECK_COMMAND)) - +#------------------------------------------------------------------------------- def import_environ(env): '''Imports environment settings into the construction environment''' @@ -219,10 +187,6 @@ def config_base(env): CXXCOMSTR='Compiling ' + Beast.blue('$SOURCES'), LINKCOMSTR='Linking ' + Beast.blue('$TARGET'), ) - platform = get_platform() - check_openssl(platform) - - env.Append(CPPDEFINES={'RIPPLE_' + platform: 1}) #git = Beast.Git(env) # TODO(TOM) if False: #git.exists: env.Append(CPPDEFINES={'GIT_COMMIT_ID' : '"%s"' % git.commit_id}) diff --git a/src/ripple_app/main/Main.cpp b/src/ripple_app/main/Main.cpp index 213562414..cff234a1c 100644 --- a/src/ripple_app/main/Main.cpp +++ b/src/ripple_app/main/Main.cpp @@ -19,6 +19,7 @@ #include "../../beast/beast/unit_test.h" #include "../../beast/beast/streams/debug_ostream.h" +#include "../../ripple_basics/system/CheckLibraryVersions.h" namespace po = boost::program_options; @@ -164,6 +165,8 @@ runUnitTests (std::string pattern, std::string format) int run (int argc, char** argv) { // Make sure that we have the right OpenSSL and Boost libraries. + version::checkLibraryVersions(); + FatalErrorReporter reporter; using namespace std; diff --git a/src/ripple_app/ripple_app.unity.cpp b/src/ripple_app/ripple_app.unity.cpp index fc03556c6..556153888 100644 --- a/src/ripple_app/ripple_app.unity.cpp +++ b/src/ripple_app/ripple_app.unity.cpp @@ -88,6 +88,7 @@ #include "node/SqliteFactory.cpp" #include "main/Application.cpp" + #include "main/Main.cpp" //------------------------------------------------------------------------------ @@ -108,6 +109,23 @@ struct ProtobufLibrary // int main (int argc, char** argv) { +#if defined(__GNUC__) && !defined(__clang__) + auto constexpr gccver = (__GNUC__ * 100 * 100) + + (__GNUC_MINOR__ * 100) + + __GNUC_PATCHLEVEL__; + + static_assert (gccver >= 40801, + "GCC version 4.8.1 or later is required to compile rippled."); +#endif + +#ifdef _MSC_VER + static_assert (_MSC_VER >= 1800, + "Visual Studio 2013 or later is required to compile rippled."); +#endif + + static_assert (BOOST_VERSION >= 105500, + "Boost version 1.55 or later is required to compile rippled"); + // // These debug heap calls do nothing in release or non Visual Studio builds. // diff --git a/src/ripple_basics/ripple_basics.unity.cpp b/src/ripple_basics/ripple_basics.unity.cpp index 0711a8945..660cf58e2 100644 --- a/src/ripple_basics/ripple_basics.unity.cpp +++ b/src/ripple_basics/ripple_basics.unity.cpp @@ -44,6 +44,7 @@ //------------------------------------------------------------------------------ #include "containers/RangeSet.cpp" +#include "system/CheckLibraryVersions.cpp" #include "log/Log.cpp" #include "log/LogFile.cpp" diff --git a/src/ripple_basics/system/CheckLibraryVersions.cpp b/src/ripple_basics/system/CheckLibraryVersions.cpp index 79295765e..13814e032 100644 --- a/src/ripple_basics/system/CheckLibraryVersions.cpp +++ b/src/ripple_basics/system/CheckLibraryVersions.cpp @@ -20,50 +20,132 @@ #include #include +#include "../../beast/beast/unit_test/suite.h" +#include "../../beast/modules/beast_core/diagnostic/SemanticVersion.h" #include #include +#include "CheckLibraryVersions.h" + namespace ripple { namespace version { -static const int BOOST_MINIMAL = 105500; -static_assert (BOOST_VERSION >= BOOST_MINIMAL, - "Boost version 1.55.0 or later is required to compile rippled."); +/** Both Boost and OpenSSL have integral version numbers. */ +typedef unsigned long long VersionNumber; -#if defined(RIPPLE_UBUNTU) || defined(RIPPLE_DEBIAN) +/** Minimal required boost version. */ +static const char boostMinimal[] = "1.55.0"; -static const int OPENSSL_MINIMAL = 0x1000106fL; -static_assert (OPENSSL_VERSION_NUMBER >= OPENSSL_MINIMAL, - "openSSL version 1.0.1-f or later is required to compile rippled"); +/** Minimal required OpenSSL version. */ +static const char openSSLMinimal[] = "1.0.1-g"; -#else +std::string boostVersion(VersionNumber boostVersion = BOOST_VERSION) +{ + std::stringstream ss; + ss << (boostVersion / 100000) << "." + << (boostVersion / 100 % 1000) << "." + << (boostVersion % 100); + return ss.str(); +} -static const int OPENSSL_MINIMAL = 0x10001070L; -static_assert (OPENSSL_VERSION_NUMBER >= OPENSSL_MINIMAL, - "openSSL version 1.0.1-g or later is required to compile rippled"); +std::string openSSLVersion(VersionNumber openSSLVersion = OPENSSL_VERSION_NUMBER) +{ + std::stringstream ss; + ss << (openSSLVersion / 0x10000000L) << "." + << (openSSLVersion / 0x100000 % 0x100) << "." + << (openSSLVersion / 0x1000 % 0x100); + auto patchNo = openSSLVersion % 0x10; + if (patchNo) + ss << '-' << char('a' + patchNo - 1); + return ss.str(); +} -#endif +void checkVersion(std::string name, std::string required, std::string actual) +{ + beast::SemanticVersion r, a; + if (!r.parse(required)) { + throw std::runtime_error("Didn't understand required version of " + + name + ": " + required); + } + if (!a.parse(actual)) { + throw std::runtime_error("Didn't understand actual version of " + + name + ": " + required); + } -#if defined(__GNUC__) && !defined(__clang__) + if (a < r) { + throw std::runtime_error("Your " + name + " library is out of date.\n" + + "Your version: " + actual + "\n" + + "Required version: " + "\n"); + } +} -static const int GCC_MINIMAL = 40801; -auto constexpr GCC_VERSION_NUMBER = - (__GNUC__ * 100 * 100) + - (__GNUC_MINOR__ * 100) + - __GNUC_PATCHLEVEL__; +void checkBoost(std::string version = boostVersion()) +{ + checkVersion("Boost", boostMinimal, version); +} -static_assert (GCC_VERSION_NUMBER >= 40801, - "GCC version 4.8.1 or later is required to compile rippled."); +void checkOpenSSL(std::string version = openSSLVersion()) +{ + checkVersion("OpenSSL", openSSLMinimal, version); +} -#endif +void checkLibraryVersions() +{ + checkBoost(); + checkOpenSSL(); +} -#ifdef _MSC_VER +struct CheckLibraryVersions_test : beast::unit_test::suite +{ + void print_message() + { + log << "ssl minimal: " << openSSLMinimal << "\n" + << "ssl actual: " << openSSLVersion() << "\n" + << "boost minimal: " << boostMinimal << "\n" + << "boost actual: " << boostVersion() << "\n" + << std::flush; + } -static const int MSVC_MINIMAL = 1800; -static_assert (_MSC_VER >= 1800, - "Visual Studio 2013 or later is required to compile rippled."); + void test_bad_ssl() + { + std::string error; + try { + checkOpenSSL(openSSLVersion(0x0090819fL)); + } catch (std::runtime_error& e) { + error = e.what(); + } + auto expectedError = "Your OpenSSL library is out of date.\n" + "Your version: 0.9.8-o\n" + "Required version: "; + unexpected(error.find(expectedError) != 0, error); + } -#endif + void test_bad_boost() + { + std::string error; + try { + checkBoost(boostVersion(105400)); + } catch (std::runtime_error& e) { + error = e.what(); + } + auto expectedError = "Your Boost library is out of date.\n" + "Your version: 1.54.0\n" + "Required version: "; + unexpected(error.find(expectedError) != 0, error); + } + + + void run() + { + print_message(); + checkLibraryVersions(); + + test_bad_ssl(); + test_bad_boost(); + } +}; + +BEAST_DEFINE_TESTSUITE(CheckLibraryVersions, ripple_basics, ripple); } // namespace version } // namespace ripple diff --git a/src/ripple_basics/system/CheckLibraryVersions.h b/src/ripple_basics/system/CheckLibraryVersions.h new file mode 100644 index 000000000..5bb150dde --- /dev/null +++ b/src/ripple_basics/system/CheckLibraryVersions.h @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012, 2013 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef RIPPLE_CHECKLIBRARYVERSIONS_H_INCLUDED +#define RIPPLE_CHECKLIBRARYVERSIONS_H_INCLUDED + +#include + +namespace ripple { +namespace version { + +/** Check all library versions against Ripple's version requirements. + + Throws std::runtime_error if one or more libraries are out-of-date and do + not meet the version requirements. + */ +void checkLibraryVersions(); + +} // namespace version +} // namespace ripple + +#endif