Boost.Build 简明教程

Boost.Build简明教程(译)
Written by Boris Schäling.html

历史:linux

2018-12-20 姚彧 初版

目录c++


介绍 Introduction

一个与编译器和平台都无关的编译系统 Compiler- and platform-independent build systemgit

Boost.Build是一个高级编译系统, 它能尽量容易地管理C++项目(集)。 其思想是, 在配置文件中指定生成程序所需的内容。例如,不须要告诉Boost.Build如何使用某个编译器, Boost.Build支持多个编译器,并知道如何使用它们。若是你建立一个配置文件,你只须要告诉Boost.Build源文件在哪里,调用哪些可执行文件,使用哪一个编译器。而后,Boost.Build会查找编译器并自动生成程序。github

Boost.Build支持许多不包含任何特定编译器选项的编译器配置文件。配置文件彻底是与编译器无关的。能够设置是否优化代码之类的选项, 不过,这些选项都是用Boost.Build语言写的。一旦选择编译器进行编译, Boost.Build会将配置文件中的选项翻译成相应的编译器命令行选项。这样就有可能写一次配置文件,在不一样的平台上用不一样的编译器生成程序。编程

听起来不错,但Boost.Build只支持C++和C项目. Boost.Build不知道如何使用其余编译器,好比Java编译器。虽然Boost.Build是可扩展的,可是对于用其余编程语言实现的程序,使用不一样的构建系统更有意义。bootstrap

建立Boost.Build,是为了在不一样平台上使用不一样的编译器轻松编译和安装Boost C++库。虽然Boost.Build是Boost C++库的一部分,而且附带了它,但它能够单独用于任何C++或C项目。若是您不想使用Boost C++库,甚至能够只下载Boost.Buildwindows

本文是一个介绍,帮助在C++或C项目中使用Boost.Build。它让咱们对Boost.Build如何工做以及怎么使用它有基本的了解。在阅读了本文以后,您不只应该可以在本身的项目中使用Boost.Build,并且还能更容易理解Boost.Build文档,由于您将了解整个过程。安全


生成过程 Build process

Jamfiles和b2解析器 Jamfiles and an interpreter called b2markdown

用于生成由Boost.Build管理项目的程序称为b2. 若是你下载和编译了Boost C++库, 你就已经用过了b2b2查找配置文件,读取配置文件, 并编译相应的项目。它还接受各类命令行选项,例如显示在b2编译项目过程当中全部的命令。

项目能够很大,能够由许多组件组成,其源代码分布在多个目录中。不须要为整个项目建立一个大的配置文件,组件有本身的配置文件。这对于Boost.Build没有什么不一样:在一个大的项目中, 有不少的配置文件,b2会发现和解释它们。

对Boost.Build来讲, 有配置文件的目录就是一个项目: 若是目录里有配置文件,就能够编译。对Boost.Build来讲, 子目录里的一个组件与包含不少组件的软件没有区别.

b2启动时,它不会在整个文件系统上运行搜索配置文件。它仅在当前工做目录中搜索配置文件。若是没有找到配置文件,它就什么也不作。若是当前工做目录中没有配置文件,b2不会在任何其余目录中搜索配置文件。

b2配置文件叫Jamfile.jam. 有jam后缀的文件叫Jamfiles. 若是b2发现当前目录下有Jamfile, 它会逐层查找父目录中的Jamfilesb2逐层查找上级目录,直到找到Jamroot.jam文件. Jamroot.jamJamfile.jam没有区别, 它只是告诉b2不须要再查找下去.

为何b2在父目录中查找Jamfiles,是由于这样能够进行批量设置。若是一些组件有一些相同的设置, 他们能够存储在父目录的Jamfile中,这些设置会自动应用到子目录组件中。

注意:
b2必需要找到Jamroot.jam文件, 没有Jamroot.jam文件就会报错. 若是当前目录下有Jamroot.jam文件, 就不须要其它Jamfile.jam文件. 若是Jamroot.jam在父目录, 当前目录必须有Jamfile.jam文件, 不然, b2不会作任何事情.

若是将b2复制到不包含Jamfiles文件的目录,并运行程序,则会收到错误消息。可是b2不会报“不能找到Jamfile”的错误,它会报”找不到构建系统”的错误。

Unable to load Boost.Build: could not find "boost-build.jam"
---------------------------------------------------------------
Attempted search from C:\Users\Boris\Desktop up to the root

Please consult the documentation at 'http://www.boost.org'.

b2所作的第一件事不是查找Jamfile,而是加载编译系统。可是Boost.Build的编译系统到底是什么呢?

b2是一个解释器。它不知道如何编译任何东西。b2的任务就是解释jamfile。Boost.Build其实是在jamfile中实现的。它们包含了全部使Boost.Build成为强大工具的逻辑。由于b2只作它在Jamfiles中读取的任务,因此它须要知道在哪里能够找到构成Boost.Build的Jamfiles。

b2启动时,它会在当前工做目录中寻找boost-build.jam。若是没有找到文件,它会搜索全部的父目录。这个文件只须要包含一行就能够告诉b2在哪里找到编译系统。

boost-build C:/boost_1_57_0/tools/build/src ;

boost-build以后的路径必须引用一个目录,该目录包含一个名为bootstrap.jam的文件。这是b2加载编译系统所需的文件。随着Boost C++库,附带了Boost.Build。您能够引用Boost C++库根目录的子目录tools/build。并且,您能够始终使用斜杠做为路径分隔符,即便是Windows。

请注意,路径和行尾的分号之间必须有空格。没有空格是语法错误。在本文后面,您将了解更多Jamfiles中使用的语法。

若是b2找到了boost-build.jam。它使用文件中的路径来加载编译系统。编译系统加载后,它还会准备要使用的编译器、连接器,和编译项目所需的其余工具。Boost.Build将这些程序称为工具集。若是运行b2时没有使用命令行选项,则编译系统将尝试找到它能够自动使用的工具集(toolset)。例如,它在Windows上搜索Visual C++。若是它检测到Visual C++已经安装,它就会使用工具集(toolset)msvc。

warning: No toolsets are configured.
warning: Configuring default toolset "msvc".
warning: If the default is wrong, your build may not work correctly.
warning: Use the "toolset=xxxxx" option to override our guess.
warning: For more configuration options, please consult
warning: http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html

若是在启动b2时, 没有指定使用哪一个工具集,则会看到警告。b2告诉您它检测到并决定使用哪一个工具集。若是您想要隐藏警告,您必须本身指定工具集。例如,要使用Visual C++, 输入b2 toolset=msvc。若是但愿使用GCC,则输入b2 toolset= GCC

到目前为止,支持的工具集超过10个。Boost.Build颇有可能与您使用的编译器能够一块儿工做。

一旦找到了编译系统, 加载并知道使用哪个工具集(要么指定, 要么是编译系统自动检测的) b2在当前目录找到Jamfile.jam文件。若是没有找到Jamfile, 就会输出错误消息。

error: error: no Jamfile in current directory found, and no target references specified.

若是您建立一个空Jamfile.jam文件, 启动b2会输出另外的错误消息。

error: Could not find parent for project at '.'
error: Did not find Jamfile.jam or Jamroot.jam in any parent directory.

b2要找到一个名为Jamroot.jam的Jamfile。若是它不存在于当前的工做目录中,b2但愿在父目录中找到它。

若是您建立一个空的Jamroot.jam文件, 运行b2, 错误消息会消失。显然, 如今Boost.Build什么都没有作。可是如今您知道了b2是如何编译程序的,以及最小Boost.Build配置是什么样子的。

注意: 若是是一个小项目,而且只须要一个配置文件,那么能够只要Jamroot.jam, 而不要Jamfile.jam


基本任务 Basic tasks

规则和特性 Rules and features

若是查看Jamfiles,语法可能会让您想起其余编译系统使用的配置文件。简单的Jamfile可能看起来像普通的旧配置文件,也是键值对。可是须要理解的关键点是,Jamfile其实是脚本文件。是在用编程语言编写Jamfileb2不是Boost.Build的核心组件, 它知道如何编译程序。Boost.Build的逻辑在Jamfile中, 它在告诉b2如何编译程序。

即便Boost.Build是基于编程语言,在建立Jamfile时也不须要考虑编程。Boost.Build编程语言的语法, 能让咱们更多地建立普通的旧配置文件。这样作的目的是实现两个方面的最佳结合:(深刻浅出)一种功能强大且灵活的编程语言,但又是在其它编译系统中熟悉的简单语法。

本文不是向您介绍Boost.Build的编程语言。这种编程语言是专有的,使用起来并不有趣。它不是Javascript或Python等流行脚本语言的竞争对手。Boost.Build的开发人员认识到这一点,并使用另外一个基于Python的Boost.Build版本。然而,对于计划使用Boost.Build管理项目的开发人员来讲,全部这些都没有什么关系。一旦认识到Boost.Build中有一种编程语言,它将有助于更好地理解jamfile的语法。可是不须要学习编程语言的细节。

让咱们看一个简单的Jamfile,它能够用于从源文件hello.cpp编译hello执行程序。

exe hello : hello.cpp ;

Boost.Build提供了许多内置规则,exe就是其中之一。虽然Boost.Build的文档将exe做为规则引用,可是您已经知道,上面的Jamfile其实是使用编程语言构建的。事实上, 规则只是函数。上面的Jamfile包含一个函数调用。

对于编译程序一般须要作的大多数任务,Boost.Build提供了预约义规则(函数)。它和其余编程语言中的函数同样,能够传递参数。在上面的Jamfile中,在调用函数exe时, 使用了两个参数hellohello.cpp

Boost.Build编程语言只基于一种数据类型: 全部内容都是字符串列表。列表能够是空的,也能够包含一个或多个字符串。在上面的Jamfile中,在调用函数exe时, 使用了两个参数, 每一个参数包含一个字符串的列表。

exe "hello" : "hello.cpp" ;

可使用引号, 但并没必要须, 由于列表中的每一个值都是字符串数据类型。只有参数包含空格时才使用引号。

规则和第一个参数之间没有特殊的分隔符,可是必须其余参数间必须使用冒号分隔。它还须要以分号结束一行,就像您从C++中习惯的那样。

请注意,Boost.Build的编程语言要求在全部标志周围都有一个空格。例如,冒号的左边和右边必须有一个空格, 分号的左边必须有一个空格。若是标志周围没有空格,b2将没法正确解析jamfile。

若是在包含上面Jamfile和hello.cpp文件的目录中运行b2, 且在Windows上使用msvc工具集,将建立一个子目录bin\msvc-9.0\debug, 用来编译可执行的hello.exe。

PS > b2
warning: No toolsets are configured.
warning: Configuring default toolset "msvc".
warning: If the default is wrong, your build may not work correctly.
warning: Use the "toolset=xxxxx" option to override our guess.
warning: For more configuration options, please consult
warning: http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html
...found 16 targets...
...updating 10 targets...
msvc.write-setup-script bin\standalone\msvc\msvc-14.1\msvc-setup.bat
compile-c-C++ bin\msvc-14.1\debug\hello.obj
hello.cpp
msvc.link bin\msvc-14.1\debug\hello.exe
msvc.manifest bin\msvc-14.1\debug\hello.exe
...updated 11 targets...

正如您所看到的,从源文件编译可执行文件只须要Jamfile中的一行。若是程序是在Windows上编译的,甚至还有正确的文件扩展名exe

Boost.Build的主要优势是,定义所需的内容, 以告诉编译系统如何生成程序. Boost.Build能够自动完成的任何事情都是自动完成的。您不须要检测构建在某个程序上的平台,以决定是否应该添加exe之类的文件扩展名。您不须要指定如何调用Visual C++之类的编译器来编译源代码。

Boost.Build支持许多现成的工具集。因为可使用不一样的工具集编译程序,Boost.Build使用与工具集相关的目录。经过这种方式,能够用不一样的工具集构建程序,而不须要一个工具集不断覆盖另外一个工具集生成的文件。

不只有工具集相关的目录, 还有版本相关的目录。版本是指调试或发行。对于每一个版本, 都有一个目录用于编译程序 —— 这样也不会覆盖另外一个版本生成的文件。默认状况下, 生成调试版本。这就是为何会建立子目录bin\msvc-9.0\debug的缘由。若是您想要建立一个发行版本, 您能够在命令行中指定版本b2 variant=release, 或, 甚至更简单b2 release

b2 release
warning: No toolsets are configured.
warning: Configuring default toolset "msvc".
warning: If the default is wrong, your build may not work correctly.
warning: Use the "toolset=xxxxx" option to override our guess.
warning: For more configuration options, please consult
warning: http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html
...found 15 targets...
...updating 3 targets...
compile-c-C++ bin\msvc-14.1\release\hello.obj
hello.cpp
msvc.link bin\msvc-14.1\release\hello.exe
msvc.manifest bin\msvc-14.1\release\hello.exe
...updated 3 targets...

根据variant参数release, 将hello.exe编译到目录bin\msvc-9.0\release.

选择版本是一件常常要作的事情,b2 release就能够。Boost.Build指出发行版是为了选择版本(variant)。

若是您不但愿在命令行上指定版本,但但愿在默认状况下构建hello.exe的发行版,Jamfile修改以下:

exe hello : hello.cpp : <variant>release ;

exe规则(函数)接受几个可选参数。第三个参数是需求列表。您能够想象命令行选项,这些选项老是设置并传递给运行命令以编译可执行文件。

为了强制编译发行版,variant属性必须设置为release,就像之前在命令行上所作的那样。可是在Jamfile中设置变量的语法与其它编译工具是不一样的。

Boost.Build定义了类XML标记的特性(features)。Boost.Build支持的特性之一是<variant>。若是一个特性要设置为一个值,那么值必须放在<variant>标记的旁边(中间没有空格)。一些特性是自由的,这意味着它们能够被设置为您想要的任何值。<variant>是一个非自由特性,由于它只能被设置为debugrelease, 不容许有其余值。若是设置了其它值,b2会输出错误。

若是您运行b2 variant=debug, 并试图编译hello.exe的调试版, 它不能成功,由于Jamfile包含hello.exe要做为一个发布版编译的要求(requirement)。若是您但愿可以在命令行上覆盖该特性,则必须将该特性做为第四个参数而不是第三个参数传递。

exe hello : hello.cpp : : <variant>release ;

第四个参数包含默认使用但能够覆盖的特性。

若是您要在默认状况下, 生成hello.exe的debug和release版, 那么, 须要两次设置<variant>特性为debugrelease

exe hello : hello.cpp : : <variant>debug <variant>release ;

这很是重要,<variant>在第四个参数(默认值)中设置了两次。若是是指定需求的第三个参数,b2将输出错误。能够在需求中屡次设置特性,可是只有在值不是互斥的状况下才能够。程序不能在第三个参数中同时设置为debug,release版. 只有在默认值部分设置<variant>, 这样, Boost.Build才理解如何编译hello的两个exe版本。

exe hello : hello.cpp : <define>WIN32 <define>_WIN32 : <variant>debug <variant>release ;

上面的Jamfile是一个在需求中屡次设置特性的例子。特性<define>用于定义预处理器指令。定义几个预处理器指令是没有问题的。所以,hello.exe的两个版本都使用了的两个指令WIN32_WIN32来生成它们。

exe hello : hello.cpp : : <variant>debug <variant>release <define>WIN32 <define>_WIN32 ;

若是将定义移动到第四个参数,并运行b2,则hello.exe的两个版本, 都一样使用两个指令WIN32和_WIN32进行编译. 因为<define>不指望互斥值,所以没有生成其余可执行文件集。这个Jamfile与上一个Jamfile的唯一区别是,在第四个参数中传递的指令是默认值,能够删除这些值,而做为第三个参数传递的任何指令都是不可变的要求。

下面是另外一个值互斥的特性示例。

exe hello : hello.cpp : : <variant>debug <variant>release <optimization>speed <optimization>off ;

b2建立hello.exe的四个版本。针对速度优化的调试版、没有优化的调试版、针对速度优化的发行版和没有优化的发行版。全部这些版本都编译在自动建立的独立目录中。

到目前为止,惟一使用的规则是exe。可是Boost.Build提供了更多的内置规则。另外一个重要的规则是lib,它用于编译一个库。

lib world : world.cpp ;

上面的Jamfile从源文件world.cpp编译了一个共享库。在Windows上, 会建立一个world.dll的文件。一般, 文件扩展名是由Boost.Build自动追加。

默认状况下,将生成一个共享库。若是但愿生成静态库,能够将<link>特性设置为static

lib world : world.cpp : <link>static ;

另外一个有用的规则是install。在生成了可执行文件和库以后,可使用此规则来安装它们。

exe hello : hello.cpp ; 
install "C:/Program Files/hello" : hello ;

上面的Jamfile, 会把可执行文件hello.exe安装到C:\Program Files\hello. 第二个参数hello是对第一行中定义的目标hello的引用。请注意,路径必须加引号,由于它包含一个空格。

在这里,从其它编译系统的概念颇有价值: 与其考虑函数调用,不如每行定义一个目标。依赖关系是经过引用其余目标建立的。这就是Boost.Build如何知道应该以什么顺序生成目标。

可是,install规则的编写一般是不一样的。使用<location>特性在第三个参数中设置安装目录,而不是将安装目录做为第一个参数传递。

exe hello : hello.cpp ; 
install install-bin : hello : <location>"C:/Program Files/hello" ;

使用<location>更好的主要缘由是, 第一个参数老是定义一个目标。其余规则可能引用目标。这就是为何, 使用之后没必要更改的目标名称是一个好主意。设想一个程序应该安装到另外一个目录。若是<location>特性已被用做不须要更新可能引用到install-bin的其余规则,则更改安装目录将更容易。It's easier to change the installation directory if the <location> feature has been used as no other rules which might refer to install-bin have to be updated.

使用特性还有另外一个缘由。Boost.Build支持条件属性,这些属性能够根据编译程序的平台使用不一样的安装目录。

exe hello : hello.cpp ; 
install install-bin : hello : <target-os>windows:<location>"C:/Program Files/hello" <target-os>linux:<location>/usr/local/bin ;

特性<target-os>是另外一个具备互斥值的特性。例如,它能够设置为windows或linux,但不能同时设置为windows和linux。

特性<location><target-os>以后, 仅用冒号分隔。这样的构造称为条件属性: Boost.Build根据操做系统选择安装目录。

固然,条件属性也能够与其余规则一块儿使用。例如,在编译程序或库时,能够根据不一样的版本定义不一样的预处理器指令。

Boost.Build提供了更多的内置规则。另外一个有用的规则是glob,它让使用通配符成为可能。在一个包含许多源文件的大型项目中,不须要逐一列出它们,而是使用glob引用它们。

exe hello : [ glob *.cpp ] ;

上面的Jamfile包含一个嵌套的函数调用: 规则glob的结果做为第二个参数传递给exe。因为编程语言的要求,Boost.Build是基于方括号的,必须用于嵌套函数调用。


项目管理 Project management

多Jamfiles

在有不少jamfile的大型项目中,须要以某种方式链接jamfile。在项目的根目录, 一般有一个Jamroot.jam文件, 在各个子目录, 有Jamfile.jam文件。若是在根目录中运行b2,开发人员可能但愿生成整个项目,包括子目录中的全部组件。当b2在父目录而不是子目录中查找jamfile时,jamfile须要显式地引用子目录中的jamfile。

build-project hello ;

若是一个Jamfile看起来像上面的示例,它将引用hello子目录中的Jamfile。build-project是一个规则,它指望路径做为它的惟一参数, 而后在该路径中查找Jamfile。

build-project hello ; 
build-project world ;

若是您但愿构建多个项目,则必须屡次使用build-project。

除了在子目录中引用jamfile以外,在项目中生成组件时, 对应该使用的选项进行分组也是有意义的。

project : default-build release ; 
build-project hello ; 
build-project world ;

project规则接受各类参数,以便为当前工做目录和子目录中的Jamfile设置选项。

project规则使用命名参数, 而其余规则,如exelib,参数顺序传递。在上面的示例中,参数的名称是default-build。这就是为何能够在一个很是不一样的参数中传递值release。(That's why it is possible to pass the value release in a very different parameter.)

project : : : : : : : : : default-build release ; 
build-project hello ; 
build-project world ;

release做为第10个参数传递是没有意义的。但它的工做原理是, project不关心顺序。它可使用第10个参数default-build

project只支持几个命名参数。另外一个参数是requirements,它能够用来设置不能修改的选项。

project : requirements <variant>release ; 
build-project hello ; 
build-project world ;

上面的Jamfile只生成release版。不可能再生成debug版本,由于不能修改需求。这与上一个示例中使用的名为default-build的命名参数不一样: 它能够修改。

当使用build-project时,Boost.Build假定该参数是对一个子目录的引用。咱们之前见过另外一种类型的引用。

exe hello : hello.cpp ; 
install install-bin : hello : <location>"C:/Program Files/hello" ;

在上面的Jamfile中,install规则引用第一行中定义的目标hello

在大型项目中,可能须要引用在其余目录里jamfile中定义的目标。可使用双斜杠将路径与Jamfile中的目标相连。It is possible to concatenate a path to a Jamfile and a target with a double slash.)

install install-bin : subdir//hello : <location>"C:/Program Files/hello" ;

如今,install规则引用子目录subdir中的Jamfile中的目标hello

让咱们假设可执行hello依赖于另外一个目录中的world库。这个库也是用Boost.Build使用lib规则生成的。

lib world : world.cpp ;

在生成可执行文件的Jamfile中,须要引用库的Jamfile。没有必要直接引用world目标,由于默认状况下,Jamfile中的全部目标都是构建的。

exe hello : hello.cpp world : : <variant>debug <variant>release ;

上面的Jamfile假设库及其Jamfile位于子目录world中。

在生成可执行文件时,会生成两个版本 — 调试版和发行版。虽然库的Jamfile没有设置<variant>特性, 可是Boost.Build假定它也会构建这个库的两个版本。特性<variant>在这里就进行了传播。

传播特性(Propagating features)简化了项目管理,由于您不须要在各类jamfile中设置相同的特性。固然,这也使得理解组件是如何构建的变得更加复杂,由于它彻底依赖于传播的特性。您能够假定Boos.tBuild知道它应该作什么。固然,这并不意味着你很容易理解它作了什么。

让咱们看另外一个使用特性<define>的例子。

exe hello : hello.cpp world : <define>WIN32 : <variant>debug <variant>release ;

上面的Jamfile为程序hello定义了一个预处理器指令WIN32。可是WIN32也会为这个库定义吗?

它不会,由于<define>不是一个传播特性。若是您想知道应该如何知道: 查找传播特性的唯一方法是查找文档。

若是您安装了Boost C++库,您可能但愿连接到其中一些库。您必须以某种方式向项目的Jamfile中相应的Boost C++库添加一个依赖项。若是没有删除已解压缩Boost C++库源文件的目录,则能够引用根目录中Jamfile中的目标。

exe hello : hello.cpp world C:/boost_1_39_0//filesystem/ ;

如今, hello还依赖于Boost.Filesystem库。因为目标文件系统是在Boost C++库根目录下的Jamfile中定义的,所以exe规则能够引用它。不只会连接适当的Boost C++库 —— 还会将include目录传递给编译器以查找头文件。若是hello.cpp包含boost/filesystem.hpp,就会找到这个头文件。

在上面的Jamfile中,Boost C++库的根目录的路径是硬编码的。b2须要知道在哪里能够找到Boost C++库。可是,若是只硬编码一次路径,以防止项目中的几个组件须要连接到某个Boost C++库,那就更好了。

project : requirements <variant>release ; 
use-project /boost : C:/boost_1_39_0 ; 
build-project hello ; 
build-project world ;

use-project规则用于定义另外一个目录中Jamfile的别名。子目录中的Jamfiles使用别名引用Boost C++库。

exe hello : hello.cpp world /boost//filesystem ;

b2会分析出hello.cpp是源文件,world是子目录,/boost//filesystem是对C:\boost_1_39_0目录里, Jamfile文件中的目标filesystem的引用。

请注意, 若是引用的是项目,引用必须以斜杠开头。

因为库能够用不一样的方式连接,所以能够设置与连接器相关的特性。

exe hello : hello.cpp world /boost//filesystem/<link>static ;

默认状况下,库是动态连接的。若是库应该静态连接,则必须将特性<link>设置为static

特性能够用斜杠附加。若是须要设置多个特性,则在前一个特性后面附加另外一个斜杠。

exe hello : hello.cpp world /boost//filesystem/<link>static/<threading>multi ;

<threading>是另外一个能够设置为single(单线程)multi(多线程)的特性。若是hello应该连接到线程安全( thread-safe)版本的Boost.Filesystem,则能够相应地设置该特性。

经过引用Jamfile连接Boost C++库可能并不老是有效。若是Boost C++库的安装方式不一样,由于它们不是从源代码生成的,那么就不会有任何能够引用的Jamfile。

lib filesystem : : <name>libboost_filesystem <search>C:/libs ; 
exe hello : hello.cpp world filesystem : <include>C:/include ;

lib规则不只能够用于从源代码生成库。它还用于引用现有预生成的库。

若是lib不须要从源代码生成库,则第二个参数必须为空。在第三个参数中,特性<name><search>用于指定库的名称和用于Boost.Build查找库的位置。

以独立于平台的方式指定库名很是重要。例如,对于上面的Jamfile, Boost.Build将尝试在Windows上找到libboost_filesystem.lib文件。一般的文件扩展名会自动附加。

若是您想经过指定文件的确切名称来引用文件,可使用<file>特性。

若是应该引用一个系统库,您能够指望Boost.Build知道在哪里能够找到它,那么能够删除<search>特性。

也可使用project规则来确保项目中的全部目标都自动连接到库。

lib filesystem : : <name>libboost_filesystem <search>C:/libs ; 
explicit filesystem ; 
project : requirements <include>C:/include <library>filesystem ; 
lib world : world.cpp ;

必须使用名为<library>的特性向project规则添加库依赖项。<library>必须引用一个使用已知特性<name><search>lib规则。

如今,明确lib规则很是重要。这是经过使用explicit规则来实现的。这很重要,由于默认状况下,Jamfile中的全部目标都是生成的。当project规则为Jamfile中的全部目标定义需求时,它们也是lib规则的需求。所以,lib规则指的是它本身。若是lib规则是explicit(显式)的,它就不会生成的,也不会发生递归引用。

请注意,只有当规则引用目标时,Jamfile中的规则顺序才重要: 在引用目标以前,必须定义了目标。


最佳实践 Best practices

其余人如何使用Boost.Build How Boost.Build is used by others

因为Boost.Build是一个高级编译系统,若是您保持Jamfiles平台和编译器独立,那么您将得到最大的好处。毕竟,您的想法是在任何平台上使用任何编译器编译C++或C项目,而不须要修改或维护多个jamfile。

您将遇到的一个典型问题是,但愿使用的第三方库将安装在不一样的目录中。若是但愿在Windows和Unix平台上生成项目,路径看起来也很是不一样。此外,您可能须要连接某个平台上的一些系统库,而在另外一个平台上不须要。

与其尝试将不一样平台的路径放在项目的jamfile中,不如依赖每一个系统上的配置文件进行特定于系统的设置。实际上,b2在启动时确实会寻找另外两个配置文件。

应该使用site-config.jam文件为整个系统设置选项, 它是机器特有的, b2是但愿在下列目录中找到它, Windows平台上的C:\Windows目录, Unix系统的/etc目录。由于site-config.jam是依赖于机器的,因此到本地库的路径是没有问题的。

可是, 用户可能没法建立或更改site-config.jam。它们要么须要等待系统管理员更新文件,要么再次被迫向本身的jamfile添加特定于系统的路径。因为这两种方法都不是一个好的解决方案,b2还会在用户的主目录中寻找user-config.jam。在Windows上它是C:\Users的子目录,在Unix上它是/home的子目录。因为用户能够维护user-config.jam文件,因此它可能比site-config.jam更经常使用。

您能够像使用其余任何Jamfile同样使用site-config.jamuser-config.jam。因为这些配置文件不属于项目,而是属于机器或机器上的用户,所以容许它们包含特定于机器的选项。例如,它们能够包含一个using规则。

using msvc ;

上面的using规则告诉b2使用msvc工具集。若是您知道系统上只安装了Visual C++,那么将这行代码放入配置文件是有意义的。这样b2就不须要再猜想要使用哪一个工具集,也不会遗漏一个警告。

若是您在site-config.jamuser-config.jam中定义目标,而且但愿在Jamfiles中引用这些目标,则必须使用project规则来设置名称。

using msvc ; 
project user-config ; 
lib xml : : <name>libxml <search>C:/lib : : <include>C:/include ;

这里, lib规则用于引用一个预生成的库,它的名称是libxml,能够在C:\lib中找到它。使用这个XML库的程序可能须要包含这个库中的头文件。这就是为何在使用需求中的第五个参数 —— 特性<include>设置为C:\include: 使用这个规则将继承<include>特性。

因为project规则设置了名称为user-config,因此Jamfile能够经过 /user-config//xml 引用XML库。

exe xmlparser : xmlparser.cpp : <library>/user-config//xml ;

为了生成xmlparser,必须将程序连接到XML库。尽管库及其头文件的位置可能有所不一样,可是Jamfile并不包含任何特定于系统的路径。Jamfile但愿在项目user-config中找到目标xml。若是这是一个配置文件,那么在将全部配置文件绑定到机器或机器上的用户以后,使用特定于系统的路径是没有问题的。

因为已经建立了Boost.Build来生成和安装Boost C++库,所以在系统配置文件中内置,能够更轻松地使用预生成的Boost C++库。

using msvc ; 
project user-config ; 
using boost : 1.39 : <include>C:/include/boost-1_39 <library>C:/lib ;

using规则必须用于引用名为boost的工具集。这个工具集不一样于msvc这样的工具集(到目前为止您已经读过的): 它不包含任何将在稍后运行的程序。做为对预生成的Boost C++库的支持,已经在一个工具集中实现了,可是须要使用using规则。

与其余库同样,Boost C++库的位置可能有所不一样。所以,将using规则放入两个配置文件之一是有意义的。

能够将参数传递给using规则: 第一个是版本号,第二个是选项列表。在上面的Jamfile中使用了Boost C++库1.39,能够在做为选项传递的目录中找到它。

一旦使用了boost工具集,就可使用Boost C++库而无需本身定义目标。

import boost ; 
boost.use-project 1.39 ; 
exe hello : hello.cpp : <library>/boost//thread ;

若是一个程序使用Boost C++库,它能够引用名为boost的项目中的目标。为了识别项目的boost,必须导入boost模块和使用boost.use-project规则: 导入boost模块让boost.use-project规则可用。此规则指望版本号做为其惟一参数。因为可使用using规则来引用Boost C++库的不一样版本,因此项目能够指定要使用哪一个版本。在上面的Jamfile中,程序hello使用1.39版的Boost.Thread


规则参考 Rule reference

Building blocks for Jamfiles

若是您使用Boost.Build管理项目并建立jamfile,那么您将一直使用规则。所以,您应该知道存在哪些规则以及如何使用它们。下表概述了最重要的规则。

在一些参数后面有一个星号、加号或问号。星号意味着能够有任意多个值,加号必须至少有一个值,问号必须是零或刚好有一个值。

Table 1. Rules
Name Parameters Description
alias name : sources * : requirements * : default-build * : usage-requirements * Refer to sources or
build-project dir Refer to a Jamfile in another directory to build a project.
conditional condition + : requirements * Create conditional requirements without using conditional
exe name : sources * : requirements * : default-build * : usage-requirements * Build an executable.
explicit target-names * Make targets explicit.
glob wildcards + : excludes * Reference files in a directory via wildcards.
glob-tree wildcards + : excludes * Reference files in a directory and all subdirectories via wildcards.
install name-and-dir : sources * : requirements * : default-build * Install files to a directory.
lib names + : sources * : requirements * : default-build * : usage-requirements * Build a library.
project id ? : options * : * Set project options.
unit-test target : source : properties * Build and run an executable.
use-project id : where Reference a Jamfile in another directory to use the project id as a target.
using toolset-module : * Select a toolset.

您的Boost.Build版本可能支持比上面列出的更多的规则。若是您想知道支持哪些规则,您应该查看Boost.Build安装的子目录build中的文件。


属性参考 Feature reference

生成过程的配置选项 Configuration options for the build process

Table 2. Features
Name Values Description
<address-model> 16, 32, 64, 32_64 Generate 16-, 32- or 64-bit code.
<architecture> x86, ia64, sparc, power, mips1, mips2, mips3, mips4, mips32, mips32r2, mips64, parisc, arm, combined, combined-x86-power Set processor family to generate code for.
<c++-template-depth> 1, 2, 3, ... Set maximum template depth.
<cflags> ... Pass flags to C compiler.
<cxxflags> ... Pass flags to C++ compiler
<debug-symbols> on, off Create debug symbols.
<def-file> ... Set path to def file (specific to Windows DLLs).
<define> ... Define preprocessor directives.
<embed-manifest> on, off Embed manifest (specific to msvc toolset).
<host-os> aix, bsd, cygwin, darwin, freebsd, hpux, iphone, linux, netbsd, openbsd, osf, qnx, qnxnto, sgi, solaris, unix, unixware, windows Use in conditional properties if features depend on host operating systems.
<include> ... Set include directories.
<inlining> off, on, full Inline functions.
<library> ... Link to a library (use in project rule).
<link> shared, static Link to shared or static version of a library.
<linkflags> ... Pass flags to linker.
<location> ... Set directory (use in install rule).
<name> ... Set basename of a library (use in lib rule).
<optimization> off, speed, space Generate optimized code.
<profiling> off, on Generate profiled code.
<runtime-link> shared, static Link to single-threaded or thread-safe runtime library.
<search> ... Set directory to search for libraries (use in lib rule together with `).
<source> ... Set source in requirements parameter of project rule or in conditional properties.
<target-os> aix, appletv, bsd, cygwin, darwin, freebsd, hpux, iphone, linux, netbsd, openbsd, osf, qnx, qnxnto, sgi, solaris, unix, unixware, windows Use in conditional properties if features depend on target operating systems.
<threading> single, multi Build singlethreaded or thread-safe version.
<toolset> gcc, msvc, intel-linux, intel-win, acc, borland, como-linux, cw, dmc, hp_cxx, sun Use in conditional properties if features depend on toolsets.
<undef> ... Undefine preprocessor directives.
<use> ... Take over only usage requirements of a referenced target but don't do anything else.
<variant> debug, release, profile Build debug, release or profile version.
<warnings> on, all, off Switch off warnings.
<warnings-as-errors> off, on Treat warnings as errors.

有关Boost.Build特性的完整和最新引用,请在Boost.Build安装的子目录tool中查找文件builtin.jam。搜索以feature.feature开始的行 —— 这是用来定义特性的内部规则。

相关文章
相关标签/搜索