xmake 描述語法和作用域詳解

2021-09-20 08:40:47 字數 4743 閱讀 2191

xmake的工程描述檔案xmake.lua雖然基於lua語法,但是為了使得更加方便簡潔得編寫專案構建邏輯,xmake對其進行了一層封裝,使得編寫xmake.lua不會像些makefile那樣繁瑣

基本上寫個簡單的工程構建描述,只需三行就能搞定,例如:

target("test")

set_kind("binary")

add_files("src/*.c")

然後只需要執行編譯並且執行它:

$ xmake run test
這對於想要臨時寫些測試**來講,極大地提公升了開發效率。。

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

那哪些屬於外部,哪些又屬於內部呢,看看下面的注釋,就知道個大概了:

-- 外部作用域

target("test")

-- 外部作用域

set_kind("binary")

add_files("src/*.c")

on_run(function

() -- 內部作用域

end)

after_package(function

() -- 內部作用域

end)

-- 外部作用域

task("hello")

-- 外部作用域

on_run(function

() -- 內部作用域

end)

簡單的說,就是在自定義指令碼function () end之內的都屬於內部作用域,也就是指令碼作用域,其他地方都是都屬於於外部作用域。。

外部作用域

對於大部分工程來說,並不需要很複雜的工程描述,也不需要自定義指令碼支援,只需要簡單的set_***或者add_***就能滿足需求了

那麼根據二八定律,80%的情況下,我們只需要這麼寫:

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")

不需要複雜的api呼叫,也不需要各種繁瑣的變數定義,以及if判斷 和for迴圈,要的就是簡潔可讀,一眼看過去,就算不懂lua語法也沒關係

就當做簡單的描述語法,看上去有點像函式呼叫而已,會點程式設計的基本一看就知道怎麼配置。

為了做到簡潔、安全,在這個作用域內,很多lua 內建api是不開放出來的,尤其是跟寫檔案、修改操作環境相關的,僅僅提供一些基本的唯讀介面,和邏輯操作

目前外部作用域開放的lua內建api有:

當然雖然內建lua api提供不多,但xmake還提供了很多擴充套件api,像描述api就不多說,詳細可參考:工程描述api文件

還有些輔助api,例如:

還有變數定義、邏輯操作也是可以使用的,畢竟是基於lua的,該有的基礎語法,還是要有的,我們可以通過if來切換編譯檔案:

target("test")

set_kind("static")

if is_plat("iphoneos") then

add_files("src/test/ios/*.c")

else

add_files("src/test/*.c")

end

我們也可以啟用和禁用某個子工程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

需要注意的是,變數定義分全域性變數和區域性變數,區域性變數只對當前xmake.lua有效,不影響子xmake.lua

-- 區域性變數,只對當前xmake.lua有效

local var1 = 0

-- 全域性變數,影響所有之後 add_subfiles(), add_subdirs() 包含的子 xmake.lua

var2 = 1

add_subdirs("src")

內部作用域

也稱外掛程式、指令碼作用域,提供更加複雜、靈活的指令碼支援,一般用於編寫一些自定義指令碼、外掛程式開發、自定義task任務、自定義模組等等

一般通過function () end包含,並且被傳入到on_***,before_***after_***介面內的,都屬於自作用域。

例如:

-- 自定義指令碼

target("hello")

after_build(function

() -- 內部作用域

end)

-- 自定義任務、外掛程式

task("hello")

on_run(function

() -- 內部作用域

end)

在此作用域中,不僅可以使用大部分lua的api,還可以使用很多xmake提供的擴充套件模組,所有擴充套件模組,通過import來匯入

具體可參考:外掛程式開發之import類庫

這裡我們給個簡單的例子,在編譯完成後,對ios目標程式進行ldid簽名:

target("iosdemo")

set_kind("binary")

add_files("*.m")

after_build( function

(target)

-- 執行簽名,如果失敗,自動中斷,給出高亮錯誤資訊

os.run("ldid -s$(projectdir)/entitlements.plist %s", target:targetfile())

end)

需要注意的是,在內部作用域中,所有的呼叫都是啟用異常捕獲機制的,如果執行出錯,會自動中斷xmake,並給出錯誤提示資訊

因此,指令碼寫起來,不需要繁瑣的if retval then判斷,指令碼邏輯更加一目了然

介面作用域

在外部作用域中的所有描述api設定,本身也是有作用域之分的,在不同地方呼叫,影響範圍也不相同,例如:

-- 全域性根作用域,影響所有target,包括 add_subdirs() 中的子工程target設定

add_defines("debug")

-- 定義或者進入demo目標作用域(支援多次進入來追加設定)

target("demo")

set_kind("shared")

add_files("src/*.c")

-- 當前target作用域,僅僅影響當前target

add_defines("debug2")

-- 選項設定,僅支援區域性設定,不受全域性api設定所影響

option("test")

-- 當前選項的區域性作用域

set_default(false)

-- 其他target設定,-ddebug 也會被設定上

target("demo2")

set_kind("binary")

add_files("src/*.c")

-- 重新進入demo目標作用域

target("demo")

-- 追加巨集定義,只對當前demo目標有效

add_defines("debug3")

xmake裡面還有些全域性api,僅提供全域性作用域支援,例如:

等等,這些呼叫不要放置在 target 或者 option 的區域性作用域之間,雖然沒什麼實際區別,但是會影響可讀性,容易被誤導

使用方式,如下:

target("***x")

set_kind("binary")

add_files("*.c")

-- 包含子模組檔案

add_subdirs("src")

作用域縮排

xmake.lua裡面縮排,只是個編寫規範,用於更加清楚的區分,當前的設定 是針對 那個作用域的,雖然就算不縮排,也一樣ok,但是可讀性上 並不是很好。。

例如:

target("***x")

set_kind("binary")

add_files("*.c")

target("***x")

set_kind("binary")

add_files("*.c")

上述兩種方式,效果上都是一樣的,但是理解上,第一種更加直觀,一看就知道 add_files 僅僅只是針對 target 設定的,並不是全域性設定

因此,適當的進行縮排,有助於更好的維護xmake.lua

最後附上,tbox的xmake.lua和src/tbox/xmake.lua描述,僅供參考。。

個人主頁:tboox開源工程

原文出處:

深入理解php函式和php作用域詳解

函式引數預設值,在呼叫函式的引數的時候直接預設資料有乙個內定的值,然後在函式的呼叫中,直接進行預設傳參。方法內的變數只在引數的裡面起作用,全域性變數在整個引數裡面起作用,變數沒有定義的錯誤,所謂作用域就是變數被訪問的範圍或者它可以起作用的範圍,區域性變數不能再函式的外部進行訪問,get以及post變...

Vue中的v slot詳解,作用域插槽和具名插槽

1 具名插槽 有時候我們希望在指定的位置輸出我們的子元素,這時候具名插槽就排上了用場。元件呼叫時 這裡v slot 後邊的值與元件內的slot的name屬性對應,也就是插槽的名稱。list 書寫元件時 這裡name的值就是這個插槽的名稱。最後我們會在我們想要的位置將我們的元素放置。2 作用域插槽 作...

C語言 變數的作用域和生命週期詳解

目錄 定義在 塊外部的是全域性變數 定義在 塊內部的是區域性變數 什麼是 塊?這是 快外部 int main 實際上用int main來演示是不太對的,實際使用的時候我們定義變數是在int main內部定義的 下面這個例子更加清晰明了 int main 塊結束 需要注意的是 同乙個變數a可以在全域性...