![]() |
當建構一個目標 X
需要先建構另一個目標 Y
時(例如一個必須與 X 連結的函式庫),Y
就稱為 X
的 相依項目 (dependency),而 X
則稱為 Y
的 相依目標 (dependent)。
為了理解目標相依性,讓我們繼續上面的例子,看看 top/app/Jamfile
如何使用來自 top/util/foo
的函式庫。如果 top/util/foo/Jamfile
包含
lib bar : bar.cpp ;
那麼要在 top/app/Jamfile
中使用這個函式庫,我們可以這樣寫:
exe app : app.cpp ../util/foo//bar ;
雖然 app.cpp
指的是一個普通的原始程式檔,但 ../util/foo//bar
指的是另一個目標:在 ../util/foo
的 Jamfile 中宣告的函式庫 bar
。
其他一些建構系統有特殊的語法來列出相依函式庫,例如 LIBS
變數。在 Boost.Build 中,您只需將函式庫添加到原始程式碼列表中即可。
假設我們用以下方式建構 app
:
b2 app optimization=full define=USE_ASM
那麼哪些屬性會被用來建構 foo
呢?答案是某些特性會被 傳播 (propagated)——Boost.Build 會嘗試使用具有相同傳播特性值的相依項目。 <optimization>
特性會被傳播,因此 app
和 foo
都將使用完整最佳化進行編譯。但是 <define>
不會被傳播:它的值會照原樣添加到 a.cpp
的編譯器旗標中,但不會影響 foo
。
讓我們進一步改進這個專案。該函式庫可能有一些標頭檔,在編譯 app.cpp
時必須使用。我們可以手動將必要的 #include
路徑作為 <include>
特性的值添加到 app
的需求中,但這樣一來,所有使用 foo
的程式都必須重複這個工作。更好的解決方案是這樣修改 util/foo/Jamfile
:
project : usage-requirements <include>. ; lib foo : foo.cpp ;
使用需求不是應用於被宣告的目標,而是應用於它的相依目標。在這種情況下,<include>.
將應用於所有直接依賴於 foo
的目標。
另一個改進是使用符號識別碼來引用函式庫,而不是使用 Jamfile
位置。在大型專案中,一個函式庫可能會被許多目標使用,如果它們都使用 Jamfile
位置,那麼目錄組織的更改將會帶來大量的工作。解決方案是使用專案 ID——與目錄佈局無關的符號名稱。首先,我們需要透過將以下程式碼添加到 Jamroot
來指定專案 ID:
use-project /library-example/foo : util/foo ;
其次,我們修改 app/Jamfile
以使用專案 ID:
exe app : app.cpp /library-example/foo//bar ;
語法 `/library-example/foo//bar
` 用於指涉專案 ID 為 `/library-example/foo
` 中的目標 `bar
`。我們已經達成了目標 — 如果函式庫被移動到不同的目錄,只需要修改 `Jamroot
` 檔案。請注意,專案 ID 是全域的 — 兩個 Jamfile 不允許將相同的專案 ID 分配給不同的目錄。
如果您希望某個專案中的所有應用程式都連結到特定的函式庫,則可以使用 `<library>
` 屬性,避免在每個目標的來源中直接指定它。例如,如果 `/boost/filesystem//fs
` 應該連結到專案中的所有應用程式,您可以將 `<library>/boost/filesystem//fs
` 新增到專案的需求中,如下所示:
project : requirements <library>/boost/filesystem//fs ;