• win10+vs2008编译比特币1.0版源码总结


    https://zhuanlan.zhihu.com/p/25074960

    https://zhuanlan.zhihu.com/p/25095222

    总体上是参考这两个链接,感谢大神的分享,但是中间遇到很多问题,也学到很多,现总结如下:

    以下是基于win10 64 位& Visual Studio 2008平台(不是标配,我电脑就是win10,vs2008也是之前项目用到装的)

    一、源码

    这里用的是bitcoin-0.1.0版本

    二、配置依赖库

    a)         wxWidgets (3.0.3版本)

    http://blog.csdn.net/sxhelijian/article/details/26163791安装参考链接

    没有为什么,上面大神用的3.1.0版本,我只是之前学习的时候安装过这个版本的。

    安装方法:到http://www.wxwidgets.org/downloads/下载Windows ZIP版本,解压,

    接下来对wxwidgets文件进行编译,这里用到了mingw32-make命令,由于我之前安装过codeblocks-13.12mingw-setup的缘故,这一步我直接可以进行,总结就不写,codeblocks安装还是比较简单的。不过这里有一些环境变量配置的问题。环境变量设置就不说了,C:Program Files (x86)CodeBlocksMinGWin

    命令行进入wxwidgets的解压目录,输入以下命令:

    mingw32-make -f makefile.gcc MONOLITHIC=1 SHARED=1 UNICODE=1 BUILD=debug

    这可能需要很久

    b)         openssl (1.0.2版本)

    上面大神说的1.0.2后会出问题我没有试,还不清楚,现在的目的是编译通过。

    安装方法就是上面提到的取巧的方法

    c)         Berkeley DB (4.8.30 版本)

    这里我下载是Windows安装版,所以没有编译源码的过程,还是很简单的。下载地址:http://www.oracle.com/technetwork/cn/products/berkeleydb/downloads/index-086374-zhs.html

    d)         Boost (1.63.0 版本)

    下载及介绍:

    http://www.boost.org/doc/libs/1_63_0/more/getting_started/windows.html#header-only-libraries

    三、使用vs的从“源码导入”导入bitcoin源码

    这里我们把src/ 目录当作根目录。

    新建立一个目录,比如叫做bitcoin什么的随便好啦。然后把src/目录下的所有文件都拷贝到这个新的目录下。我们现在把这个新的目录当做 / 。之后的描述都针对 / 作为根目录进行。

    打开vs

    点击新建

    从现有代码创建项目

    弹出对话框,选择默认的Visual C++ ,点击下一步

    项目位置填写上刚才的 / 目录的位置,项目名称取名 bitcoin-v0.1或者其他你喜欢的项目名字,点击下一步

    使用visual studio ->项目类型选择“Windows 应用程序项目” (就是说直接使用默认),其他的不动,点击下一步

    点击完成

    此时就已经新创建了项目,并导入的源码。

    四、配置

    这步是很关键的第一步

    现在我们先假设把刚才配置好的4个依赖库都设置成环境变量(如果不设置环境变量也行,那么等会在配置项目的依赖的时候就填写路径就好了。)

    回到桌面->对“此电脑”右键->属性->高级系统设置->环境变量->在系统变量的部分开始创建环境变量

    点击新建:

    举例:wsWidgets =>那么就在变量名写上WXWidgetsPath,然后变量值填写刚才安装(解压)widgets的根目录

    其他3个依赖库同理,则总共配置了4个环境变量:

    WXWidgetsPath

    OpenSSLPath

    BDBPath

    BoostPath

    当然上面这4个环境变量的名字是我乱取的,并没有什么约定,你可以根据自己想象取想取的名字。这里取这4个变量等会我们就会在项目的配置中引用这4个变量,自己取的名字等会就换成自己取的就好了。

    此时先关闭刚才创建的项目,然后再重新启动(这个是为了让vs加载刚才取的环境变量,如果没配置环境变量用不着重启vs)

    在解决方案中右键刚才创建的项目,选择属性。

    a)         设置unicode字符集

    注意,这步的配置不是必须,如果你的wxWidgets是老版本(似乎是小于2.8?)或者你在编译wxWidgets库的时候选择关闭unicode开关,编译除了非unicode的wxWidgets的库时,可以直接跳过这步,不设置unicode字符集。否则在等会启动编译的时候会出现wxWidgets的setup.h找不到路径。

    如果你是vs编译的,那么一定要设置unicode字符集。

    在配置属性-常规中找到项目默认值 - 字符集

    点击下拉框,选择使用 Unicode 字符集

    b)         设置VC++依赖项

    在配置属性-VC++目录下找到包含目录和库目录,点击包含目录,填写

     $(WXWidgetsPath)include

     $(WXWidgetsPath)includemsvc

    (注意这里的WXWidgetsPath就是刚才配置的环境变量,如果没有配置,就直接填写wxWidgets的路径加上include路径,以下同理)

    这样就引入了wxWidgets库的头文件路径以及 lib 路径。

    注:因为wxWidgets库是和windows应用程序绑定的,不是普通的c++依赖库,所以必须在VC++的部分设置,否则,wxWidgets会不能通过编译。

    c)         设置C++依赖

    在配置属性 - c/c++ - 常规中找到“附加包含目录”,点击编辑,填写:

     $(BoostPath)

     $(OpenSSLPath)include

     $(BDBPath)include

    这样就引入了 boost,openssl, bdb的头文件路径

    在配置属性 - 链接器 -常规中找到“附加库目录”,点击编辑,填写:

     $(OpenSSLPath)lib

     $(BDBPath)lib  // 注意这条可能根据你的环境改变

    (加粗|醒目) oracle神坑的地方在这里就体现出来了。$(BDBPath)lib指代的bdb的 libs 的路径,但是!因为我们编译的是 debug 项目,所以等会只能引入 debug 的dll(lib) (如果正常应该是可以引入release的lib的,但是对于bdb来说,debug项目使用release的dll在运行free()的时候会崩溃/(ㄒoㄒ)/~~)。

    但是引入debug后,源安装包中的 debug的dll似乎是有问题的(加粗),会直接引起程序崩溃!!(不清楚我是不是个例。如果出现了这个问题,请重新在自己的电脑上编译debug版本的bdb,把$(BDBPath)lib换成新的路径,参考下一篇文章)

    在配置属性 - 链接器 -输入中找到“附加依赖项”,点击编辑,填写:

     libeay32.lib

     libdb48d.lib  // 注意这个是带 'd' 的,也就是 debug 的dll库

    然后打开资源管理器(就是点我的电脑。。),找到这个项目的目录,在本项目根目录 / 下创建 libs/ 目录,拷贝

    $(OpenSSLPath) 目录下的 libeay32.dll

    $(BDBPath)indebug 目录下的libdb48d.dll

    进入 libs 目录。

    注意,刚才描述的问题的dll就是这个 libdb48d.dll,如果出问题了,很可能需要替换成自己编译的dll

    然后回到 VS 的项目配置中

    在配置属性 - 生成事件 - 后期生成事件中找到“命令行”

    填写上:

    xcopy /y /d  "$(ProjectDir)libs*.dll" "$(OutDir)"

    这个command的 libs 就是刚才在项目的根目录下创建的 libs/ 目录。所以这句话的意思就是把 libs/ 目录下的dll都拷贝到输出目录中(这里指代的就是 Debug 目录)

    五、修改源码

    错误

    1. headers.h

    vc6++ 与 vc9以上平台冲突

    因为源码应该是在vc6++的平台下编译完成的,所以首先要先移除对于winnt的预定义,否则会产生兼容性问题。

    找到headers.h文件,在第10行发现:

     #ifdef _WIN32_WINNT

     #undef _WIN32_WINNT

     #endif

     #define _WIN32_WINNT 0x0400 // 删除这4行

    将这4行都注释掉,或者删除。

    windows.h与 winsokc2.h 顺序

    找到headers.h文件第23行发现:

     #include <windows.h>

     #include <winsock2.h>

     #include <mswsock.h> // 把windows.h移动到最下面

    移动windows.h得到

    #include <winsock2.h>

    #include <mswsock.h>

    #include <windows.h>

    或者引入一个宏也可以解决windows.h头文件引入的问题:

     #define _WINSOCKAPI_    // stops windows.h including winsock.h

     #include <windows.h>

     // ...

     #include "MyClass.h"    // Which includes <winsock2.h>

    之后找到 net.cpp 文件,第5行交换头文件引入

     #include "headers.h"

     #include <winsock2.h> // 和上面一样互换这两行

     // =>

     #include <winsock2.h>

     #include "headers.h"

    2. c++11 与现存代码冲突

    net.h/net.c boost::array 与c++11 的std::array 冲突

    找到net.h文件,在第419行发现

     extern array<bool, 10>vfThreadRunning; // 添加命名空间

    //  修改为 =>

     extern boost::array<bool, 10>vfThreadRunning; // 添加命名空间

    找到net.c文件,第26行进行同样更改

    array<bool, 10>vfThreadRunning;

    //  修改为 =>

     boost::array<bool, 10>vfThreadRunning;

    winsock.h的 bind 函数与std::bind 冲突

    找到net.c文件,第937行

    if (bind(hListenSocket, (structsockaddr*)&sockaddr, sizeof(sockaddr))

     == SOCKET_ERROR) // bind函数冲突

    // 转变为=>

    if (::bind(hListenSocket, (structsockaddr*)&sockaddr,

    sizeof(sockaddr)) == SOCKET_ERROR) // 添加上::global 命名空间

    3. serialize.h insert函数const char*想要强制转换为const_iterator

    找到serialize.h文件,在第 808 行发现一个根据宏的定义

     #if !defined(_MSC_VER) || _MSC_VER >= 1300

    void insert(iterator it, const char* first, const char* last)

        {

    insert(it, (const_iterator)first, (const_iterator)last);

        }

    #endif

    修改为

     #if !defined(_MSC_VER) || _MSC_VER >= 1300

    void insert(iterator it, const char* first, const char* last)

        {

    vector_type v(first, last);

    insert(it, v.begin(), v.end());

        }

    #endif

    4. 似乎是关于MSVC8 allocator的兼容问题(不确定)

    文件serialize.h第699行

    typedef vector<char,constsecure_allocator<char>>vector_type;

    // 修改为=>也就是把作者原来写的这个secure_allocator移除,使用vector自带的。

    typedef vector<char>vector_type;

    同时因为vector_type的typedef已经等同于vector<char>,所以对于CDataStream类的构造函数也要更改

    文件serialize.h第741行, 删除或着注释掉这个构造函数

     //CDataStream(const vector<char>&vchIn, intnTypeIn=0, int

    VersionIn=VERSION) :vch(vchIn.begin(), vchIn.end())

    //{

    //    Init(nTypeIn, nVersionIn);

    //}

    文件key.h第40行

    typedef vector<unsigned char, constsecure_allocator<unsigned char>>

    CPrivKey;

    // =>修改方式同上

    typedef vector<unsigned char>CPrivKey;

    5. unicode字符的替换

    ps: 若使用低版本的wxwidgets,总之就是没开启unicode宏的话不需要替换

    util.cpp文件的第74行

    long ret = RegQueryValueEx(HKEY_PERFORMANCE_DATA, "Global", NULL,

    NULL, pdata, &nSize);

    // 把“Global”字符串该为 win32 支持的unicode =>

    long ret = RegQueryValueEx(HKEY_PERFORMANCE_DATA, L"Global", NULL,

    NULL, pdata, &nSize);

    // 或者换成另一个版本的win API也行

    long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL,

    ULL, pdata, &nSize);

    第173行

    GetModuleFileName(NULL, pszModule, sizeof(pszModule));

    //在unicode宏定义下的GetModuleFileName是宽字符版本,直接替换成Acsii版本=>

    GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));

    第272行

    returnGetFileAttributes(psz) != -1;

    // 与上面同理 =>

    returnGetFileAttributesA(psz) != -1;

    util.h文件的第274行

    OutputDebugString(p1);

    // 与上同理  =>

    OutputDebugStringA(p1);

    6. ui.cpp / ui.h错误

    ui.cpp 第254行,关于wsString的迭代器填充构造函数无法自动转化的问题 (或许当wxWidgets版本低的时候不会出现这个问题)

    returnCDataStream(strData.begin(), strData.begin() + event.GetInt(), SER_NETWORK);

    // 替换成为 =>

    const char* s = strData.mb_str();

    returnCDataStream(s, s + event.GetInt(), SER_NETWORK);

    类似的第2650,wsString到std::string的转换

     wtx.vOrderForm.push_back(make_pair(m_staticTextLabel[i]->GetLabel(),

    strValue));

    // 把wsString调用ToStdString()  =>

    wtx.vOrderForm.push_back(make_pair(m_staticTextLabel[i]-

    >GetLabel().ToStdString(), strValue));

    ui.cpp 第1245行,字符缺少引号

    ps: 强调!这里缺少引号,是因为本来源码中这里是个十分奇怪的字符,在导入vs后打开的时候就被转义了。所以这里的?实际上是代表原来的一个字符。但是这个函数并没什么鸟用,所以这里随便改正就好,不用还原原来的意思。

    if (str.Find('?) != wxNOT_FOUND)

    str.Remove(str.Find('?), 1);

    //  添加上缺失的引号

    if (str.Find('?') != wxNOT_FOUND)

    str.Remove(str.Find('?'), 1);

    2890行,宽字符

     _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL,

    OPEN_EXISTING, 0, 0));

    // =>

    _CrtSetReportFile(_CRT_WARN, CreateFile(L"NUL", GENERIC_WRITE, 0, NULL,

    OPEN_EXISTING, 0, 0));

    2913行,同上

     HWND hwndPrev = FindWindow("wxWindowClassNR", "Bitcoin");

    // =>

    HWND hwndPrev = FindWindow(L"wxWindowClassNR", L"Bitcoin");

    3148行,对于3.0以上的wxWidgets版本来说AddPendingEvent()函数已废弃,需要依靠eventhandler才能调用。

     //pframeMain->AddPendingEvent(event);

    pframeMain->GetEventHandler()->AddPendingEvent(event);

    7. 去除因跨平台带来的兼容问题

    文件util.h第161行

    inline string i64tostr(int64 n)

    {

    returnstrprintf("%"PRId64, n); 

    // 其中的PRId64 是为了跨平台带来的,修改为下面的代码

      // =>因为这里不关心跨平台问题,只把环境限制在win64上,所以不必担心int64的问题

    returnstrprintf("%l", n);

    }

    8. berkeleydb版本为6.2+后的修改兼容 (使用4.7或4.8版本则无需考虑)

    文件db.cpp 第18行

    DbEnvdbenv(0);

    // =>

    DbEnvdbenv((u_int32_t)0);

    警告

    源码中出现的警告多半是因为符号隐式转换的问题,这个根据自己需要修改就行。

    六、解决wx依赖库的问题

    http://www.cnblogs.com/waynecheng/archive/2012/04/18/2455765.html

    按上述方法修改源码后运行会出现找不到“wx/msw/wx.rc”,这需要引入资源文件,设置资源目录,项目->属性->资源->常规->附加包含目录:E:wxWidgets-3.0.3include

    接下来会出现一大堆error LNK2019: 无法解析的外部符号,这种错误,这是需要重新编译wx,步骤如下:

    进入E:wxWidgets-3.0.3uildmsw目录,Visual Studio 2008打开wx_vc9.sln,生成解决方案,之后会看到在lib下生成vc_lib文件夹,其中包括生成的相应的.lib等文件和mswud文件夹。到此,wxWidgets编译完毕。

     项目设定

    右键单击项目->属性->C/C++->常规

    【附加包含目录】 = "$(wxWin)libvc_libmswud"

    项目属性->连接器->常规

    【附加库目录】= "$(wxWin)libvc_lib"

    项目属性->连接器->输入

    【附加依赖项】=

    wxmsw29ud_core.lib

    wxbase29ud.lib

    wxtiffd.lib

    wxjpegd.lib

    wxpngd.lib

    wxzlibd.lib

    wxregexud.lib

    wxexpatd.lib

    winmm.lib

    comctl32.lib

    rpcrt4.lib

    wsock32.lib

    odbc32.lib

    再次编译运行就可以了

    七、运行

    以上的部分只是解决在编译期出现的问题,大头是需要让bitcoin能够运行起来(惨····)

    接下来将详细描述如何修改代码让bitcoin运行起来。

    好累。。

    这里我只说我遇到的问题,

    原因就不说了,我也没看懂,直接来解决办法,

    因为安装包中的release和debug都无法运行,所以只能自己编译出Berkeley DB的lib和dll

    假设现在的berkeleydb的根目录是 <bdbroot>

    那么在 <bdbroot>db-4.8.30uild_windows目录下可以找到 Berkeley_DB.sln

    打开它向上兼容后,进行项目构建,然后将一个example项目设为主项目进行运行。如果能运行成功就是构建成功并且能够正常运行。

    此时在 <bdbroot>db-4.8.30uild_windowsWin32Debug 目录下可以发现 libdb48d.lib 和 libdb48d.dll 这两个文件。而这两个文件就是在自己平台上编译出来的动态链接库。

    之后把bitcoin源码的关于Berkeley DB 的依赖库修改为新的路径,然后就可以正常运行了。。。

    这里修改的路径就是 $(BDBPath)db-4.8.30uild_windowsWin32Debug (参照上一篇)

    然后把 libdb48d.dll 拷贝到 bitcoin项目的 libs 目录下。

    到此为止,应该就可以编译并运行出来了。

    没写过博客,写的不好,纯粹个人学习总结,分享出来,需要可以参考,感兴趣的可以一起交流。

    https://my.oschina.net/u/3364259/blog/1503532

  • 相关阅读:
    gulp4.0 存在的错误信息 The following tasks did not complete: default,Did you forget to signal async completion?
    高性能前端 art-template 模板
    cookie 详解
    Cross origin requests are only supported for protocol schemes: http, data, chrome,chrome-extension的问题
    jQuery EasyUI 详解
    我的游戏学习日志1——恐龙快打
    我的游戏学习日志2——雪人兄弟
    关于网页导航栏制作的几种方法与常见问题解决(新人向)
    JavaScript基础
    利用CSS3制作网页动画
  • 原文地址:https://www.cnblogs.com/findumars/p/4969830.html
Copyright © 2020-2023  润新知