diff --git a/Makefile.am b/Makefile.am index b51f477..58241df 100644 --- a/Makefile.am +++ b/Makefile.am @@ -35,6 +35,11 @@ COVERAGE_INFO = baseline_filtered_combined.info baseline.info block_test.info \ baseline_filtered.info block_test_filtered.info \ leveldb_baseline_filtered.info test_bitcoin_coverage.info test_bitcoin.info +if ENABLE_DAEMONLIB +all: + $(MAKE) -C src +endif + dist-hook: -$(MAKE) -C $(top_distdir)/src/leveldb clean -$(MAKE) -C $(top_distdir)/src/secp256k1 distclean diff --git a/configure.ac b/configure.ac index 9814197..3f25415 100644 --- a/configure.ac +++ b/configure.ac @@ -126,6 +126,12 @@ AC_ARG_ENABLE([reduce-exports], [use_reduce_exports=$enableval], [use_reduce_exports=auto]) +AC_ARG_ENABLE([daemonlib], + [AS_HELP_STRING([--enable-daemonlib], + [compile all of bitcoind as a library (default is no)])], + [use_daemonlib=$enableval], + [use_daemonlib=no]) + AC_ARG_ENABLE([ccache], [AS_HELP_STRING([--enable-ccache], [use ccache for building (default is yes if ccache is found)])], @@ -387,6 +393,9 @@ fi if test x$use_hardening != xno; then AX_CHECK_COMPILE_FLAG([-Wstack-protector],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -Wstack-protector"]) AX_CHECK_COMPILE_FLAG([-fstack-protector-all],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fstack-protector-all"]) + if test x$use_daemonlib = xno; then + AX_CHECK_COMPILE_FLAG([-fPIE],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fPIE"]) + fi AX_CHECK_PREPROC_FLAG([-D_FORTIFY_SOURCE=2],[ AX_CHECK_PREPROC_FLAG([-U_FORTIFY_SOURCE],[ @@ -400,7 +409,7 @@ if test x$use_hardening != xno; then AX_CHECK_LINK_FLAG([[-Wl,-z,relro]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,relro"]) AX_CHECK_LINK_FLAG([[-Wl,-z,now]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,now"]) - if test x$TARGET_OS != xwindows; then + if test x$TARGET_OS != xwindows -a x$use_daemonlib = xno; then # All windows code is PIC, forcing it on just adds useless compile warnings AX_CHECK_COMPILE_FLAG([-fPIE],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fPIE"]) AX_CHECK_LINK_FLAG([[-pie]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -pie"]) @@ -418,6 +427,17 @@ if test x$use_hardening != xno; then OBJCXXFLAGS="$CXXFLAGS" fi +AC_DEFINE([ENABLE_DAEMONLIB],[0],[Enable daemonlib.]) +AM_CONDITIONAL([ENABLE_DAEMONLIB],[false]) +if test x$use_daemonlib != xno; then + AX_CHECK_COMPILE_FLAG([-fPIC],[DAEMONLIB_CXXFLAGS="$DAEMONLIB_CXXFLAGS -fPIC"]) + AC_DEFINE([ENABLE_DAEMONLIB],[1],[Enable daemonlib.]) + AM_CONDITIONAL([ENABLE_DAEMONLIB],[true]) + CXXFLAGS="$CXXFLAGS $DAEMONLIB_CXXFLAGS" + CPPFLAGS="$CPPFLAGS $DAEMONLIB_CPPFLAGS" + OBJCXXFLAGS="$CXXFLAGS" +fi + dnl this flag screws up non-darwin gcc even when the check fails. special-case it. if test x$TARGET_OS = xdarwin; then AX_CHECK_LINK_FLAG([[-Wl,-dead_strip]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip"]) @@ -463,7 +483,7 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([ ] ) -if test x$use_reduce_exports != xno; then +if test x$use_reduce_exports != xno -a x$use_daemonlib = xno; then AX_CHECK_COMPILE_FLAG([-fvisibility=hidden],[RE_CXXFLAGS="-fvisibility=hidden"], [ if test x$use_reduce_exports = xyes; then @@ -811,6 +831,13 @@ if test x$build_bitcoin_utils$build_bitcoin_libs$build_bitcoind$bitcoin_enable_q AC_MSG_ERROR([No targets! Please specify at least one of: --with-utils --with-libs --with-daemon --with-gui or --enable-tests]) fi +AC_MSG_CHECKING([whether to compile as daemonlib]) +if test x$use_daemonlib != xno; then + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin]) AM_CONDITIONAL([BUILD_DARWIN], [test x$BUILD_OS = xdarwin]) AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows]) diff --git a/doc/build-unix.md b/doc/build-unix.md index 8ddee3b..c4274a3 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -239,3 +239,42 @@ In this case there is no dependency on Berkeley DB 4.8. Mining is also possible in disable-wallet mode, but only using the `getblocktemplate` RPC call not `getwork`. +Compiling bitcoind as a shared object (`libbitcoind.so`) +-------------------------------------------------------- + +### Compiling as a library + +``` bash +# ensure clean up +$ make clean + +# create configure file +$ ./autogen.sh + +# configure as a library with -fPIC on all object files +# use --with-incompatible-bdb if necessary +# use --prefix=/usr if necessary +$ ./configure --enable-daemonlib + +# build libbitcoind.so +$ time make +... +real 31m33.128s +user 16m23.930s +sys 2m52.310s +``` + +`--enable-daemonlib` will compile all object files with `-fPIC` (Position +Independent Code - needed to create a shared object). + +`make` will then compile `./src/libbitcoind.so` (with `-shared -fPIC`), linking +to all the freshly compiled PIC object files. This will completely ignore +compiling tests and the QT object files. + +Without `--enable-daemonlib`, the Makefile with compile bitcoind with -fPIE +(Position Independent for Executable), this allows compiling of bitcoind. + +#### Todo + +- Find a way to compile bitcoind and libbitcoind.so at the same time without + recompiling object files each time? Possibly use libtool's .lo/.la. diff --git a/src/Makefile.am b/src/Makefile.am index d6ac6e1..4ac63a2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,12 +31,15 @@ LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a LIBBITCOIN_UNIVALUE=univalue/libbitcoin_univalue.a LIBBITCOINQT=qt/libbitcoinqt.a LIBSECP256K1=secp256k1/libsecp256k1.la +LIBBITCOIND=libbitcoind.so $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: + +if !ENABLE_DAEMONLIB noinst_LIBRARIES = \ crypto/libbitcoin_crypto.a \ libbitcoin_util.a \ @@ -76,6 +79,7 @@ BITCOIN_CORE_H = \ amount.h \ base58.h \ bloom.h \ + bitcoind.h \ chain.h \ chainparams.h \ chainparamsbase.h \ @@ -152,10 +156,17 @@ JSON_H = \ json/json_spirit_writer.h \ json/json_spirit_writer_template.h +else +.PHONY: FORCE +BITCOIN_INCLUDES += $(BDB_CPPFLAGS) +endif + obj/build.h: FORCE @$(MKDIR_P) $(builddir)/obj @$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \ $(abs_top_srcdir) + +if !ENABLE_DAEMONLIB libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h # server: shared between bitcoind and bitcoin-qt @@ -165,6 +176,7 @@ libbitcoin_server_a_SOURCES = \ alert.cpp \ bloom.cpp \ chain.cpp \ + bitcoind.cpp \ checkpoints.cpp \ init.cpp \ leveldbwrapper.cpp \ @@ -304,7 +316,7 @@ bitcoind_LDADD = \ if ENABLE_WALLET bitcoind_LDADD += libbitcoin_wallet.a endif -bitcoind_SOURCES = bitcoind.cpp +bitcoind_SOURCES = bitcoin-main.cpp # if TARGET_WINDOWS @@ -380,6 +392,7 @@ if USE_LIBSECP256K1 libbitcoinconsensus_la_LIBADD += secp256k1/libsecp256k1.la endif endif +endif CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno @@ -405,6 +418,9 @@ clean-local: @test -f $(PROTOC) $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $( -#include -#include +#include "bitcoind.h" /* Introduction text for doxygen: */ @@ -174,13 +164,3 @@ bool AppInit(int argc, char* argv[]) return fRet; } - -int main(int argc, char* argv[]) -{ - SetupEnvironment(); - - // Connect bitcoind signal handlers - noui_connect(); - - return (AppInit(argc, argv) ? 0 : 1); -} diff --git a/src/bitcoind.h b/src/bitcoind.h new file mode 100644 index 0000000..0e34008 --- /dev/null +++ b/src/bitcoind.h @@ -0,0 +1,25 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2013 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef _BITCOIN_BITCOIND +#define _BITCOIN_BITCOIND 1 + +#include "clientversion.h" +#include "rpcserver.h" +#include "init.h" +#include "main.h" +#include "noui.h" +#include "ui_interface.h" +#include "util.h" +#include "rpcclient.h" + +#include +#include +#include + +extern void DetectShutdownThread(boost::thread_group* threadGroup); +extern bool AppInit(int argc, char* argv[]); + +#endif diff --git a/src/init.h b/src/init.h index f2f7ac6..10abc3a 100644 --- a/src/init.h +++ b/src/init.h @@ -15,7 +15,15 @@ namespace boost class thread_group; } // namespace boost +#ifdef ENABLE_WALLET +extern std::string strWalletFile; extern CWallet* pwalletMain; +#endif + +#include +#include + +void ThreadImport(std::vector vImportFiles); void StartShutdown(); bool ShutdownRequested(); diff --git a/src/leveldbwrapper.h b/src/leveldbwrapper.h index 4247920..08c8164 100644 --- a/src/leveldbwrapper.h +++ b/src/leveldbwrapper.h @@ -29,10 +29,9 @@ class CLevelDBBatch { friend class CLevelDBWrapper; -private: +public: leveldb::WriteBatch batch; -public: template void Write(const K& key, const V& value) { @@ -63,7 +62,7 @@ public: class CLevelDBWrapper { -private: +public: //! custom environment this database is using (may be NULL in case of default environment) leveldb::Env* penv; @@ -85,7 +84,6 @@ private: //! the database itself leveldb::DB* pdb; -public: CLevelDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false); ~CLevelDBWrapper(); diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index 8b95373..53f9a5a 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -26,11 +26,11 @@ using namespace std; void EnsureWalletIsUnlocked(); -std::string static EncodeDumpTime(int64_t nTime) { +std::string EncodeDumpTime(int64_t nTime) { return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime); } -int64_t static DecodeDumpTime(const std::string &str) { +int64_t DecodeDumpTime(const std::string &str) { static const boost::posix_time::ptime epoch = boost::posix_time::from_time_t(0); static const std::locale loc(std::locale::classic(), new boost::posix_time::time_input_facet("%Y-%m-%dT%H:%M:%SZ")); @@ -43,7 +43,7 @@ int64_t static DecodeDumpTime(const std::string &str) { return (ptime - epoch).total_seconds(); } -std::string static EncodeDumpString(const std::string &str) { +std::string EncodeDumpString(const std::string &str) { std::stringstream ret; BOOST_FOREACH(unsigned char c, str) { if (c <= 32 || c >= 128 || c == '%') { diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index d2d14ad..e8abb3d 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -4,6 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "amount.h" +#include "rpcwallet.h" #include "base58.h" #include "core_io.h" #include "rpcserver.h" diff --git a/src/rpcwallet.h b/src/rpcwallet.h new file mode 100644 index 0000000..2b53241 --- /dev/null +++ b/src/rpcwallet.h @@ -0,0 +1,17 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2013 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef _BITCOINRPC_WALLET_H_ +#define _BITCOINRPC_WALLET_H_ 1 + +#include "wallet.h" +#include "walletdb.h" + +#include + +CAmount GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, int nMinDepth, const isminefilter& filter); +CAmount GetAccountBalance(const std::string& strAccount, int nMinDepth, const isminefilter& filter); + +#endif diff --git a/src/wallet.h b/src/wallet.h index 70d274c..604e9e7 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -105,8 +105,6 @@ public: class CWallet : public CCryptoKeyStore, public CValidationInterface { private: - bool SelectCoins(const CAmount& nTargetValue, std::set >& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL) const; - CWalletDB *pwalletdbEncryption; //! the current wallet version: clients below this version are not able to load the wallet @@ -201,6 +199,7 @@ public: bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; } void AvailableCoins(std::vector& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL) const; + bool SelectCoins(const CAmount& nTargetValue, std::set >& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL) const; bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector vCoins, std::set >& setCoinsRet, CAmount& nValueRet) const; bool IsSpent(const uint256& hash, unsigned int n) const;