xmake從入門到精通10:多個子工程目標的依賴配置

xmake是一個基於Lua的輕量級現代化c/c++的項目構建工具,主要特色是:語法簡單易上手,提供更加可讀的項目維護,實現跨平臺行爲一致的構建體驗。c++

本文主要詳細講解下,若是在一個項目中維護和生成多個目標文件的生成,以及它們之間的依賴關係設置。git

target究竟是什麼?

xmake的概念定義裏,一個獨立的項目工程可能會有多個子工程組織在一塊兒,每一個子工程對應只能生成一個惟一的目標文件,例如:可執行程序,靜態庫或者動態庫等。github

而這裏所說的每一個子工程就是xmake裏面所說的target,字面意思就是目標子工程工具

所以每一個子工程,咱們均可以經過新增一個target在xmake.lua裏面維護,例如:ui

target("test1")
    set_kind("binary")
    add_files("src/test1/*.c")
    
target("test2")
    set_kind("binary")
    add_files("src/test2/*.c")

上面咱們就定義了兩個獨立的子工程目標,編譯時候會生成兩個互不依賴的可執行文件。lua

從根域繼承全局設置

暫時先不談target間的依賴問題,若是咱們有許多通用設置,每一個target下都得設置一遍,那會很是冗餘,也很差維護。設計

所以,咱們能夠把這些配置移到target域的外面,也就是根做用域中去設置,這樣對當前xmake.lua以及全部子xmake.lua中的target都會生效,例如:code

add_links("tbox")
add_linkdirs("lib")
add_includedirs("include")

target("test1")
    set_kind("binary")
    add_files("src/test1/*.c")
    
target("test2")
    set_kind("binary")
    add_files("src/test2/*.c")

好比這兩target都須要連接tbox庫,放置在外層根域設置,test1和test2都能加上對應links。繼承

目標間的依賴設置

那若是某個target須要用到另一個tatget生成的靜態庫,應該怎麼配置呢?接口

一種方式就是經過add_linkdirsadd_links手動指定對應target最後生成的目錄庫所在目錄,而後把連接加上。

target("foo")
    set_kind("static")
    add_files("foo/*.c")
    add_defines("FOO")

target("test1")
    set_kind("binary")
    add_includedirs("foo/inc")
    add_links("foo")
    add_linkdirs("$(buildir)")
    add_files("test1/*.c")
    add_defines("FOO")
    
target("test2")
    set_kind("binary")
    add_includedirs("foo/inc")
    add_links("foo")
    add_linkdirs("$(buildir)")
    add_files("test2/*.c")
    add_defines("FOO")

上述配置中,test1和test2都會用到libfoo庫,而且須要獲取到libfoo庫的頭文件路徑,庫路徑和連接,而且在使用過程當中還須要額外設置-DFOO宏定義開關才行。

看上去沒啥,其實這麼寫有兩個問題:

  1. test目標和另外兩個庫目標之間是有編譯順序依賴的,若是test先編譯就會提示連接庫找不到
  2. 配置太過繁瑣很差維護,test1和test2有不少冗餘配置

那有沒有更加簡單可靠的配置方式呢,其實咱們只須要add_deps來對target間配置上依賴關係便可。

target("foo")
    set_kind("static")
    add_files("*.c")
    add_defines("FOO", {public = true})
    add_includedirs("foo/inc", {public = true})

target("test1")
    set_kind("binary")
    add_deps("foo")
    add_files("test1/*.c")
    
target("test2")
    set_kind("binary")
    add_deps("foo")
    add_files("test2/*.c")

對比下,test1和test2的配置,是否是精簡了好多?僅僅經過add_deps("foo")就繼承了libfoo的全部導出設置:linkdirs, links, includedirs以及defines

其中target自身生成的庫默認就會自動導出連接設置,而includedirs和defines經過設置public屬性,咱們也將它們標記爲導出,這樣能夠被test目標繼承到。

而且,如今有了依賴關係,xmake在編譯的時候,會自動處理這些target之間的編譯順序,保證不會出現連接的時候,libfoo庫尚未生成的問題。

依賴繼承的進一步解析

級聯依賴繼承

根據上文所說,target會自動繼承依賴目標中的配置和屬性,不須要額外調用add_links, add_linkdirsadd_rpathdirs等接口去關聯依賴目標了。

而且繼承關係是支持級聯的,例如:

target("library1")
    set_kind("static")
    add_files("*.c")
    add_includedirs("inc") -- 默認私有頭文件目錄不會被繼承
    add_includedirs("inc1", {public = true}) -- 此處的頭文件相關目錄也會被繼承

target("library2")
    set_kind("static")
    add_deps("library1")
    add_files("*.c")

target("test")
    set_kind("binary")
    add_deps("library2")

上面的配置中,test依賴library2,而後library2又依賴library1,那麼經過add_deps僅僅添加library2的依賴,test就能夠完整繼承整個依賴鏈上的全部導出設置。

禁用默認的繼承行爲

那若是咱們不想繼承依賴target的任何配置,如何操做呢?

add_deps("dep1", "dep2", {inherit = false})

經過顯式設置inherit配置,來告訴xmake,這兩個依賴的配置是否須要被繼承,若是不設置,默認就是啓用繼承的。

可繼承的導出屬性詳解

上文,咱們還經過 add_includedirs("inc1", {public = true}), 設置public爲true, 將includedirs的設置公開給其餘依賴的子target繼承。

目前對於target的編譯連接flags相關接口設置,都是支持繼承屬性的,能夠人爲控制是否須要導出給其餘target來依賴繼承,目前支持的屬性有:

屬性 描述
private 默認設置,做爲當前target的私有配置,不會被依賴的其餘target所繼承
public 公有配置,當前target,依賴的子target都會被設置
interface 接口設置,僅被依賴的子target所繼承設置,當前target不參與

這個其實參考借鑑了cmake的設計,目前xmake中只要跟target相關的全部編譯連接設置接口,都是支持可見性導出的,例如:add_includedirs, add_defines, add_cflags等等。

關於這塊的詳細信息,能夠看下:https://github.com/xmake-io/x...

原文:https://tboox.org/cn/2019/12/...

我的主頁
我的項目
相關文章
相關標籤/搜索