文档章节

TDM-GCC编译Boost库时的错误

P
 Polarix
发布于 2018/11/04 00:05
字数 2001
阅读 227
收藏 1

最近总是被一些莫名其妙的小问题困扰,深切的体会到了何为“阎王好斗,小鬼难缠”。
因为研究Codeblocks这个开源IDE,在编译源码时候,发现其中部分插件引用了Boost库,于是乎就想把Boost库编译一下。
我的编译器是TDM-GCC5.1.0,用了有一段时间了,早些时候为了跳出微软的圈儿决定学习和使用wxWidgets,就用了这个编译器。本来想着,下个代码编译一下,然后添加引用,多么简单的一个事儿!

然而我还是在阴沟里翻船了,就这么简单的一个事儿,遇上了麻烦。
下载Boost库、配置GCC环境这些基本操作就不表了,在编译bjam编译工具时候,遇上了麻烦。
按照GettingStart的说明,执行脚本bootstrap.bat gcc,然后坐等工具编译,然后,就弹出了以下两个错误:

E:\Workspace\Librarys\Boost\boost_1_68_0>bootstrap.bat gcc
Building Boost.Build engine
execnt.c: In function 'try_wait_callback':
execnt.c:856:5: warning: implicit declaration of function 'UnregisterWait' [-Wimplicit-function-declaration]
     UnregisterWait( slot->wait_handle );
     ^
execnt.c: In function 'register_wait':
execnt.c:876:9: warning: implicit declaration of function 'RegisterWaitForSingleObject' [-Wimplicit-function-declaration]
         RegisterWaitForSingleObject( &cmdtab[ job_id ].wait_handle,
         ^
C:\Users\Polarix\AppData\Local\Temp\ccI8RYOz.o:execnt.c:(.text+0x139a): undefined reference to `UnregisterWait'
C:\Users\Polarix\AppData\Local\Temp\ccI8RYOz.o:execnt.c:(.text+0x146b): undefined reference to `RegisterWaitForSingleObject'
collect2.exe: error: ld returned 1 exit status

Failed to build Boost.Build engine.
Please consult bootstrap.log for further diagnostics.

E:\Workspace\Librarys\Boost\boost_1_68_0>

错误很常见,分别是调用函数没有显式声明和函数未定义。上网查了一下,UnregisterWait和RegisterWaitForSingleObject函数均为WindowsAPI,所以这两个问题应该是头文件未包含和系统函数库未引用导致。
函数未显式声明可以暂时不理,这种警告一般不会影响程序的运行,至于函数未定义,加上对应的系统库引用不就好了!
至少我是这样想的。
于是我找到了编译脚本,位于\tools\build\src\engine下的build.bat文件,然后又顺藤摸瓜,找到了config_toolset.bat文件,最终找到了这样一段处理。

if NOT "_%BOOST_JAM_TOOLSET%_" == "_gcc_" goto Skip_GCC
set "BOOST_JAM_CC=gcc -DNT"
set "BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe"
set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
set "_known_=1"
:Skip_GCC

库的引用应该就加在这里了,于是上微软的网站,找到这两个函数,关键信息如下:

Header:winbase.h (include Windows.h)
Library:Kernel32.lib
DLL:Kernel32.dll

小事儿,将库引用加在BOOST_JAM_CC参数后面就行了,像这样:

set "BOOST_JAM_CC=gcc -DNT -lkernel32"

满心欢喜的进入控制台,再次编译……
问题依旧……
这下我就懵了,这个错误就这么回事儿,还能有别的问题报这个错误?
毫无头绪之际,本着之前编程时“无警告编译”的习惯,我决定先看看这两个警告,把他俩先干掉。于是我找到了报错的execnt.c文件,然后在确认了这个文件没有包含winbase.h后,我在头部加入了winbase.h的包含,再编译一下试试。
这时,诡异的现象发生了!控制台上居然又出现了这两句话:

E:\Workspace\Librarys\Boost\boost_1_68_0>bootstrap.bat gcc
Building Boost.Build engine
execnt.c: In function 'try_wait_callback':
execnt.c:856:5: warning: implicit declaration of function 'UnregisterWait' [-Wimplicit-function-declaration]
     UnregisterWait( slot->wait_handle );
     ^
execnt.c: In function 'register_wait':
execnt.c:876:9: warning: implicit declaration of function 'RegisterWaitForSingleObject' [-Wimplicit-function-declaration]
         RegisterWaitForSingleObject( &cmdtab[ job_id ].wait_handle,
         ^

这个不应该啊,头文件包含了,这又是C文件,应该不存在同名函数重载的现象。于是乎我打开了TDM-GCC的include文件夹,决定看一下这两个函数的声明,是这样的:

#if (_WIN32_WINNT >= 0x0500)
WINBASEAPI BOOL WINAPI UnregisterWait(HANDLE);
WINBASEAPI BOOL WINAPI UnregisterWaitEx(HANDLE,HANDLE);
#endif
#if (_WIN32_WINNT >= 0x0500)
WINBASEAPI BOOL WINAPI RegisterWaitForSingleObject(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
WINBASEAPI HANDLE WINAPI RegisterWaitForSingleObjectEx(HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
#endif

函数声明的类型和调用的地方一致,应该没问题,但是这个警告真的好诡异,于是乎,我突然发现了另一个东西,那就是这两个函数包着的纳个宏定义:

#if (_WIN32_WINNT >= 0x0500)

这个宏定义没有问题,因为在刚才查找资料时,微软的在线文档也明确表示:

Minimum supported client:Windows XP [desktop apps only]
Minimum supported server:Windows Server 2003 [desktop apps only]

但是如果这个宏定义不满足,那么这两个函数的声明就相当于没有,这个和编译产生的警告是符合的,那么系统函数的定义也可能未被包含!
想到这,我觉得我可能找到了问题的突破口,于是我用_WIN32_WINNT这个宏名在编译脚本及参数文件中搜索了一圈,发现只有在指定编译器为微软的VC系列时候,这个宏会被全局定义,在GCC和Mingw时,并没有这个定义。
问题似乎找到了,于是我将config_toolset.bat文件,中BOOST_JAM_CC参数的定义修改为:

set "BOOST_JAM_CC=gcc -DNT -D_WIN32_WINNT=0x0501"

再次编译。
之前的警告和错误都没有了,但是编译时显示:

Failed to build Boost.Build engine.
Please consult bootstrap.log for further diagnostics.

工具还是没有生成,没关系,进入\tools\build\src\engine目录,单独编译工具,这样可以看到更多回显信息。
执行build.bat gcc后,屏幕回显信息如下:

E:\Workspace\Librarys\Boost\boost_1_68_0\tools\build\src\engine>.\bootstrap\jam0 -f build.jam --toolset=gcc "--toolset-root= "
...found 161 targets...
...updating 2 targets...
[COMPILE] bin.ntx86\b2.exe
execnt.c: In function 'try_wait_callback':
execnt.c:856:5: warning: implicit declaration of function 'UnregisterWait' [-Wimplicit-function-declaration]
     UnregisterWait( slot->wait_handle );
     ^
execnt.c: In function 'register_wait':
execnt.c:876:9: warning: implicit declaration of function 'RegisterWaitForSingleObject' [-Wimplicit-function-declaration]
         RegisterWaitForSingleObject( &cmdtab[ job_id ].wait_handle,
         ^
C:\Users\Polarix\AppData\Local\Temp\ccx8A2Ia.o:execnt.c:(.text+0x2f0): undefined reference to `UnregisterWait'
C:\Users\Polarix\AppData\Local\Temp\ccx8A2Ia.o:execnt.c:(.text+0x1845): undefined reference to `RegisterWaitForSingleObject'
collect2.exe: error: ld returned 1 exit status

错误信息只截取了最重要的部分,不是全部,从这里可以看出,依然是之前的问题,只不过发生在另一次编译中,使用的是另一个文件build.jam。打开这个文件,可以找到以下内容。

toolset gcc gcc : "-o " : -D
    : -pedantic -fno-strict-aliasing
    [ opt --release : [ opt --symbols : -g : -s ] -O3 ]
    [ opt --debug : -g -O0 -fno-inline ]
    [ opt --profile : -O3 -g -pg ]
    -I$(--python-include) -I$(--extra-include) -Wno-long-long
    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;

同样的,宏定义加在第二行处,变为:

toolset gcc gcc : "-o " : -D
    : -pedantic -fno-strict-aliasing -D_WIN32_WINNT=0x0501
    [ opt --release : [ opt --symbols : -g : -s ] -O3 ]
    [ opt --debug : -g -O0 -fno-inline ]
    [ opt --profile : -O3 -g -pg ]
    -I$(--python-include) -I$(--extra-include) -Wno-long-long
    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;

保存,再次编译。

E:\Workspace\Librarys\Boost\boost_1_68_0\tools\build\src\engine>build.bat gcc
###
### Using 'gcc' toolset.
###

E:\Workspace\Librarys\Boost\boost_1_68_0\tools\build\src\engine>if exist bootstrap rd /S /Q bootstrap

E:\Workspace\Librarys\Boost\boost_1_68_0\tools\build\src\engine>md bootstrap

E:\Workspace\Librarys\Boost\boost_1_68_0\tools\build\src\engine>gcc -DNT -D_WIN32_WINNT=0x0501 -o bootstrap\jam0.exe  command.c compile.c constants.c debug.c execcmd.c execnt.c filent.c frames.c function.c glob.c hash.c hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c object.c option.c output.c parse.c pathnt.c pathsys.c regexp.c rules.c scan.c search.c subst.c timestamp.c variable.c modules.c strings.c filesys.c builtins.c md5.c class.c cwd.c w32_getreg.c native.c modules/set.c modules/path.c modules/regex.c modules/property-set.c modules/sequence.c modules/order.c

E:\Workspace\Librarys\Boost\boost_1_68_0\tools\build\src\engine>.\bootstrap\jam0 -f build.jam --toolset=gcc "--toolset-root= "  clean
...found 1 target...
...updating 1 target...
...updated 1 target...

E:\Workspace\Librarys\Boost\boost_1_68_0\tools\build\src\engine>.\bootstrap\jam0 -f build.jam --toolset=gcc "--toolset-root= "
...found 161 targets...
...updating 2 targets...
[COMPILE] bin.ntx86\b2.exe
[COPY] bin.ntx86\bjam.exe
...updated 2 targets...

E:\Workspace\Librarys\Boost\boost_1_68_0\tools\build\src\engine>exit /b 0

E:\Workspace\Librarys\Boost\boost_1_68_0\tools\build\src\engine>

0错误,0警告通过。
此时再回到Boost的根目录下,重新执行bootstrap.bat gcc,不再有错误和警告,命令执行完成后,Boost的根目录下多出b2.exe和bjam.exe两个文件,这就是Boost的编译工具。同时,控制台回显:

E:\Workspace\Librarys\Boost\boost_1_68_0>bootstrap.bat gcc
Building Boost.Build engine

Bootstrapping is done. To build, run:

    .\b2

To adjust configuration, edit 'project-config.jam'.
Further information:

    - Command line help:
    .\b2 --help

    - Getting started guide:
    http://boost.org/more/getting_started/windows.html

    - Boost.Build documentation:
    http://www.boost.org/build/doc/html/index.html

之后的操作步骤就和网上说的大相径庭,请大家自行搜索参照吧。

© 著作权归作者所有

P

Polarix

粉丝 3
博文 4
码字总数 7151
作品 2
大连
程序员
私信 提问
CentOS6.5 下编译Ceph源码

引言 ceph源码编译不是一件很容易的事情,中间报了很多错误,比如对C++11的依赖,对BOOST的依赖以及大量其他库的依赖,这些过程都要一一解决。本文对编译的过程进行了一个详细的说明,并对碰...

西昆仑
2015/12/03
1K
4
分布式日志系统Scribe编译安装

最近准备整合多个系统的日志,因而想到构建一套分布式日志存储系统,首先考虑的是Scribe,不过编译安装耗费了很多时间(Scribe相关文档确实少了点,相比Flume) 环境:Ubuntu13.04 32bit 组件...

IUnKnown
2013/07/03
772
2
Golang在windows下交叉编译linux程序

1、下载相关程序。   Golang下载:http://www.golangtc.com/download   Git下载:http://git-scm.com/download/   TDM-GCC下载:http://tdm-gcc.tdragon.net/download 2、Go编译环境配......

ethantonylam
2016/04/20
69
0
Unity的lua项目为Tolua# 编译protobuf

记录以备忘 因为有别的现有架构,所以只是换lua中间件,同时需要protobuf,所以使用pbc加入编译。tolua#在github上就有simpleframwork可用,个人项目可以使用。 下载tolua# 的runtime项目 ht...

陌路-野山君
2016/10/09
4.2K
5
Windows 下64位TDM-GCC-64 g++自定义库的生成及使用

一、自定义库的生成 生成szlib.o文件: 生成libszlib.a文件: 查看库文件中的函数: 解决方法: 环境:Windows 2016 cmd 参考: undefined reference to `std::ios_base::Init::Init() https:...

SamXIAO
02/09
21
2

没有更多内容

加载失败,请刷新页面

加载更多

聊聊nacos的LocalConfigInfoProcessor

序 本文主要研究一下nacos的LocalConfigInfoProcessor LocalConfigInfoProcessor nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/impl/LocalConfigInfoProcessor.java p......

go4it
昨天
1
0
前端技术之:webpack热模块替换(HMR)

第一步:安装HMR中间件: npm install --save-dev webpack-hot-middleware 第二步:webpack配置中引入webpack对象 const webpack = require('webpack’); 第三步:增加devServer配置项: ho......

popgis
昨天
2
0
死磕 java线程系列之线程池深入解析——体系结构

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本。 简介 Java的线程池是块硬骨头,对线程池的源码做深入研究不仅能提高对Java整个并发编程的理解,也能提高自己...

彤哥读源码
昨天
3
0
虚函数表 图解

虚函数表 图解 p504

天王盖地虎626
昨天
2
0
java反射

学习目标  什么是反射  反射运行原理  了解反射机制的相关类  获取 class 对象的 3 种方式  通过反射获取构造方法并使用  通过反射获取成员变量并调用  通过反射获取成员方法并...

流川偑
昨天
3
2

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部