1、将BitcoinCore核心代码移植到Windows系统。
2、将BitcoinCore代码与Chromium浏览器工程融合,实现gyp编译。
3、浏览器启动后自动加载BitcoinCore服务。
BitcoinCore工程依赖于:
1、leveldb——已存在于bitcoincore源码工程中。
2、secp256k1——已存在于bitcoincore源码工程中。
3、univalue——已存在于bitcoincore源码工程中。
4、libevent——从http://libevent.org/下载源码。
5、libboost——采用下载静态库方式,直接链接到工程。
从https://dl.bintray.com/boostorg/release/1.67.0/binaries/下载编译过的工程(头文件和静态库)。
6、openssl——由于openssl工程在Windows系统编译配置较麻烦,且Chromium工程预置了与其功能相近的boringssl(源码存在于Chromium工程的third_party/boringssl中)及crypto模块,故将BitcoinCore使用openssl的代码适配到crypto和boringssl模块。
一、配置Chromium源码工程
配置方法不在本文描述范围,请参考《Windows系统下Chromium/content shell工程的编译》。
二、下载BitcoinCore源码
下载地址https://github.com/bitcoin/bitcoin,可使用git或直接下载源码包方式下载。代码目录为:
其中,有效源码在src子目录下(如下图)。移植时,也是将src目录的源码文件放置至Chromium工程中编译。
三、依赖工程的编译及整合
1、libboost
本文采用下载prebuilt库方式(如果Windows系统编译libboost库则推荐采用交叉编译),下载地址为https://dl.bintray.com/boostorg/release/1.67.0/binaries/。本文使用libboost1.67.0版本,解压后的目录结构如下图所示。
其中,boost目录为头文件路径,lib32-msvc-12.0为对应Windows系统的libboost库(静态库和动态库均有)。
本文编译bitcoincore时采用静态链接,因此使用其中的*.lib。
将此两个目录拷贝到bitcoincore源码工程下(在bitcoincore源码目录下新建boost目录存放此两个目录内容),且为命名便利,将lib32-msvc-12.0改为libs。
2、libevent
从http://libevent.org/下载源码,本文下载的是2.0.22稳定版。通过命令行启动
最终生成三个静态库文件,参见下图。
3、bitcoincore
1)在Chromium工程中创建bitcoin目录(假设创建于chromium/src/content/shell路径下)。
2)将bitcoincore源码中src下源码文件拷贝到新创建的bitcoin目录下。
3)在bitcoincore路径下创建boost目录。将libboost源码中的boost目录中内容(头文件),以及lib32-msvc-12.0目录中的静态库文件拷贝到bitcoin/boost目录中,参见下图所示。其中,libs中的文件即为lib32-msvc-12.0中内容。
4)在bitcoincore路径下创建libevent目录。将libevent工程中文件和生成的静态库文件拷贝到此路径下,参见下图所示。其中,lib目录存在的即为2步骤中生成的*.lib文件。
5)最终生成的bitcoin源码工程结构如下图所示,在原bitcoincore基础上多出了boost和libevent目录。
本文未计划构建完整的bitcoincore(包括bitcoind、bitcoin-cli、bitcoin-tx、bitcoin-qt),只构建bitcoind服务,因此原bitcoincore源码中的wallet、qt、interface、bench、test、zmq子目录和bitcoin-tx、bitcoin-cli等文件不参与编译,未纳入到工程中。
由于本文中的Chromium工程构建系统为gyp,因此需要针对参与编译的bitcoin工程编写相应的gyp文件,命名为bitcoin.gyp。共计由7部分组成:
1、target_name
工程生成目标名称,本文指定target_name参数为bitcoin_lib,即'target_name': 'bitcoin_lib'。名称可自主定义。
2、type
构建类型,指定静态库,即'type': 'static_library'。本文计划将bitcoind服务生成为静态库,并最终链接到可执行文件中(本文移植验证目标为content shell可执行程序)。
3、dependencies
工程依赖,本bitcoin工程为定制工程,会使用原Chromium工程的子项目,如加密库、ssl和log系统。因此依赖如下三个子项目。
4、include_dirs
头文件目录清单。根据对内、对外的头文件依赖情况,头文件目录清单如下。
5、sources
参与编译源码文件清单。包括:
1)compat目录文件
'shell/bitcoin/compat/strnlen.cpp'
2)crypto目录文件
3)secp256k1目录文件
'shell/bitcoin/secp256k1/src/secp256k1.c'
4)support目录文件
5)primitives目录文件
6)consensus目录文件
7)univalue目录文件
8)policy目录文件
9)leveldb目录文件
10)script目录文件
11)rpc目录文件
12)bitcoin主目录下文件
除了bitcoin-clic.cpp、bitcoin-tx.cpp、span.h(vs对模板支持不完整,引入该文件会导致编译错误,后文会对调用Span模板代码进行改写)以外的其它cpp文件。
6、msvs_settings等
编译选项设置,需启动RTTI,否则会导致编译出错。并禁止一些warning,避免因warning的编译中断。
若编译过程中仍然报RTTI相关错误,可将chromium/src/build/common.gypi中的RuntimeTypeInfo置为true。
7、defines
编译过程中的宏定义。
由于本文计划将bitcoin服务加入到content shell项目中,因此bitcoin.gyp放置在chromium/src/content/路径下。
一、bitcoind服务入口定制
由于原bitcoind本身是可执行文件,当嵌入到Chromium系统中,需要对bitcoind.cpp文件进行修改。将main修改为bitcoindStart。
并新建名为bitcoind.h文件,定义bitcoindStart(),以便content shell合适位置调用此函数时包含此头文件。
二、content shell编译配置文件定制
将bitcoin子项目相关信息加入到content shell配置文件(chromium/src/content/content_shell.gypi)中,使得编译可生效。主要加入到如下单元中:
1、dependencies和include_dirs修改
增加对bitcoin项目目标和头文件路径依赖,如下图所示。
2、添加静态库依赖
主要增加bitcoin所依赖的boost、libevent静态库及路径,以保证链接时能正常通过。其中libboost和libevent路径加入到variables变量中。
除上述的编译配置外,若要bitcoin通过VS2012或其它VS编译环境成功,还需要对代码进行定制。
一、constexpr编译报错
VS不支持此关键字,因此部分引用此关键字的代码会编译失败。遇到此情况,可在编译报错源码前部增加如下代码。
二、__func__和_Exit编译报错
该关键字在VS编译环境中无法识别,可用__FUNCTION__代替。
_Exit可替换为_exit。
三、ssize_t编译报错
若遇到提示ssize_t无法识别,则增加如下声明。
四、宽字符报错
编译如env_win.cc源码时可能提示宽字符报错,可采用Chromium工程中的字符串转换函数进行宽字符抓换。首先在编译报错的源码中增加#include <base/strings/utf_string_conversions.h>,而后修改报错代码,参考如下:
五、std::numeric_limits<int64_t>::max()编译报错
若遇到关于max或min报错,则修改成VS可支持宏,如下。
六、“带有类内初始值设定项的静态数据成员必须具有不可变的常量整型”编译报错
诸如fees.h定义了常量静态变量的初始化。
将.h中的初始化去掉,如下:
增加到相应的.cpp文件中统一初始化。
七、std::atomic_*类型编译报错
VS2012不支持std::atomic_bool或std::atomic_int类型,修改为std::atomic<bool>即可。
八、span.h相关编译报错
span.h中的模板定义VS2012无法支持,因此需要改写,主要影响serialize.h。建议参照github的bitcoin早期版本修改。
九、缺省构造函数编译报错
net.h中的CSerializedNetMsg(CSerializedNetMsg&&) = default;无法被VS2012识别,可修改如下:
十、[noreturn]编译报错
VS2012无法识别noreturn关键字,诸如[[noreturn]] static void RandFailure()形式可修改为static void RandFailure(),确保编译通过。
【编译过程中的代码报错不止上述几类,需要根据具体情况进行相应修改。】
编译配置和代码修改定制完成后即可保证bitcoind编译链接通过,但启动bitcoind需要调用加入Chromium编译系统章节中的bitcoinStart()接口。
参考代码如下,取content shell的命令行,并将其构成启动bitcoind的参数,传入bitcoindStart()启动bitcoind服务。
可在命令行下启动content_shell.exe时将bitcoind支持的参数代入,即可在运行content shell的同时启动bitcoind。运行打印如下: