Boost.Build簡明教程(譯)
Written by Boris Schäling.html
歷史:linux
2018-12-20 姚彧 初版
目錄c++
一個與編譯器和平臺都無關的編譯系統 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.Build。windows
本文是一個介紹,幫助在C++或C項目中使用Boost.Build。它讓咱們對Boost.Build如何工做以及怎麼使用它有基本的瞭解。在閱讀了本文以後,您不只應該可以在本身的項目中使用Boost.Build,並且還能更容易理解Boost.Build文檔,由於您將瞭解整個過程。安全
Jamfiles和b2解析器 Jamfiles and an interpreter called b2markdown
用於生成由Boost.Build管理項目的程序稱爲b2. 若是你下載和編譯了Boost C++庫, 你就已經用過了b2。b2查找配置文件,讀取配置文件, 並編譯相應的項目。它還接受各類命令行選項,例如顯示在b2編譯項目過程當中全部的命令。
項目能夠很大,能夠由許多組件組成,其源代碼分佈在多個目錄中。不須要爲整個項目建立一個大的配置文件,組件有本身的配置文件。這對於Boost.Build沒有什麼不一樣:在一個大的項目中, 有不少的配置文件,b2會發現和解釋它們。
對Boost.Build來講, 有配置文件的目錄就是一個項目: 若是目錄裏有配置文件,就能夠編譯。對Boost.Build來講, 子目錄裏的一個組件與包含不少組件的軟件沒有區別.
當b2啓動時,它不會在整個文件系統上運行搜索配置文件。它僅在當前工做目錄中搜索配置文件。若是沒有找到配置文件,它就什麼也不作。若是當前工做目錄中沒有配置文件,b2不會在任何其餘目錄中搜索配置文件。
b2配置文件叫Jamfile.jam
. 有jam
後綴的文件叫Jamfiles
. 若是b2發現當前目錄下有Jamfile
, 它會逐層查找父目錄中的Jamfiles
。b2逐層查找上級目錄,直到找到Jamroot.jam
文件. Jamroot.jam
與Jamfile.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
。
規則和特性 Rules and features
若是查看Jamfiles
,語法可能會讓您想起其餘編譯系統使用的配置文件。簡單的Jamfile
可能看起來像普通的舊配置文件,也是鍵值對。可是須要理解的關鍵點是,Jamfile
其實是腳本文件。是在用編程語言編寫Jamfile
。b2不是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
時, 使用了兩個參數hello
和hello.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>
是一個非自由特性,由於它只能被設置爲debug
或release
, 不容許有其餘值。若是設置了其它值,b2會輸出錯誤。
若是您運行b2 variant=debug
, 並試圖編譯hello.exe的調試版, 它不能成功,由於Jamfile包含hello.exe
要做爲一個發佈版編譯的要求(requirement)。若是您但願可以在命令行上覆蓋該特性,則必須將該特性做爲第四個參數而不是第三個參數傳遞。
exe hello : hello.cpp : : <variant>release ;
第四個參數包含默認使用但能夠覆蓋的特性。
若是您要在默認狀況下, 生成hello.exe的debug和release版, 那麼, 須要兩次設置<variant>
特性爲debug
和release
。
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是基於方括號的,必須用於嵌套函數調用。
多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
規則使用命名參數, 而其餘規則,如exe
和lib
,參數順序傳遞。在上面的示例中,參數的名稱是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中的規則順序才重要: 在引用目標以前,必須定義了目標。
其餘人如何使用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.jam
和user-config.jam
。因爲這些配置文件不屬於項目,而是屬於機器或機器上的用戶,所以容許它們包含特定於機器的選項。例如,它們能夠包含一個using
規則。
using msvc ;
上面的using
規則告訴b2使用msvc工具集。若是您知道系統上只安裝了Visual C++,那麼將這行代碼放入配置文件是有意義的。這樣b2就不須要再猜想要使用哪一個工具集,也不會遺漏一個警告。
若是您在site-config.jam
或user-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
。
Building blocks for Jamfiles
若是您使用Boost.Build管理項目並建立jamfile,那麼您將一直使用規則。所以,您應該知道存在哪些規則以及如何使用它們。下表概述了最重要的規則。
在一些參數後面有一個星號、加號或問號。星號意味着能夠有任意多個值,加號必須至少有一個值,問號必須是零或剛好有一個值。
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
中的文件。
生成過程的配置選項 Configuration options for the build process
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
開始的行 —— 這是用來定義特性的內部規則。