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_xxx和after_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
最后附上,tbox的xmake.lua和src/tbox/xmake.lua描述,僅供參考。。
個(gè)人主頁(yè):TBOOX開(kāi)源工程
原文出處:http://tboox.org/cn/2016/10/26/api-scope/