`
huozheleisi
  • 浏览: 1233386 次
文章分类
社区版块
存档分类
最新评论

Boost编译方法

 
阅读更多

方法一:

经历了将近半年多的时间boost终于发布了1.35.0版本(前版本1.34.1发布于2007/7),其编译方法和原来的编译方法基本上是一致的,主要改变包括1.34.0以来bjam的toolset所提供的参数名称的改变(具体参见《boost1.34.0编译日志》)外,还包括bjam的编译默认选项的变化,在1.35.0之前的版本默认编译时会自动编译各种版本的库,包括静态库、动态库、debug库和release库等全部的版本,但是到了1.35.0时默认的选择仅仅编译release版本的库,这样一来在开发的时候就不能进行必要的调试了,为了能够使其编译全部的版本
需要在bjam的命令行参数中添加一个--build-type=complete类型的参数来指明需要编译全部的版本,所需要编译同时为了使得regex库能够通过ICU库支持Unicode,在编译上需要有一些特殊的选择。我在Visual Studio 2005 Pro + SP1环境下编译了该库,为了避免走弯路所以将其编译的方法进行说明,以方便大家编译。
由于boost是采用其自己的bjam工具通过命令行进行编译的,所以必须在Windows下开启console窗口,同时必须将Visual Studio中C++目录下的环境vcvarsall.bat配置脚本运行一遍,以设置好VC的编译器环境变量。
1. 编译不带ICU支持的boost库
此种情况下的boost库编译起来比较的简单,在准备好的console窗口中输入:
bjam --without-python --toolset=msvc-8.0 --build-type=complete stage
就可以了,如果要安装的话则输入:
bjam --without-python --toolset=msvc-8.0 --build-type=complete install

2. 编译具有ICU支持的boost库
首先我们必须编译ICU库才能够编译boost库,在准备好的console窗口中输入:
bjam -sICU_PATH=d:/ICU --without-python --toolset=msvc-8.0 --build-type=complete stage
就可以了,如果要安装的话则输入:
bjam -sICU_PATH=d:/ICU --without-python --toolset=msvc-8.0 --build-type=complete install
通过上面的方法可以很正常完成boost各种需要版本的关系。每次用bjam编译boost总是要查看帮助文件才行。
虽然现在的bjam编译命令只有两三个参数,可是不小心还是会错。

1. toolset参数中,试图用vc,正确的应该是msvc。
vc用于库文件的命名后缀中。两个名字能统一就好了。

2. 编译工具的版本号应该用点号分隔,并且总是应该指定该版本号。
如msvc-71是错误的,应该用msvc-7.1。
小版本号不能省,如msvc-6.0不能写成msvc-6。
版本号指定错误,可能也能编译,但是生成库的名字是错的。

3. 使用stlport。
要在user-config.jam中配置stlport,
例如:using stlport : : F:/STLport-5.1.0/stlport F:/STLport-5.1.0/lib ;
并且别忘了在参数中加上参数:--stdlib=stlport。
user-config.jam中的stlport配置可以一直保持开启,
因为最终是由stdlib参数决定是否使用stlport。

方法二:

1.点击 开始->程序->Microsoft Visual Studio 2005->Visual Studio Tools->Visual Studio 2005 命令提示
2.cd D:/Libs/boost_1_35_0/tools/jam/src
3.build.bat
此时在src/bin.ntx86/目录下产生了bjam.exe
4.将bjam.exe拷贝到boost的根目录D:/Libs/boost_1_35_0
5.cd D:/Libs/boost_1_35_0
6.bjam.exe --build-dir=build --toolset=msvc stage

编译完成后,产生了2个目录build和stage,但同时也发现一个奇怪问题:stage里面的文件,竟然有很多相同的lib,比如boost_date_time-vc80-mt-1_35.lib和boost_date_time-vc80-mt.lib,boost_filesystem-vc80-mt-1_35.lib和boost_filesystem-vc80-mt.lib他们文件的大小一样,只是文件名稍微不同,一个带有版本号,另一个没有。编译的问题,还是boost本身有

方法三:

 一、下载安装:

  下载boost 1.31,解压缩至一个文件夹,本文以[boost-path]来引用这个路径。

  二、编译准备工作:

  首先是编译jam,在< boost-path >/tools/build/v1下,把vc7.1-tools.jam文件复制一份,改名为vc80-tools.jam,我暂时未测试stl-port。

  修改文件内容里的路径,这个根据你的安装路径来改。去掉几个flag行,以后编译时就少一些警告。修改以后内容如下:

extends-toolset msvc ;

# singleton variables...
set-as-singleton VC80_ROOT ;

if ! $(MSVCDir)
{
ProgramFiles ?= $(PROGRAMFILES) ;
VC80_ROOT ?= $(ProgramFiles:J=" ")//Microsoft Visual Studio 8//VC" ;
VC_TOOL_PATH = "$(VC80_ROOT)//bin// ;
VC_SETUP = "CALL /"$(VC_TOOL_PATH)VCVARS32.BAT/" >nul" ;
}
VC_PDB_NAME = vc80 ;
flags vc80 C++FLAGS on : /Zc:wchar_t ;

  然后打开VC2005程序组里面的Visual Studio Command Prompt,这能确保已加载环境变量,减少后面一些操作过程。在[boost-path]/tools/build/jam-src目录下运行:

build -sTOOLS=vc80

  编译会通过的,最后链接时会报错,之后想到的方法如下:

./bootstrap.vc7/jam0 -f build.jam --toolset=vc7 "--toolset-root=C:/Program Files/Microsoft Visual Studio 8/VC"

  注:这个选项不能直接附加在build批处理后面,所以要这样调用。

  好了,bjam编译完成。下面编译boost,有2个文件需要改一下:

  [boost-path]/boost/config/auto_link.hpp在第118行附近改为:

#elif defined(BOOST_MSVC) && (BOOST_MSVC == 1310)

// vc71:
# define BOOST_LIB_TOOLSET "vc71"

#elif defined(BOOST_MSVC) && (BOOST_MSVC >= 1400)

// vc80:
# define BOOST_LIB_TOOLSET "vc80"

  注:如果你不修改这里,那么后面测试时无法链接到正确的lib,因为前面我们已经使用了“VC.NET 2005”,生成的lib全是VC.NET 2005的。

  [boost-path]/boost/config/compile/visualc.hpp最后面的>1310改为1400,如下:

#if (_MSC_VER?> 1400)

  注:如果不修改这个,无法正确生成所需要的lib。

  这些文件修改就完成了。如果你需要boost-python,那么还需设置几个环境变量,注意路径替换为你自己的,版本号只留前2位,比如2.3.4,则只需要写上2.3。

SET PYTHON_ROOT=c:/soft/python24
SET PYTHON_VERSION=2.4
SET PYTHON_LIB_PATH=c:/soft/python24/libs

  三、编译:

  以上过程都完毕了,现在转到[boost-path]目录下,运行如下命令:

tools/build/jam_src/bin.ntx86/bjam -sTOOLS=vc80 "-sBUILD=debug release static/dynamic single/multi"

  编译完成以后,设置VC2005的include和lib路径,最好搜索一下*.lib,拷到一个文件夹下,接下来就可以测试了。

  四、测试:

  写了一段测试正则表达式的代码,编译、链接,结果是报错。原来是要链接多线程版本!在VC2005里找了一下,发现只有多线程选项,单线程竟然没有列进来。

  这中间我走了一点弯路,试图编译一个多线程版本的boost,结果发现不行,编译出来还是单线程的,就线程库是多线程版本。

  最后用了个蠢办法:在#include < stdafx.h >后面加上一句:#undef _MT,终于可以运行起来了。

  五、补充说明:

  如果系统中有MSVCDir 这个环境变量,VC80_ROOT这个变量将会被忽略掉。由于vc2005对C++的标准库增加了更严格的安全性检测,所以在VC2005里使用boost会得到很多假的警告,可以通过定义 _SCL_SECURE_NO_DEPRECATE 或者加入#pragma warning(disable:4996)来处理掉,另外一些是因为某些老的C库函数被VC2005声明为deprecated(不赞成使用的),例如fopen, str*字符串函数等。

方法四:

boost库是一个跨平台的C++库,因此它的安装多少有些麻烦——如果你需要使用那些必须编译的库的时候。在windows平台上(使用VS2003和VS2005)最简单的办法就是从 http://www.boost-consulting.com/download/windows?下载boost库的installer,使用它可以指定安装基于哪个开发环境的库,每个库安装那些版本,非常方便,免去了配置编译之苦。

编译了一个使用正则表达式库regex的控制台应用程序,设定好包含目录和库目录后,发现最后链接失败,提示:LINK : fatal error LNK1104: 无法打开文件“libboost_regex-vc80-mt-gd-1_34_1.lib”。使用boost库不需要在工程设置中显式的指定库名字,而是由boost自身来完成这个设定的。由于boost库跨平台并且支持多个编译环境,因此这个被链接库文件的文件名是根据当前编译的配置动态生成的。boost_regex是库的基本名称,vc80是编译环境,mt表示这是一个多线程库,gd表示包含调试信息,最后的1_34_1是版本号。检查安装后的库文件,发现有的是boost_regex-vc80-mt-gd-1_34_1.lib,所以很明显,在库名生成的过程中出现了问题,多了一个“lib”前缀。

打开boost/regex.hpp,继续打开boost/regex/config.hpp文件,最终可以发现动态链接配置的功能是由boost/config/auto_link.hpp统一实现的。在这个文件开头的注释里详细说明了使用方式,相信这种方式对我们自己的库开发也很有裨益。这里提到了名称的构造公式:

BOOST_LIB_PREFIX
+ BOOST_LIB_NAME
+ "_"
+ BOOST_LIB_TOOLSET
+ BOOST_LIB_THREAD_OPT
+ BOOST_LIB_RT_OPT
"-"
+ BOOST_LIB_VERSION

根据我们的错误,我们应该检查BOOST_LIB_PREFIX的值为什么是“lib”而不是空的。通过搜索,发现

#if (defined(_DLL) || defined(_RTLDLL)) && defined(BOOST_DYN_LINK)
#? define BOOST_LIB_PREFIX
#elif defined(BOOST_DYN_LINK)
#? error "Mixing a dll boost library with a static runtime is a really bad idea..."
#else
#? define BOOST_LIB_PREFIX "lib"
#endif

现在终于清楚了,我们应该在工程设置中加入_DLL定义或者_RTLDLL定义,并且指定boost库采用动态连接,定义BOOST_DYN_LINK。在工程设置中加入_DLL;BOOST_DYN_LINK,链接就通过了。

方法五:

这几天写代码需要序列化自定义类,类的定义可以抽象为vector<vector<T> >。我本想通过重载operator<<和operator>> 来实现序列化。但是写入是写入了,读就读不出来了。在读完第一个对象之后istream的tellg()返回了-1,导致后续的对象无法读取。后来我使用boost很方便的就完成了序列化的工作。但是我使用的编译环境是VC9,boost还没有针对vc9的编译设置,所以编译安装还是花了点时间。

针对VC9,下载的boost需做如下修改:(+为需增加的行,)

文件 msvc.jam

@@ -231,6 +231,10 @@ local rule configure-really (
{
# Even if version is not explicitly specified, try to detect the version
# from the path.
+ if [ MATCH "(Microsoft Visual Studio 9.0)" : $(command) ]
+ {
+ version = 9.0 ;
+ }
if [ MATCH "(Microsoft Visual Studio 8)" : $(command) ]
{
version = 8.0 ;
@@ -913,13 +916,14 @@ actions compile.mc

.ProgramFiles = [ path.make [ common.get-program-files-dir ] ] ;

-.known-versions = 8.0 8.0express 7.1 7.1toolkit 7.0 6.0 ;
+.known-versions = 9.0 9.0express 8.0 8.0express 7.1 7.1toolkit 7.0 6.0 ;

# Version aliases
.version-alias-6 = 6.0 ;
.version-alias-6.5 = 6.0 ;
.version-alias-7 = 7.0 ;
.version-alias-8 = 8.0 ;
+.version-alias-9 = 9.0 ;

# Name of the registry key that contains Visual C++ installation path
# (relative to "HKEY_LOCAL_MACHINE/SOFTWARE//Microsoft"
@@ -928,6 +932,8 @@ actions compile.mc
.version-7.1-reg = "VisualStudio//7.1//Setup//VC" ;
.version-8.0-reg = "VisualStudio//8.0//Setup//VC" ;
.version-8.0express-reg = "VCExpress//8.0//Setup//VC" ;
+.version-9.0-reg = "VisualStudio//9.0//Setup//VC" ;
+.version-9.0express-reg = "VCExpress//9.0//Setup//VC" ;

# Visual C++ Toolkit 2003 do not store its installation path in the registry.
# The environment variable 'VCToolkitInstallDir' and the default installation

文件 auto_link.hpp

line133开始改成:

#elif defined(BOOST_MSVC) && (BOOST_MSVC == 1400)

// vc80:
# define BOOST_LIB_TOOLSET "vc80"

#elif defined(BOOST_MSVC) && (BOOST_MSVC >= 1500)

// vc90:
# define BOOST_LIB_TOOLSET "vc90"

#elif defined(__BORLANDC__)

文件 visualc.hpp

#error "Compiler not supported or configured - please reconfigure"
#endif
//
-// last known and checked version is 1400 (VC8):
-#if (_MSC_VER > 1400)
+// last known and checked version is 1500 (VC9):
+#if (_MSC_VER > 1500)
# if defined(BOOST_ASSERT_CONFIG)
# error "Unknown compiler version - please run the configure tests and report the results"
# else


然后就可以编译了,但是在编译过程中会有很多的warning C4819: The file contains a character that cannot be represented in the current code page (936). 原因是boost源代码的注释中有很多非low ASCII的字符,都是人名和版权注释。在编译boost库时可以不管,但是在编译包含了boost的头文件的项目时却很烦人。可以在project properties, C/C++, Advanced, Disable Specific warnings中填入4819关闭这个警告。

VS2005中 error LNK2019: 无法解析的外部符号 _WinMain@16 ,该符号在函数 _WinMainCRTStartup 中被引用。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/huangjack_1/archive/2008/10/14/3073575.aspx

boost库使用了一种自动链接技术,通过分析编译器设定的工程选项自动选择库进行链接。例如:
新建一个VC工程,右击项目,选择属性->配置属性->C/C++->代码生成->运行时库。如果选择非动态链接库(MT, MTD),boost自动链接对应的静态库,否则(MD, MDD)会链接动态库,用户在在链接选项中手动设置的boost库被忽略。
具体链接的库名也是有boost/config/auto_link.hpp中的预编译宏自动生成,如果发现boost链接了不正确的库,应该仔细分析该文件。
总之,配置boost项目的库链接不是通过配置链接器,而是通过编译器的预编译选项和预编译宏实现的。
再举一个例子:使用VC编译boost相关工程常见的一个错误是,选择MDD库编译时,报找不到boost库的错误,分析auto_link.hpp可知,在MDD选项打开时,预编译宏_DLL被设置,在auto_link.hpp的294行有如下代码:
#if ((defined(_DLL) || defined(_RTDLL))) && defined(BOOST_DYN_LINK)
#define BOOST_LIB_PREFIX
#elif defined(BOOST_DYN_LINK)
#error "Mixing a dll boost library with a static runtime is a really bad idea..."
#else
#define BOOST_LIB_PREFIX "lib"
#endif
由于BOOST_DYN_LINK未设置,导致库名前缀宏BOOST_LIB_PREFIX被定义为"lib",而boost动态链接库的库名默认是没有lib前缀的,如是会导致上述链接错误。只要在编译器预编译头中定义宏BOOST_DYN_LINK即可解决该问题

一个link error
error LNK2001: unresolved external symbol __imp___assert
You may be using /MTd (Debug Multithreaded), which could explain this link error.
When you build and link your static library, I recommend you use /MDd [debug] or /MD [release], which means use the DLL runtime libraries.

关于STLport
首先应该定义:
#define __STL_DEBUG
但由于用了STLport,会链接boost_regex-vc80-mt-gdp-1_41.lib(不用STLport时是boost_regex-vc80-mt-gd-1_41.lib)。boost_regex-vc80-mt-gdp-1_41.lib在boost的lib目录下没有,如果非得使用STLport,可以想到的有两种办法:
1)将boost的lib目录下的boost_regex-vc80-mt-gd-1_41的lib和dll复制一份出来改成boost_regex-vc80-mt-gdp-1_41的lib和dll。这种方法又会引入很多新的link error
2)将STLport下的stlportd.5.1的lib和dll拷贝出来,放入当前工程目录下,程序声明中加上:
#pragma comment(lib, "stlportd.5.1.lib")

由于boost库默认是静态链接的,因此要加入声明:
#define BOOST_ALL_DYN_LINK
#define BOOST_LIB_DIAGNOSTIC

一个测试程序:
#define BOOST_ALL_DYN_LINK
#define BOOST_LIB_DIAGNOSTIC
#define __STL_DEBUG
#pragma comment(lib, "stlportd.5.1.lib")

#include <cstdlib>
#include <stdlib.h>
#include <boost/regex.hpp>
#include <string>
#include <iostream>

using namespace boost;
using namespace std;

regex expression("^select ([a-zA-Z]*) from ([a-zA-Z]*)");

int main(int argc, char* argv[]){
std::string in;
cmatch what;
cout << "enter test string in the from of select aaa from bbb:" << endl;
getline(cin,in);
if(regex_match(in.c_str(), what, expression))

{
for(int i=0;i<what.size();i++)
cout<<"str :"<<what[i].str()<<endl;
}
else{
cout<<"Error Input"<<endl;
}
return 0;
}


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/sptoor/archive/2009/12/04/4933863.aspx

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics