Skip to content

Commit

Permalink
Merge PIVX-Project#1703: [Build] Require minimum boost version 1.57.0
Browse files Browse the repository at this point in the history
44c13ee Travis: Remove trusty test target (Fuzzbawls)
9c6cb1b Doccument the minimum boost version bump (Fuzzbawls)
e0d5271 Enforce that no deprecated boost filesystem methods can be re-introduced (Fuzzbawls)
c9f53b5 Stop using deprecated boost filesystem methods (Fuzzbawls)
85210ec Build: Remove redundant configure-time boost fallbacks (Fuzzbawls)
35748bb Build: Remove old boost version precompiler fallbacks (Fuzzbawls)
249c442 Build: Set minimum Boost version to 1.57.0 (Fuzzbawls)

Pull request description:

  This implements a minimum required boost version bump, pursuant to PIVX-Project#1682

  The configure script has been updated to require a detected version of at least 1.57.0, and now-redundant sub-checks have been removed. Precompiler macros that offered version or feature fallbacks have also been largely removed as they are unnecessary.

  Finally, this also updates some Boost Filesystem Path codebase that was using deprecated methods, and sets the `BOOST_FILESYSTEM_NO_DEPRECATED` macro so that such methods do not get re-added to the codebase in the future.

  Ready for review, but should not be merged until after the `4.2` branch-off.

ACKs for top commit:
  furszy:
    utACK 44c13ee
  random-zebra:
    utACK 44c13ee and merging...

Tree-SHA512: 2491625f21f488bcec025f75eebfd50a571a6c896892f6c902febf1ed2262e453ed71c4c1f5ae2901e30c5f4a2f58c404851995b31008d66b40fd59b98fb82c5
  • Loading branch information
random-zebra committed Jul 15, 2020
2 parents fda84ee + 44c13ee commit 2e11030
Show file tree
Hide file tree
Showing 15 changed files with 23 additions and 224 deletions.
11 changes: 0 additions & 11 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,17 +156,6 @@ jobs:
BITCOIN_CONFIG="--enable-zmq --with-gui=no --enable-glibc-back-compat --enable-reduce-exports"
BUILD_TIMEOUT=800
- stage: test
name: 'x86_64 Linux [GOAL: install] [trusty] [no functional tests, no depends, no GUI, only system libs]'
env: >-
HOST=x86_64-unknown-linux-gnu
DOCKER_NAME_TAG=ubuntu:14.04
PACKAGES="python3-zmq libicu-dev libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libdb5.1++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libgmp-dev"
NO_DEPENDS=1
RUN_FUNCTIONAL_TESTS=false
GOAL="install"
BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --with-gui=no --disable-bench"
- stage: test
name: 'x86_64 Linux [GOAL: install] [xenial] [no depends, only system libs]'
env: >-
Expand Down
113 changes: 2 additions & 111 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,7 @@ fi
if test x$use_boost = xyes; then

dnl Minimum required Boost version
define(MINIMUM_REQUIRED_BOOST, 1.47.0)
define(MINIMUM_REQUIRED_BOOST, 1.57.0)

dnl Check for boost libs
AX_BOOST_BASE([MINIMUM_REQUIRED_BOOST])
Expand All @@ -943,26 +943,6 @@ dnl Boost 1.56 through 1.62 allow using std::atomic instead of its own atomic
dnl counter implementations. In 1.63 and later the std::atomic approach is default.
m4_pattern_allow(DBOOST_AC_USE_STD_ATOMIC) dnl otherwise it's treated like a macro
BOOST_CPPFLAGS="-DBOOST_SP_USE_STD_ATOMIC -DBOOST_AC_USE_STD_ATOMIC $BOOST_CPPFLAGS"

if test x$use_reduce_exports = xyes; then
AC_MSG_CHECKING([for working boost reduced exports])
TEMP_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS"
AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[
@%:@include <boost/version.hpp>
]], [[
#if BOOST_VERSION >= 104900
// Everything is okay
#else
# error Boost version is too old
#endif
]])],[
AC_MSG_RESULT(yes)
],[
AC_MSG_ERROR([boost versions < 1.49 are known to be broken with reduced exports. Use --disable-reduce-exports.])
])
CPPFLAGS="$TEMP_CPPFLAGS"
fi
fi

if test x$use_reduce_exports = xyes; then
Expand Down Expand Up @@ -1003,96 +983,7 @@ if test x$use_tests = xyes; then
fi

if test x$use_boost = xyes; then

BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_PROGRAM_OPTIONS_LIB $BOOST_THREAD_LIB $BOOST_CHRONO_LIB"


dnl If boost (prior to 1.57) was built without c++11, it emulated scoped enums
dnl using c++98 constructs. Unfortunately, this implementation detail leaked into
dnl the abi. This was fixed in 1.57.

dnl When building against that installed version using c++11, the headers pick up
dnl on the native c++11 scoped enum support and enable it, however it will fail to
dnl link. This can be worked around by disabling c++11 scoped enums if linking will
dnl fail.
dnl BOOST_NO_SCOPED_ENUMS was changed to BOOST_NO_CXX11_SCOPED_ENUMS in 1.51.

TEMP_LIBS="$LIBS"
LIBS="$BOOST_LIBS $LIBS"
TEMP_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
AC_MSG_CHECKING([for mismatched boost c++11 scoped enums])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <boost/config.hpp>
#include <boost/version.hpp>
#if !defined(BOOST_NO_SCOPED_ENUMS) && !defined(BOOST_NO_CXX11_SCOPED_ENUMS) && BOOST_VERSION < 105700
#define BOOST_NO_SCOPED_ENUMS
#define BOOST_NO_CXX11_SCOPED_ENUMS
#define CHECK
#endif
#include <boost/filesystem.hpp>
]],[[
#if defined(CHECK)
boost::filesystem::copy_file("foo", "bar");
#else
choke;
#endif
]])],
[AC_MSG_RESULT(mismatched); BOOST_CPPFLAGS="$BOOST_CPPFLAGS -DBOOST_NO_SCOPED_ENUMS -DBOOST_NO_CXX11_SCOPED_ENUMS"], [AC_MSG_RESULT(ok)])
LIBS="$TEMP_LIBS"
CPPFLAGS="$TEMP_CPPFLAGS"

dnl Boost >= 1.50 uses sleep_for rather than the now-deprecated sleep, however
dnl it was broken from 1.50 to 1.52 when backed by nanosleep. Use sleep_for if
dnl a working version is available, else fall back to sleep. sleep was removed
dnl after 1.56.
dnl If neither is available, abort.
TEMP_LIBS="$LIBS"
LIBS="$BOOST_LIBS $LIBS"
TEMP_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <boost/thread/thread.hpp>
#include <boost/version.hpp>
]],[[
#if BOOST_VERSION >= 105000 && (!defined(BOOST_HAS_NANOSLEEP) || BOOST_VERSION >= 105200)
boost::this_thread::sleep_for(boost::chrono::milliseconds(0));
#else
choke me
#endif
]])],
[boost_sleep=yes;
AC_DEFINE(HAVE_WORKING_BOOST_SLEEP_FOR, 1, [Define this symbol if boost sleep_for works])],
[boost_sleep=no])
LIBS="$TEMP_LIBS"
CPPFLAGS="$TEMP_CPPFLAGS"

if test x$boost_sleep != xyes; then
TEMP_LIBS="$LIBS"
LIBS="$BOOST_LIBS $LIBS"
TEMP_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <boost/version.hpp>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
]],[[
#if BOOST_VERSION <= 105600
boost::this_thread::sleep(boost::posix_time::milliseconds(0));
#else
choke me
#endif
]])],
[boost_sleep=yes; AC_DEFINE(HAVE_WORKING_BOOST_SLEEP, 1, [Define this symbol if boost sleep works])],
[boost_sleep=no])
LIBS="$TEMP_LIBS"
CPPFLAGS="$TEMP_CPPFLAGS"
fi

if test x$boost_sleep != xyes; then
AC_MSG_ERROR(No working boost sleep implementation found.)
fi

BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_PROGRAM_OPTIONS_LIB $BOOST_THREAD_LIB $BOOST_CHRONO_LIB"
fi

if test x$use_pkgconfig = xyes; then
Expand Down
2 changes: 1 addition & 1 deletion doc/dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ These are the dependencies currently used by PIVX Core. You can find instruction
| Dependency | Version used | Minimum required | CVEs | Shared | [Bundled Qt library](https://doc.qt.io/qt-5/configure-options.html#third-party-libraries) |
| --- | --- | --- | --- | --- | --- |
| Berkeley DB | [4.8.30](https://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html) | 4.8.x | No | | |
| Boost | [1.64.0](https://www.boost.org/users/download/) | [1.47.0](https://github.com/bitcoin/bitcoin/pull/8920) | No | | |
| Boost | [1.64.0](https://www.boost.org/users/download/) | [1.57.0](https://github.com/PIVX-Project/PIVX/pull/1703) | No | | |
| Clang | | [3.3+](https://llvm.org/releases/download.html) (C++11 support) | | | |
| D-Bus | [1.10.18](https://cgit.freedesktop.org/dbus/dbus/tree/NEWS?h=dbus-1.10) | | No | Yes | |
| Expat | [2.2.6](https://libexpat.github.io/) | | No | Yes | |
Expand Down
1 change: 1 addition & 0 deletions src/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <stdio.h>
#include <string>

#define BOOST_FILESYSTEM_NO_DEPRECATED
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/detail/utf8_codecvt_facet.hpp>
Expand Down
3 changes: 2 additions & 1 deletion src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1081,7 +1081,8 @@ bool AppInit2()
std::string strDataDir = GetDataDir().string();
#ifdef ENABLE_WALLET
// Wallet file must be a plain filename without a directory
if (strWalletFile != fs::basename(strWalletFile) + fs::extension(strWalletFile))
fs::path wallet_file_path(strWalletFile);
if (strWalletFile != wallet_file_path.filename().string())
return UIError(strprintf(_("Wallet %s resides outside data directory %s"), strWalletFile, strDataDir));
#endif
// Make sure only a single PIVX process is using the data directory.
Expand Down
15 changes: 0 additions & 15 deletions src/qt/guiutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@
#include <QMouseEvent>


#if BOOST_FILESYSTEM_VERSION >= 3
static fs::detail::utf8_codecvt_facet utf8;
#endif

#if defined(Q_OS_MAC)
extern double NSAppKitVersionNumber;
Expand Down Expand Up @@ -895,7 +893,6 @@ void setClipboard(const QString& str)
QApplication::clipboard()->setText(str, QClipboard::Selection);
}

#if BOOST_FILESYSTEM_VERSION >= 3
fs::path qstringToBoostPath(const QString& path)
{
return fs::path(path.toStdString(), utf8);
Expand All @@ -905,18 +902,6 @@ QString boostPathToQString(const fs::path& path)
{
return QString::fromStdString(path.string(utf8));
}
#else
#warning Conversion between boost path and QString can use invalid character encoding with boost_filesystem v2 and older
fs::path qstringToBoostPath(const QString& path)
{
return fs::path(path.toStdString());
}

QString boostPathToQString(const fs::path& path)
{
return QString::fromStdString(path.string());
}
#endif

QString formatDurationStr(int secs)
{
Expand Down
3 changes: 2 additions & 1 deletion src/qt/pivx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,8 @@ int main(int argc, char* argv[])
std::string strWalletFile = GetArg("-wallet", "wallet.dat");
std::string strDataDir = GetDataDir().string();
// Wallet file must be a plain filename without a directory
if (strWalletFile != fs::basename(strWalletFile) + fs::extension(strWalletFile)){
fs::path wallet_file_path(strWalletFile);
if (strWalletFile != wallet_file_path.filename().string()) {
throw std::runtime_error(strprintf(_("Wallet %s resides outside data directory %s"), strWalletFile, strDataDir));
}

Expand Down
12 changes: 5 additions & 7 deletions src/qt/pivx/masternodeswidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,8 @@ void MasterNodesWidget::onDeleteMNClicked()

std::string strConfFile = "masternode.conf";
std::string strDataDir = GetDataDir().string();
if (strConfFile != fs::basename(strConfFile) + fs::extension(strConfFile)) {
fs::path conf_file_path(strConfFile);
if (strConfFile != conf_file_path.filename().string()) {
throw std::runtime_error(strprintf(_("masternode.conf %s resides outside data directory %s"), strConfFile, strDataDir));
}

Expand Down Expand Up @@ -433,21 +434,18 @@ void MasterNodesWidget::onDeleteMNClicked()
streamConfig.close();

if (lineNumToRemove != -1) {
fs::path pathConfigFile("masternode_temp.conf");
if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir() / pathConfigFile;
fs::path pathConfigFile = AbsPathForConfigVal(fs::path("masternode_temp.conf"));
FILE* configFile = fsbridge::fopen(pathConfigFile, "w");
fwrite(lineCopy.c_str(), std::strlen(lineCopy.c_str()), 1, configFile);
fclose(configFile);

fs::path pathOldConfFile("old_masternode.conf");
if (!pathOldConfFile.is_complete()) pathOldConfFile = GetDataDir() / pathOldConfFile;
fs::path pathOldConfFile = AbsPathForConfigVal(fs::path("old_masternode.conf"));
if (fs::exists(pathOldConfFile)) {
fs::remove(pathOldConfFile);
}
rename(pathMasternodeConfigFile, pathOldConfFile);

fs::path pathNewConfFile("masternode.conf");
if (!pathNewConfFile.is_complete()) pathNewConfFile = GetDataDir() / pathNewConfFile;
fs::path pathNewConfFile = AbsPathForConfigVal(fs::path("masternode.conf"));
rename(pathConfigFile, pathNewConfFile);

// Unlock collateral
Expand Down
12 changes: 5 additions & 7 deletions src/qt/pivx/masternodewizarddialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,8 @@ bool MasterNodeWizardDialog::createMN()
// Update the conf file
std::string strConfFile = "masternode.conf";
std::string strDataDir = GetDataDir().string();
if (strConfFile != fs::basename(strConfFile) + fs::extension(strConfFile)) {
fs::path conf_file_path(strConfFile);
if (strConfFile != conf_file_path.filename().string()) {
throw std::runtime_error(strprintf(_("masternode.conf %s resides outside data directory %s"), strConfFile, strDataDir));
}

Expand Down Expand Up @@ -342,22 +343,19 @@ bool MasterNodeWizardDialog::createMN()
ipAddress = "["+ipAddress+"]";
}

fs::path pathConfigFile("masternode_temp.conf");
if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir() / pathConfigFile;
fs::path pathConfigFile = AbsPathForConfigVal(fs::path("masternode_temp.conf"));
FILE* configFile = fopen(pathConfigFile.string().c_str(), "w");
lineCopy += alias+" "+ipAddress+":"+port+" "+mnKeyString+" "+txID+" "+indexOutStr+"\n";
fwrite(lineCopy.c_str(), std::strlen(lineCopy.c_str()), 1, configFile);
fclose(configFile);

fs::path pathOldConfFile("old_masternode.conf");
if (!pathOldConfFile.is_complete()) pathOldConfFile = GetDataDir() / pathOldConfFile;
fs::path pathOldConfFile = AbsPathForConfigVal(fs::path("old_masternode.conf"));
if (fs::exists(pathOldConfFile)) {
fs::remove(pathOldConfFile);
}
rename(pathMasternodeConfigFile, pathOldConfFile);

fs::path pathNewConfFile("masternode.conf");
if (!pathNewConfFile.is_complete()) pathNewConfFile = GetDataDir() / pathNewConfFile;
fs::path pathNewConfFile = AbsPathForConfigVal(fs::path("masternode.conf"));
rename(pathConfigFile, pathNewConfFile);

mnEntry = masternodeConfig.add(alias, ipAddress+":"+port, mnKeyString, txID, indexOutStr);
Expand Down
3 changes: 1 addition & 2 deletions src/rpc/protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ static const std::string COOKIEAUTH_FILE = ".cookie";
fs::path GetAuthCookieFile()
{
fs::path path(GetArg("-rpccookiefile", COOKIEAUTH_FILE));
if (!path.is_complete()) path = GetDataDir() / path;
return path;
return AbsPathForConfigVal(path);
}

bool GenerateAuthCookie(std::string *cookie_out)
Expand Down
16 changes: 0 additions & 16 deletions src/scheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,6 @@ CScheduler::~CScheduler()
assert(nThreadsServicingQueue == 0);
}


#if BOOST_VERSION < 105000
static boost::system_time toPosixTime(const boost::chrono::system_clock::time_point& t)
{
return boost::posix_time::from_time_t(boost::chrono::system_clock::to_time_t(t));
}
#endif

void CScheduler::serviceQueue()
{
boost::unique_lock<boost::mutex> lock(newTaskMutex);
Expand All @@ -52,20 +44,12 @@ void CScheduler::serviceQueue()
// Wait until either there is a new task, or until
// the time of the first item on the queue:

// wait_until needs boost 1.50 or later; older versions have timed_wait:
#if BOOST_VERSION < 105000
while (!shouldStop() && !taskQueue.empty() &&
newTaskScheduled.timed_wait(lock, toPosixTime(taskQueue.begin()->first))) {
// Keep waiting until timeout
}
#else
// Some boost versions have a conflicting overload of wait_until that returns void.
// Explicitly use a template here to avoid hitting that overload.
while (!shouldStop() && !taskQueue.empty() &&
newTaskScheduled.wait_until<>(lock, taskQueue.begin()->first) != boost::cv_status::timeout) {
// Keep waiting until timeout
}
#endif
// If there are multiple threads, the queue can empty while we're waiting (another
// thread may service the task we were waiting on).
if (shouldStop() || taskQueue.empty())
Expand Down
9 changes: 0 additions & 9 deletions src/test/scheduler_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
#include "scheduler.h"
#if defined(HAVE_CONFIG_H)
#include "config/pivx-config.h"
#else
#define HAVE_WORKING_BOOST_SLEEP_FOR
#endif

#include <boost/bind.hpp>
Expand All @@ -34,14 +32,7 @@ static void microTask(CScheduler& s, boost::mutex& mutex, int& counter, int delt

static void MicroSleep(uint64_t n)
{
#if defined(HAVE_WORKING_BOOST_SLEEP_FOR)
boost::this_thread::sleep_for(boost::chrono::microseconds(n));
#elif defined(HAVE_WORKING_BOOST_SLEEP)
boost::this_thread::sleep(boost::posix_time::microseconds(n));
#else
//should never get here
#error missing boost sleep implementation
#endif
}

BOOST_AUTO_TEST_CASE(manythreads)
Expand Down
6 changes: 1 addition & 5 deletions src/torcontrol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -770,14 +770,10 @@ void InterruptTorControl()

void StopTorControl()
{
// timed_join() avoids the wallet not closing during a repair-restart. For a 'normal' wallet exit
// try_join_for() avoids the wallet not closing during a repair-restart. For a 'normal' wallet exit
// it behaves for our cases exactly like the normal join()
if (gBase) {
#if BOOST_VERSION >= 105000
torControlThread.try_join_for(boost::chrono::seconds(1));
#else
torControlThread.timed_join(boost::posix_time::seconds(1));
#endif
event_base_free(gBase);
gBase = 0;
}
Expand Down
Loading

0 comments on commit 2e11030

Please sign in to comment.