基于Chromium工程的BitcoinCore移植

移植目标

1、将BitcoinCore核心代码移植到Windows系统。

2、将BitcoinCore代码与Chromium浏览器工程融合,实现gyp编译。

3、浏览器启动后自动加载BitcoinCore服务。

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等文件不参与编译,未纳入到工程中。

编写编译脚本(gyp)

由于本文中的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

       编译过程中的宏定义。

加入Chromium编译系统

由于本文计划将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代码定制

除上述的编译配置外,若要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(),确保编译通过。

Content shell启动bitcoind服务

编译配置和代码修改定制完成后即可保证bitcoind编译链接通过,但启动bitcoind需要调用加入Chromium编译系统章节中的bitcoinStart()接口。

参考代码如下,取content shell的命令行,并将其构成启动bitcoind的参数,传入bitcoindStart()启动bitcoind服务。

可在命令行下启动content_shell.exe时将bitcoind支持的参数代入,即可在运行content shell的同时启动bitcoind。运行打印如下:

 

猜你喜欢

转载自blog.csdn.net/weixin_42080566/article/details/81103175