使用 Linux 上的 IBM 编译器的 xlcpp 工具集构建 Boost 库

结合使用 Boost 构建引擎和小端系统上的 IBM XL for Linux 编译器

本文将介绍结合使用 Boost 构建引擎 b2/bjam 以及小端系统上的 IBM XL for Linux 编译器的新 xlcpp 工具集来构建 Boost 库的过程。目标读者是对使用专家设计的 Boost 库提高 C++ 应用程序的生产力和质量感兴趣的软件工程师。在项目要求超出了 C++ 标准库提供的特性范围时,这对开发高质量应用程序非常重要。

Anh Tuyen Tran (anhtuyen_cnnew1@ca.ibm.com), 软件工程师, IBM

Anh Tuyen Tran 的照片Anh Tuyen Tran 拥有加拿大多伦多大学的软件工程、计算机科学学士学位,以及日本山口大学金融研究硕士学位。自 2007 年开始,他在 IBM 担任调试器团队的软件开发人员,现在效力于编译器团队。在 2009 年到 2013 年,Anh 曾担任过编译器领域的 Test Servers Administration 团队的团队领导。他是使用新 xlcpp 工具集构建 Boost 库、针对 Linux on z Systems 的内联汇编、硬件事务内存函数和针对 IBM POWER8 架构的内置加密功能的文档的主要贡献者之一。Anh 编写了多篇针对 IBM 编译器的文章。



2016 年 7 月 05 日

简介

Boost 是一个 C++ 库集合,这些库由 Boost 社区根据 Boost 软件许可来开发、审核和发布。Boost 中的库使用 C++ 程序设计中的高级特性和最新创新,增强了编程语言的功能。多年来,许多 Boost 库已在经过调整后包含在 C++ 标准库中。

Boost 包中包含构建 Boost 库的代码库,引导构建引擎的源代码,以及推进构建流程的 JAM 配置。尽管一些用户仍在采用使用 make 实用工具构建常规 C++ 应用程序的相同方式来构建 Boost 库,但业界的部分用户现在已经开始使用 Boost 构建引擎 b2 构建和安装这些库。因为构建流程所需的所有 JAM 配置文件会与每个 Boost 版本一起发布,所以使用 b2 构建 Boost 库是一个非常简单的过程。


Boost 构建工具 b2/bjam

b2 是构建引擎的官方名称,该引擎是根据一个名为 bjam 的早期构建工具来开发的。在较新的 Boost 版本中,b2bjam 实际上是相同的。这可以通过在两个文件上运行校验和函数来验证。为了便于讨论,本文将 Boost 构建工具称为 b2

图 1:校验和可确认 b2bjam 是相同的

b2 支持许多平台上的大量编译器。每个编译器都代表构建引擎的一个工具集。不同于为 IBM XL 编译器指定的传统工具集 vacpp,Boost 1.59.0 为较新的 IBM 编译器引入了一个名为 xlcpp 的新工具集。编写本文时,小端系统上的 IBM XL for Linux 编译器支持 xlcpp 工具集。

表 1 显示了 Boost 版本、编译器版本和用于小端系统上的 Linux 的相应工具集之间的关系。对于其他平台上的 IBM XL 编译器对 Boost xlcpp 工具集的支持,请参阅 IBM C 和 C++ 编译器家族 网站。

表 1:小端系统上的 IBM XL for Linux 编译器所支持的工具集

Linux(小端)编译器版本 Boost 版本 工具集
XL C/C++ V13.1.2 1.55.0 vacpp
XL C/C++ V13.1.3 1.59.0 xlcpp

有关 Boost.Jam 语言、Boost 构建引擎、构建配置和安装的详细信息,很容易在 www.boost.org 网站上找到。本文将重点介绍使用用于 IBM XL 编译器的新 xlcpp 工具集构建和安装 Boost 库所需的具体配置。讨论中使用了 1.59.0 版,这是随 xlcpp 工具集一起发布的第一个 Boost 版本。但是,这些内容可能也适用于更高的 Boost 版本。


构建流程

通常,构建 Boost 库的过程包含以下 3 个步骤:

  1. 准备源代码
  2. 引导 Boost 构建引擎 b2
  3. 使用 b2 构建和安装 Boost 库

在指定位置构建和安装 Boost 库后,该库和 Boost 头文件即可供软件工程师在其应用程序中使用。

准备源代码

您可以从 www.boost.org 网站下载 Boost 源代码。您需要先解压下载的包,然后才能使用它。清单 1 给出了一个获取和解压 Boost 1.59.0 版源代码的示例。

清单 1:获取和解压 Boost 代码库

$ wget http://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.tar.gz 
$ gunzip < boost_1_59_0.tar.gz | tar –xvf-

无需像清单 1 中那样分开使用 gunziptar,用户可结合使用 z 标志和 tar 实用工具,使用 gunzip 解压 .gz 文件。但是,在命令中包含 f 作为最后一个标志非常重要。f 标志指定了压缩文件的路径和名称。

解压过程会创建一个名为 boost_1_59_0 的目录。在讨论构建和安装过程时,将此目录称为 BOOST_ROOT。

需要打补丁才能使用 xlcpp 工具集构建 Boost 库。用户必须获取相应的补丁文件并应用于已解压的 Boost 源代码,然后才能继续操作。在修补过程中,将会适当地修改 Boost 头文件和 JAM 配置文件,以确保成功创建 Boost 库。请参阅 IBM XL 编译器的 Boost 库回归测试摘要页面,查看可用补丁文件的列表。补丁文件可通过 FTP 客户端或系统工具(比如 wget)获取。用户必须避免复制 Web 浏览器上呈现的补丁文件内容,因为这可能导致丢失该文件的一些部分。清单 2 给出了一个为 Boost 1.59.0 的源代码获取和应用补丁文件的示例。

清单 2:获取和修补 Boost 源代码

$ wget ftp://public.dhe.ibm.com/software/xlcpp/boost/bst1590/boost_modfile_le_1313.txt 
$ cd <the-directory-where-boost_1_59_0-resides>  
$ patch –p0 < <path-to-the-pathfile>/boost_modfile_le_1313.txt

备注:由于某些限制,比如存在遗留代码,一些用户将无法向 Boost 源代码应用补丁文件。这将在本文的一篇配套文件中解决。

尽管压缩包相对较小,但解压、构建、安装以及测试整个 Boost 库集合的构建产品需要数 GB 的磁盘空间。如果要测试 Boost 库,必须准好充足的磁盘空间。

跟着引导过程来创建 Boost 构建引擎

Boost 提供了一个名为 bootstrap.sh 的脚本来构建 b2,b2 是构建、安装和测试 Boost 库所需的 Boost 构建引擎。可以在 BOOST_ROOT 目录 boost_1_59_0 中找到 bootstrap.sh 脚本。

要使用 xlcpp 工具集引导 b2,用户必须确保 IBM xlC 编译器的路径包含在 $PATH 环境变量中。您可以使用 which 命令验证这一点,如清单 3 所示。

清单 3:准备用于引导的 $PATH 环境变量

$ which xlC                                           #xlC is not on $PATH
 which: 0652-141 There is no xlC in  …	
$ PATH=/full-path-to-xlC:${PATH}                           #Add path of xlC to $PATH 
export PATH	
$ which xlC                                           #xlC is on the $PATH
/full-path-to-xlCxlC

准备好 $PATH 变量,让构建引擎能够找到 xlC 编译器,然后使用选项 --with-toolset=xlcpp 从 BOOST_ROOT 目录中调用 bootstrap.sh 脚本。

清单 4:调用 bootstrap.sh 来使用 xlcpp 工具集构建 b2/bjam

$ cd boost_1_59_0 
$ ./bootstrap.sh --with-toolset=xlcpp 
Building Boost.Build engine with toolset xlcpp... 
… 
Generating Boost.Build configuration in project-config.jam... 
Bootstrapping is done. To build, run: 
    ./b2 
To adjust configuration, edit 'project-config.jam'. 
…

如果 bootstrap.sh 脚本成功运行,将在目录 boost_1_59_0 中创建两个名为 b2bjam 的可执行文件。如图 1 所示,b2bjam 事实上是两个相同的文件。

如果引导失败,查看 boost_1_59_0 目录中存储的日志文件 bootstrap.log 可能会了解失败的原因。请注意,尽管 bootstrap.log 中的信息描述了当前工作目录 "." 中的问题,但在某些地方,目录 "." 实际指向 boost_1_59_0/tools/build/src/engine。这是因为在构建过程中,脚本 bootstrap.sh 发出了 cd 命令来导航到 boost_1_59_0/tools/build/src/engine 目录。

如果没有指定工具集,bootstrap.sh 脚本会尝试使用系统上的其他可用编译器。该脚本执行的所有活动都将记录在 BOOST_ROOT 目录 boost_1_59_0 中的日志文件 bootstrap.log 中。

在极少数情况下,bootstrap.sh 脚本未能使用 xlcpp 工具集创建可执行文件 b2bjam,这时用户可尝试使用系统上的不同编译器来调用该脚本。其他编译器创建的构建引擎 b2/bjam 可用作替代引擎,以便在后续步骤中继续使用 xlcpp 工具集构建、安装和测试 Boost。

使用 xlcpp 工具集构建和安装 Boost

使用引导程序创建后,b2/bjam 可用于构建、安装和测试 Boost 库。如果调用 b2/bjam 时未使用任何命令行选项,将会使用默认配置来构建 Boost。对于大多数软件项目,具有默认配置的构建版本可能还不够。下一节将讨论使用 xlcpp 工具集和 b2 的命令行选项执行完整的 Boost 构建所需的步骤。可以在 www.boost.org 网站上找到所有构建选项的文档;本文只重点介绍用于 xlcpp 工具集的主要选项。

设置一个目录来启动 Boost 构建
为方便讨论,我们假设构建过程将从一个名为 mybuild 的工作目录中执行。Boost 源代码的路径(也称为 BOOST_ROOT)是 <path>/boost_1_59_0。工作目录的的设置如清单 5 所示。

清单 5:设置 Boost 构建的环境变量

$ mkdir mybuild                                         #Create working directory 
$ cd mybuild 
$ BOOST_ROOT=<path>/boost_1_59_0                         #Set $BOOST_ROOT 
$ export BOOST_ROOT 

$ mkdir boost_build                                     #Create build directory 
$ BOOST_BUILD=<path>/boost_build                         #Set $BOOST_BUILD 
$ export BOOST_BUILD

您需要正确设置所创建目录的权限,构建流程才能访问它们。

指定 BOOST_ROOT 路径对构建过程至关重要;它会告知构建引擎在系统上的何处查找源代码。除了如清单 5 中所示指定 BOOST_ROOT 作为环境变量之外,用户还可以在使用 –s 选项调用 b2 时直接提供该值作为命令行选项。

清单 6:在命令行上指定 BOOST_ROOT

<path>/b2 -s BOOST_ROOT=<path>/boost_1_59_0 …

指定要用于 Boost 构建流程的编译器
无需修改 xlcpp.jamuser_config.jam 文件,b2 将在 $PATH 上使用 xlC 编译器,使用 xlcpp 工具集构建 Boost 库。您可以在清单 3 中了解在 $PATH 上设置 xlC 编译器的详细信息。

用户可修改配置文件来灵活地指定编译器作为构建参数。有关细节将在下一篇文章中讨论。

Boost 构建引擎 b2 接受 3 种命令行标志:选项、属性和目标。可以按任意顺序指定命令行标志,并按以下方式区分它们。

  • 选项(规定构建引擎 b2 的行为)以一个或两个连字符开头,比如 –a--build-dir
  • 属性(指定要构建的库的细节)是采用了 feature=value 格式的标志,比如 link=static
  • 目标是所有不是选项也不是属性的标志。目标标志向构建引擎告知要构建的目标。

主要命令行选项
表 2 列出了一些常用于构建 Boost 库的最重要的选项。对于支持的选项的完整列表,请参阅 www.boost.org 发布的 Boost.Build 用户手册

表 2:重要选项

选项描述
-a 重新构建所有内容,即使目标已存在
-n 不运行命令,而是将它们打印到标准输出
-d0 启用调试级别 0(也就是说,不会显示信息性消息)
-dN 启用从 1 到 N 的累积调试级别。–d1 是默认值,它显示了在运行调试时为构建每个目标而采取的动作的信息
-d+N 仅启用调试级别 N
-jN 并行运行最多 N 个命令
-s var=value 使用指定的 value 覆盖变量 var 的值(从环境中导入)
--debug-configuration 显示了加载 Boost.Build 和工具集文件的过程的调试信息
--clean 清理当前目录和任何子项目中的所有目标
--help 显示帮助信息

常用属性
表 3 中列出了最常用的属性,用户可能经常在命令行上以 feature=value 形式指定这些属性。对于可接受的属性的完整列表,请参阅 www.boost.org 发表的 内置特性 节。

表 3:“特性=值” 形式的常用属性

特性可接受的值描述
variantdebug release 确定构建版本将是调试构建还是发布构建
linkshared static 确定创建的库将是共享对象还是静态对象
threadingsingle multiple 如果指定了 multiple,则生成的库是线程安全的。这需要在源代码中提供适当的支持。
cxxflags(任意字符串) 指定要传递给 C++ 编译器的选项集
cflags(任意字符串) 指定要传递给 C 编译器的选项集
linkflags(任意字符串) 指定要传递给链接器的选项集

对于一些特性,比如 linkthreading,可在命令行中为它们指定多个值。在这种情况下,目标将被构建多次,为特性的每个指定值都构建一次。例如,如果命令行属性是 link=static link=shared threading=single threading=multi 或等效的 link=static,shared threading=single,multi,将总共执行 4 次构建。

表 4:具有多个指定值的组合属性

组合属性BuildLinkThreading



link=static,shared threading=single,multi
1staticsingle
2staticmultiple
3sharedsingle
4sharedmultiple

构建和安装 Boost
准备好 Boost 源代码并设置环境后,用户就可以开始从 mybuild 目录构建和安装 Boost 库。请参阅清单 7 了解有关的命令。

清单 7:构建和安装 Boost 库

$ mkdir mybuild 
$ cd mybuild 
$ BOOST_ROOT=<path>/boost_1_59_0 
$ export BOOST_ROOT 
$ mkdir <path>/boost_build 
$ BOOST_INSTALL=<path>/boost_install 
$ export BOOST_ INSTALL 
$ BOOST_BUILD=<path>/boost_build 
$ export BOOST_BUILD 

$ cd $BOOST_ROOT 
$ ./b2 install --prefix=$BOOST_ INSTALL --build-dir=$BOOST_BUILD -j8 
-l1200 toolset=xlcpp variant=release target-os=linux -s OS=LINUX -d2 -a

命令 b2 install 执行一次配置检查,然后根据检查结果来构建和安装所有库。

与架构独立的文件(例如头文件)将安装在值 --prefix 指定的位置中由 --includedir 指定的子目录。如果没有提供相关选项,则使用默认值。

表 5:安装独立于架构的文件的选项

选项默认值描述
--prefix=<PREFIX>/usr/local 指定安装独立于架构的文件的位置
--includedir=<HDRDIR><PREFIX>/include 指定安装头文件的位置

在清单 7 中所示的例子中,--prefix 值是显式指定的位置 <path>/boost_install。另外,因为命令行上缺少 --includedir,所以会使用它的默认值 <PREFIX>/include。因此,在这种情况下,Boost 的头文件将被复制到 <path>/boost_install/include

图 2:包含在 <path>/boost_install/include 中的头文件

将根据相应的 JAM 配置文件来创建编译的库。然后将它们复制到值 --exec-prefix 规定的位置中由 --libdir 指定的子目录。如果没有这些选项,则使用默认值。

表 6:安装独立于架构的文件的选项

选项默认值描述
--exec-prefix=<EPREFIX><PREFIX> 指定安装独立于架构的文件的位置
--libdir=<DIR><EPREFIX>/lib 指定安装库文件的位置

在清单 7 中所示的例子中,--exec-prefix 的值是默认值 <PREFIX>,即 <path>/boost_install,因为未显式指定该值。类似地,由于命令行上还缺少 --libdir,所以将使用它的默认值 <EPREFIX>/lib。相应地,这些库将安装在 <path>/boost_install/lib 中。

图 3:安装在 <path>/boost_install/lib 中的库

点击查看大图

--build-dir=$BOOST_BUILD 属性规定必须在 $BOOST_BUILD 目录而不是分布树中执行构建。这在分布树位于只读位置时必不可少。

–j8 选项指定最多可并行运行 8 个命令。–l1200 选项指示 Boost 构建引擎将在 1200 秒后超时。–d2 选项启用调试级别 2,该级别会向标准输出显示运行的命令的所有动作文本。toolset=xlcpp 属性告知构建引擎,将使用 IBM XL 编译器进行编译。target-os 属性告诉构建引擎为 Linux 操作系统创建库。

因为绝大部分 Boost 库都只是头文件,所以在未优化的情况下,Boost 库的构建和安装相对较快。在更高的优化级别上,比如 –O2–qipa(过程间分析优化),编译 Boost 库可能会花更多的时间。

要向编译器传递更多选项,可以使用 cxxflagscflagslinkflags。例如,可以按照清单 8 中所示的方式,将 -qnoxlcompatmacros 选项传递给编译器。下一篇介绍 Boost 配置的进一步优化的文章将会讨论将额外选项传递给编译器的其他方式。

清单 8:将额外的选项传递给编译器

$ ./b2 install cxxflags="-qnoxlcompatmacros" cflags="-qnoxlcompatmacros" 
--prefix=$BOOST_ INSTALL --build-dir=$BOOST_BUILD -j8 -l1200 toolset=xlcpp 
variant=release target-os=linux -s OS=LINUX -d2 -a

显示要构建到 Boost 版本中的库名称
Boost 版本中的库数量在不同版本中可能有所不同。要显示所有要构建到某个 Boost 版本中的库的准确名称,可以使用 --show-libraries 选项调用 b2

清单 9:显示要构建的库

$ BOOST_ROOT/b2 --show-libraries 
The following libraries require building: 
    - atomic 
    - chrono 
    - container 
    - context 
< … >

使用此选项获取的库的准确名称将与其他选项一起使用,比如 --with-<library>--without-<library>。这些选项将在下一节介绍。

仅构建和安装特定的库
仅使用 install 命令调用时,Boost 构建引擎 b2 将构建和安装项目中包含的所有库。要规定只构建某些库,用户可以使用 --with-<library> 命令行选项。通过此选项调用时,Boost 构建引擎 b2 仍将安装所有头文件,但只会构建以下两组中的库:

  • 显式库(使用一个选项显式指定的库)
  • 隐式库(构建显式库所需的库)

例如,以下调用规定将只构建 chrono 库。尽管未指定 system 库,但仍然构建了它,因为显式指定的库 chrono 需要它。

清单 10:仅构建 chrono 库

$BOOST_ROOT/bjam install --with-chrono -j4 -l1200 toolset=xlcpp 
variant=release target-os=linux -s OS=LINUX -d2 -a

图 4 表明显式库 chrono 和隐式库 system, 均已构建。

图 4:同时构建了显式和隐式库

排除特定的库
不需要某些库时,用户可以使用选项 --without-<library> 告知 b2 这一事实。但是请注意,如果其他某个库需要指定的库,仍会构建它。例如,因为 chrono 库需要 system 库,所以即使没有显式提到要构建 system 库,仍会创建它作为 chrono 库的隐式库。

清单 11:仅排除 system 库

$BOOST_ROOT/bjam install --without-system -j4 -l1200 toolset=xlcpp 
variant=release target-os=linux -s OS=LINUX -d2 -a

结束语

从 1.59.0 版开始,Boost 支持用于 IBM XL 编译器的 xlcpp 工具集。使用 b2/bjamxlcpp 工具集构建 Boost 库很简单,尤其是在项目允许使用补丁文件来修改 Boost 头文件和 JAM 配置文件时。在不适合使用补丁文件的情况下,或者在不容易获取补丁文件时,需要完成更多工作才能构建 Boost 库。

本文介绍了在正确修补 Boost 头文件和 JAM 配置文件后,从 Boost 源代码构建和安装 Boost 库的基本过程。后续的一篇文章将会进一步介绍如何自定义 Boost 配置来轻松构建 Boost 库,甚至在不允许使用补丁文件时也能实现此操作。


致谢

感谢 Nha-Vy Tran 女士在创作本文期间提供的意见和建议。


参考资料


参考资料

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Linux
ArticleID=1034645
ArticleTitle=使用 Linux 上的 IBM 编译器的 xlcpp 工具集构建 Boost 库
publish-date=07052016