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開始的行 —— 這是用來定義特性的內部規則。

相關文章
相關標籤/搜索