![]() |
主要目標 (Main target) 是一個使用者自定義的具名實體,可以被建置,例如一個可執行檔。宣告主要目標通常使用 內建規則 章節中描述的主要目標規則之一。使用者也可以宣告自定義的主要目標規則,如 主要目標規則 章節所示。
Boost.Build 中的大多數主要目標規則都具有相同的通用簽名 (signature):
rule rule-name
(
main-target-name :
sources + :
requirements * :
default-build * :
usage-requirements * )
main-target-name
是用於在命令列上請求目標以及從其他主要目標使用它的名稱。主要目標名稱可以包含字母數字字元、破折號 ('-
') 和底線 ('_
')。sources
是必須組合的原始程式碼檔案和其他主要目標的清單。requirements
是建置此主要目標時必須始終存在的屬性清單。default-build
是將使用的屬性清單,除非相同功能的某些其他值已被指定,例如在命令列上或透過從屬目標的傳播。usage-requirements
是將傳播到所有使用此目標的主要目標(即所有其依賴項)的屬性清單。某些主要目標規則具有不同的參數清單,如其文件中明確說明。
目標的實際必要條件是透過使用明確指定的必要條件來調整宣告目標的專案的必要條件而獲得的。 usage-requirements 也是如此。更多細節可以在 屬性調整 章節中找到。
主要目標的名稱有兩個用途。首先,它用於從其他目標和命令列引用此目標。其次,它用於計算生成的檔案的名稱。通常,檔名是透過在主要目標名稱後附加系統相關的後綴和前綴而獲得的。
主要目標的名稱可以包含字母數字字元、破折號、底線和點。在解析來自其他目標的引用時,整個名稱都很重要。為了確定檔名,只會採用第一個點之前的部分。例如:
obj test.release : test.cpp : <variant>release ; obj test.debug : test.cpp : <variant>debug ;
將產生兩個名為 test.obj
的檔案(在兩個不同的目錄中),而不是兩個名為 test.release.obj
和 test.debug.obj
的檔案。
來源檔案清單指定應處理哪些內容以獲得生成的目標。大多數情況下,它只是一個檔案清單。有時,您會想要自動建構來源檔案清單,而不是手動拼寫出來,在這種情況下,您可以使用 glob 規則。以下是兩個範例:
exe a : a.cpp ; # a.cpp is the only source file exe b : [ glob *.cpp ] ; # all .cpp files in this directory are sources
除非您指定具有絕對路徑的檔案,否則該名稱將被視為相對於來源目錄 - 該目錄通常是 Jamfile 所在的目錄,但可以根據 專案 章節中的描述進行更改。
來源列表也可以參考其他主要目標。同一專案中的目標可以透過名稱互相參考,而其他專案中的目標則必須使用目錄或符號專案名稱來限定。目錄/專案名稱與目標名稱以雙正斜線區隔。沒有特殊的語法來區分目錄名稱和專案名稱 — 雙正斜線之前的部分會先被查找為專案名稱,然後再查找為目錄名稱。例如
lib helper : helper.cpp ; exe a : a.cpp helper ; # Since all project ids start with slash, ".." is a directory name. exe b : b.cpp ..//utils ; exe c : c.cpp /boost/program_options//program_options ;
第一個 exe 使用在同一個專案中定義的程式庫。第二個使用由上一層 Jamfile 定義的目標(很可能是程式庫)。最後,第三個目標使用 C++ Boost 程式庫,並使用其絕對符號名稱來參考它。更多關於目標參考的資訊可以在 「相依目標」 和 「目標識別碼和參考」 這兩個章節中找到。
需求是在建置目標時應該始終存在的屬性。通常,它們是 include 和 define
exe hello : hello.cpp : <include>/opt/boost <define>MY_DEBUG ;
還有許多其他功能,列在 「內建功能」 章節中。例如,如果一個程式庫只能靜態建置,或者由於編譯器錯誤而無法對檔案進行最佳化編譯,則可以使用
lib util : util.cpp : <link>static ; obj main : main.cpp : <optimization>off ;
有時,需要在目標的建置屬性之間維持特定的關係。這可以透過條件式需求來達成。例如,您可能希望在程式庫以共享方式建置時,或目標的 release
變體以發布模式建置時,設定特定的 #defines
。
lib network : network.cpp
: <link>shared:<define>NETWORK_LIB_SHARED
<variant>release:<define>EXTRA_FAST
;
在上面的例子中,每當 network
使用 <link>shared
建置時,<define>NETWORK_LIB_SHARED
也會在其屬性中。
您可以在條件中使用多個屬性,例如
lib network : network.cpp : <toolset>gcc,<optimization>speed:<define>USE_INLINE_ASSEMBLER ;
條件式需求的更強大變體是間接條件式需求。您可以提供一個規則,該規則將使用目前的建置屬性進行呼叫,並可以計算要新增的額外屬性。例如
lib network : network.cpp : <conditional>@my-rule ; rule my-rule ( properties * ) { local result ; if <toolset>gcc <optimization>speed in $(properties) { result += <define>USE_INLINE_ASSEMBLER ; } return $(result) ; }
這個例子與前一個例子相同,但對於複雜的情況,間接條件式需求更容易撰寫和理解。
為目標明確指定的的需求通常會與包含專案的需求合併。您可以讓目標完全忽略特定的專案需求,方法是在屬性前加上減號,例如
exe main : main.cpp : -<define>UNNECESSARY_DEFINE ;
這種語法是忽略父項的自由屬性(例如 define)的唯一方法。它也適用於一般屬性。請參考以下範例
project test : requirements <threading>multi ; exe test1 : test1.cpp ; exe test2 : test2.cpp : <threading>single ; exe test3 : test3.cpp : -<threading>multi ;
這裡,test1
繼承專案需求,並且將始終以多執行緒模式建置。test2
目標覆寫專案的需求,並且將始終以單執行緒模式建置。相反地,test3
目標從專案需求中移除一個屬性,並且將根據使用者要求的變體以單執行緒或多執行緒模式建置。
請注意,移除需求條件完全是文字比對的:您需要指定完全相同的屬性才能將其移除。
default-build
參數是一組屬性,如果建置請求沒有為該組中的功能指定值,則會使用這些屬性。例如
exe hello : hello.cpp : : <threading>multi ;
除非使用者明確要求單執行緒版本,否則將會建置多執行緒目標。需求條件和預設建置之間的差異在於需求條件無法以任何方式被覆寫。
建置目標的方式可能非常不同,以至於使用條件需求來描述它們會很困難。例如,假設一個程式庫實際上根據用於建置它的工具集使用不同的原始程式碼檔案。我們可以使用目標替代方案來表達這種情況
lib demangler : dummy_demangler.cpp ; # alternative 1 lib demangler : demangler_gcc.cpp : <toolset>gcc ; # alternative 2 lib demangler : demangler_msvc.cpp : <toolset>msvc ; # alternative 3
在上面的例子中,當使用 gcc
或 msvc
建置時,demangler
將使用特定於該工具集的原始程式碼檔案。否則,它將使用通用的原始程式碼檔案 dummy_demangler.cpp
。
可以內嵌宣告目標,即「sources」參數可以包含對其他主要規則的呼叫。例如
exe hello : hello.cpp [ obj helpers : helpers.cpp : <optimization>off ] ;
將導致「helpers.cpp」始終在沒有最佳化的情況下被編譯。當引用內嵌的主要目標時,其宣告的名稱必須在其父目標的名稱和兩個點之前。在上面的例子中,要只建置 helpers,應該執行 b2 hello..helpers
。
當命令列中沒有請求任何目標時,將會建置目前專案中的所有目標。如果一個目標應該只透過明確請求來建置,這可以使用 explicit 規則來表示
explicit install_programs ;