Boost.Build 簡明教程


Boost.Build簡明教程(譯)
Written by Boris Schäling.

歷史:

2018-12-20 姚彧 第一版

目錄


介紹 Introduction

一個與編譯器和平台都無關的編譯系統 Compiler- and platform-independent build system

Boost.Build是一個高級編譯系統, 它能盡可能容易地管理C++項目(集)。 其思想是, 在配置文件中指定生成程序所需的內容。例如,不需要告訴Boost.Build如何使用某個編譯器, Boost.Build支持多個編譯器,並知道如何使用它們。如果你創建一個配置文件,你只需要告訴Boost.Build源文件在哪里,調用哪些可執行文件,使用哪個編譯器。然后,Boost.Build會查找編譯器並自動生成程序。

Boost.Build支持許多不包含任何特定編譯器選項的編譯器配置文件。配置文件完全是與編譯器無關的。可以設置是否優化代碼之類的選項, 不過,這些選項都是用Boost.Build語言寫的。一旦選擇編譯器進行編譯, Boost.Build會將配置文件中的選項翻譯成相應的編譯器命令行選項。這樣就有可能寫一次配置文件,在不同的平台上用不同的編譯器生成程序。

聽起來不錯,但Boost.Build只支持C++和C項目. Boost.Build不知道如何使用其他編譯器,比如Java編譯器。雖然Boost.Build是可擴展的,但是對於用其他編程語言實現的程序,使用不同的構建系統更有意義。

創建Boost.Build,是為了在不同平台上使用不同的編譯器輕松編譯和安裝Boost C++庫。雖然Boost.Build是Boost C++庫的一部分,並且附帶了它,但它可以單獨用於任何C++或C項目。如果您不想使用Boost C++庫,甚至可以只下載Boost.Build

本文是一個介紹,幫助在C++或C項目中使用Boost.Build。它讓我們對Boost.Build如何工作以及怎么使用它有基本的了解。在閱讀了本文之后,您不僅應該能夠在自己的項目中使用Boost.Build,而且還能更容易理解Boost.Build文檔,因為您將了解整個過程。


生成過程 Build process

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM