xmake 描述語(yǔ)法和作用域詳解

xmake的工程描述文件xmake.lua雖然基于lua語(yǔ)法,但是為了使得更加方便簡(jiǎn)潔得編寫(xiě)項(xiàng)目構(gòu)建邏輯,xmake對(duì)其進(jìn)行了一層封裝,使得編寫(xiě)xmake.lua不會(huì)像些makefile那樣繁瑣

基本上寫(xiě)個(gè)簡(jiǎn)單的工程構(gòu)建描述,只需三行就能搞定,例如:

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

然后只需要執(zhí)行編譯并且運(yùn)行它:

$ xmake run test

這對(duì)于想要臨時(shí)寫(xiě)些測(cè)試代碼來(lái)講,極大地提升了開(kāi)發(fā)效率。。

作用域與工程描述語(yǔ)法

xmake的描述語(yǔ)法是按作用域劃分的,主要分為:

  • 外部作用域
  • 內(nèi)部作用域

那哪些屬于外部,哪些又屬于內(nèi)部呢,看看下面的注釋?zhuān)椭纻€(gè)大概了:


-- 外部作用域

target("test")

    -- 外部作用域
    set_kind("binary")
    add_files("src/*.c")

    on_run(function ()
        -- 內(nèi)部作用域
        end)

    after_package(function ()
        -- 內(nèi)部作用域
        end)


-- 外部作用域

task("hello")

    -- 外部作用域

    on_run(function ()
        -- 內(nèi)部作用域
        end)

簡(jiǎn)單的說(shuō),就是在自定義腳本function () end之內(nèi)的都屬于內(nèi)部作用域,也就是腳本作用域,其他地方都是都屬于于外部作用域。。

外部作用域

對(duì)于大部分工程來(lái)說(shuō),并不需要很復(fù)雜的工程描述,也不需要自定義腳本支持,只需要簡(jiǎn)單的 set_xxx 或者 add_xxx 就能滿足需求了

那么根據(jù)二八定律,80%的情況下,我們只需要這么寫(xiě):

target("test")
    set_kind("static")
    add_files("src/test/*.c")

target("demo")
    add_deps("test")
    set_kind("binary")
    add_links("test")
    add_files("src/demo/*.c")

不需要復(fù)雜的api調(diào)用,也不需要各種繁瑣的變量定義,以及 if 判斷 和 for 循環(huán),要的就是簡(jiǎn)潔可讀,一眼看過(guò)去,就算不懂lua語(yǔ)法也沒(méi)關(guān)系

就當(dāng)做簡(jiǎn)單的描述語(yǔ)法,看上去有點(diǎn)像函數(shù)調(diào)用而已,會(huì)點(diǎn)編程的基本一看就知道怎么配置。

為了做到簡(jiǎn)潔、安全,在這個(gè)作用域內(nèi),很多l(xiāng)ua 內(nèi)置api是不開(kāi)放出來(lái)的,尤其是跟寫(xiě)文件、修改操作環(huán)境相關(guān)的,僅僅提供一些基本的只讀接口,和邏輯操作

目前外部作用域開(kāi)放的lua內(nèi)置api有:

  • table
  • string
  • pairs
  • ipairs
  • print:修改版,提供格式化打印支持
  • os:僅提供只讀接口,例如getenv等等

當(dāng)然雖然內(nèi)置lua api提供不多,但xmake還提供了很多擴(kuò)展api,像描述api就不多說(shuō),詳細(xì)可參考:工程描述api文檔

還有些輔助api,例如:

  • dirs:掃描獲取當(dāng)前指定路徑中的所有目錄
  • files:掃描獲取當(dāng)前指定路徑中的所有文件
  • format: 格式化字符串,string.format的簡(jiǎn)寫(xiě)版本

還有變量定義、邏輯操作也是可以使用的,畢竟是基于lua的,該有的基礎(chǔ)語(yǔ)法,還是要有的,我們可以通過(guò)if來(lái)切換編譯文件:

target("test")
    set_kind("static")

    if is_plat("iphoneos") then
        add_files("src/test/ios/*.c")
    else
        add_files("src/test/*.c")
    end

我們也可以啟用和禁用某個(gè)子工程target:

if is_arch("arm*") then

    target("test1")
        set_kind("static")
        add_files("src/*.c")
 
else

    target("test2")
        set_kind("static")
        add_files("src/*.c")
 
end

需要注意的是,變量定義分全局變量和局部變量,局部變量只對(duì)當(dāng)前xmake.lua有效,不影響子xmake.lua


-- 局部變量,只對(duì)當(dāng)前xmake.lua有效
local var1 = 0

-- 全局變量,影響所有之后 add_subfiles(), add_subdirs() 包含的子 xmake.lua 
var2 = 1

add_subdirs("src")

內(nèi)部作用域

也稱(chēng)插件、腳本作用域,提供更加復(fù)雜、靈活的腳本支持,一般用于編寫(xiě)一些自定義腳本、插件開(kāi)發(fā)、自定義task任務(wù)、自定義模塊等等

一般通過(guò) function () end 包含,并且被傳入到 on_xxx, before_xxxafter_xxx接口內(nèi)的,都屬于自作用域。

例如:


-- 自定義腳本
target("hello")
    after_build(function ()
        -- 內(nèi)部作用域
        end)

-- 自定義任務(wù)、插件
task("hello")
    on_run(function ()
        -- 內(nèi)部作用域
        end)

在此作用域中,不僅可以使用大部分lua的api,還可以使用很多xmake提供的擴(kuò)展模塊,所有擴(kuò)展模塊,通過(guò)import來(lái)導(dǎo)入

具體可參考:插件開(kāi)發(fā)之import類(lèi)庫(kù)

這里我們給個(gè)簡(jiǎn)單的例子,在編譯完成后,對(duì)ios目標(biāo)程序進(jìn)行l(wèi)did簽名:

target("iosdemo")

    set_kind("binary")
    add_files("*.m")
    after_build( function (target) 

        -- 執(zhí)行簽名,如果失敗,自動(dòng)中斷,給出高亮錯(cuò)誤信息
        os.run("ldid -S$(projectdir)/entitlements.plist %s", target:targetfile())
    end)

需要注意的是,在內(nèi)部作用域中,所有的調(diào)用都是啟用異常捕獲機(jī)制的,如果運(yùn)行出錯(cuò),會(huì)自動(dòng)中斷xmake,并給出錯(cuò)誤提示信息

因此,腳本寫(xiě)起來(lái),不需要繁瑣的if retval then 判斷,腳本邏輯更加一目了然

接口作用域

在外部作用域中的所有描述api設(shè)置,本身也是有作用域之分的,在不同地方調(diào)用,影響范圍也不相同,例如:


-- 全局根作用域,影響所有target,包括 add_subdirs() 中的子工程target設(shè)置
add_defines("DEBUG")

-- 定義或者進(jìn)入demo目標(biāo)作用域(支持多次進(jìn)入來(lái)追加設(shè)置)
target("demo")
    set_kind("shared")
    add_files("src/*.c")

    -- 當(dāng)前target作用域,僅僅影響當(dāng)前target
    add_defines("DEBUG2")

-- 選項(xiàng)設(shè)置,僅支持局部設(shè)置,不受全局api設(shè)置所影響
option("test")
    
    -- 當(dāng)前選項(xiàng)的局部作用域
    set_default(false)

-- 其他target設(shè)置,-DDEBUG 也會(huì)被設(shè)置上
target("demo2")
    set_kind("binary")
    add_files("src/*.c")
    

-- 重新進(jìn)入demo目標(biāo)作用域
target("demo")

    -- 追加宏定義,只對(duì)當(dāng)前demo目標(biāo)有效
    add_defines("DEBUG3")

xmake里面還有些全局api,僅提供全局作用域支持,例如:

  • add_subfiles()
  • add_subdirs()
  • add_packagedirs()

等等,這些調(diào)用不要放置在 target 或者 option 的局部作用域之間,雖然沒(méi)什么實(shí)際區(qū)別,但是會(huì)影響可讀性,容易被誤導(dǎo)

使用方式,如下:

target("xxxx")
    set_kind("binary")
    add_files("*.c")

-- 包含子模塊文件
add_subdirs("src")

作用域縮進(jìn)

xmake.lua里面縮進(jìn),只是個(gè)編寫(xiě)規(guī)范,用于更加清楚的區(qū)分,當(dāng)前的設(shè)置 是針對(duì) 那個(gè)作用域的,雖然就算不縮進(jìn),也一樣ok,但是可讀性上 并不是很好。。

例如:

target("xxxx")
    set_kind("binary")
    add_files("*.c")

target("xxxx")
set_kind("binary")
add_files("*.c")

上述兩種方式,效果上都是一樣的,但是理解上,第一種更加直觀,一看就知道 add_files 僅僅只是針對(duì) target 設(shè)置的,并不是全局設(shè)置

因此,適當(dāng)?shù)倪M(jìn)行縮進(jìn),有助于更好的維護(hù)xmake.lua

最后附上,tboxxmake.luasrc/tbox/xmake.lua描述,僅供參考。。


個(gè)人主頁(yè):TBOOX開(kāi)源工程
原文出處:http://tboox.org/cn/2016/10/26/api-scope/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容