接口的命名,是有按照預(yù)定義的一些規(guī)范來命名的,這樣更加方便理解和易于使用,目前命名按照如下一些規(guī)則:
接口規(guī)則 | 描述 |
---|---|
is_ 前綴的接口 |
表示為條件判斷 |
set_ 前綴的接口 |
表示為覆蓋設(shè)置 |
add_ 前綴的接口 |
表示為追加設(shè)置 |
s 后綴的接口 |
表示支持多值傳入,例如:add_files("*.c", "test.cpp") |
on_ 前綴的接口 |
表示為覆蓋內(nèi)置腳本 |
before_ 前綴的接口 |
表示為在內(nèi)置腳本運(yùn)行前,執(zhí)行此腳本 |
after_ 前綴的接口 |
表示為在內(nèi)置腳本運(yùn)行后,執(zhí)行此腳本 |
scope("name") 的接口 |
表示為定義一個(gè)描述域,例如:target("xxx") , option("xxx") |
描述域/描述設(shè)置 | 建議縮進(jìn)表示 |
條件判斷的api,一般用于必須要處理特定平臺的編譯邏輯的場合。。通常跟lua的if語句配合使用。
接口 | 描述 | 支持版本 |
---|---|---|
is_os | 判斷當(dāng)前構(gòu)建目標(biāo)的操作系統(tǒng) | >= 2.0.1 |
is_arch | 判斷當(dāng)前編譯架構(gòu) | >= 2.0.1 |
is_plat | 判斷當(dāng)前編譯平臺 | >= 2.0.1 |
is_host | 判斷當(dāng)前主機(jī)環(huán)境操作系統(tǒng) | >= 2.1.4 |
is_mode | 判斷當(dāng)前編譯模式 | >= 2.0.1 |
is_kind | 判斷當(dāng)前編譯類型 | >= 2.0.1 |
is_option | 判斷選項(xiàng)是否啟用 | >= 2.0.1 |
-- 如果當(dāng)前操作系統(tǒng)是ios
if is_os("ios") then
add_files("src/xxx/*.m")
end
目前支持的操作系統(tǒng)有:
用于檢測編譯配置:xmake f -a armv7
-- 如果當(dāng)前架構(gòu)是x86_64或者i386
if is_arch("x86_64", "i386") then
add_files("src/xxx/*.c")
end
-- 如果當(dāng)前平臺是armv7, arm64, armv7s, armv7-a
if is_arch("armv7", "arm64", "armv7s", "armv7-a") then
-- ...
end
如果像上面那樣一個(gè)個(gè)去判斷所有arm架構(gòu),也許會很繁瑣,畢竟每個(gè)平臺的架構(gòu)類型很多,xmake提供了類似add_files中的通配符匹配模式,來更加簡潔的進(jìn)行判斷:
--如果當(dāng)前平臺是arm平臺
if is_arch("arm*") then
-- ...
end
用*
就可以匹配所有了。。
用于檢測編譯配置:xmake f -p iphoneos
-- 如果當(dāng)前平臺是android
if is_plat("android") then
add_files("src/xxx/*.c")
end
-- 如果當(dāng)前平臺是macosx或者iphoneos
if is_plat("macosx", "iphoneos") then
add_mxflags("-framework Foundation")
add_ldflags("-framework Foundation")
end
目前支持的平臺有:
當(dāng)然你也可以自己擴(kuò)展添加自己的平臺,甚至直接指定自己的平臺名:
$ xmake f -p other --sdk=...
如果指定的平臺名不存在,就會自動切到cross
平臺進(jìn)行交叉編譯,但是缺可以通過is_plat("other")
來判斷自己的平臺邏輯。
有些編譯平臺是可以在多個(gè)不同的操作系統(tǒng)進(jìn)行構(gòu)建的,例如:android的ndk就支持linux,macOS還有windows環(huán)境。
這個(gè)時(shí)候就可以通過這個(gè)接口,區(qū)分當(dāng)前是在哪個(gè)系統(tǒng)環(huán)境下進(jìn)行的構(gòu)建。
-- 如果當(dāng)前主機(jī)環(huán)境是windows
if is_host("windows") then
add_includes("C:\\includes")
else
add_includes("/usr/includess")
end
目前支持的主機(jī)環(huán)境有:
你也可以通過$(host)內(nèi)置變量或者os.host接口,來進(jìn)行獲取
用于檢測編譯配置:xmake f -m debug
編譯模式的類型并不是內(nèi)置的,可以自由指定,一般指定:debug
, release
, profile
這些就夠用了,當(dāng)然你也可以在xmake.lua使用其他模式名來判斷。
-- 如果當(dāng)前編譯模式是debug
if is_mode("debug") then
-- 添加DEBUG編譯宏
add_defines("DEBUG")
-- 啟用調(diào)試符號
set_symbols("debug")
-- 禁用優(yōu)化
set_optimize("none")
end
-- 如果是release或者profile模式
if is_mode("release", "profile") then
-- 如果是release模式
if is_mode("release") then
-- 隱藏符號
set_symbols("hidden")
-- strip所有符號
set_strip("all")
-- 忽略幀指針
add_cxflags("-fomit-frame-pointer")
add_mxflags("-fomit-frame-pointer")
-- 如果是profile模式
else
-- 啟用調(diào)試符號
set_symbols("debug")
end
-- 添加擴(kuò)展指令集
add_vectorexts("sse2", "sse3", "ssse3", "mmx")
end
判斷當(dāng)前是否編譯的是動態(tài)庫還是靜態(tài)庫,用于檢測編譯配置:xmake f -k [static|shared]
一般用于如下場景:
target("test")
-- 通過配置設(shè)置目標(biāo)的kind
set_kind("$(kind)")
add_files("src/*c")
-- 如果當(dāng)前編譯的是靜態(tài)庫,那么添加指定文件
if is_kind("static") then
add_files("src/xxx.c")
end
編譯配置的時(shí)候,可手動切換,編譯類型:
## 編譯靜態(tài)庫
$ xmake f -k static
$ xmake
## 編譯動態(tài)庫
$ xmake f -k shared
$ xmake
用于檢測自定義的編譯配置選型:xmake f --xxxx=y
如果某個(gè)自動檢測選項(xiàng)、手動設(shè)置選項(xiàng)被啟用,那么可以通過is_option
接口來判斷,例如:
-- 如果手動啟用了xmake f --demo=y 選項(xiàng)
if is_option("demo") then
-- 編譯demo目錄下的代碼
add_subdirs("src/demo")
end
全局接口影響整個(gè)工程描述,被調(diào)用后,后面被包含進(jìn)來的所有子xmake.lua
都會受影響。
接口 | 描述 | 支持版本 |
---|---|---|
includes | 添加子工程文件和目錄 | >= 2.1.5 |
set_modes | 設(shè)置支持的編譯模式 | >= 2.1.2 |
set_project | 設(shè)置工程名 | >= 2.0.1 |
set_version | 設(shè)置工程版本 | >= 2.0.1 |
set_xmakever | 設(shè)置最小xmake版本 | >= 2.1.1 |
add_subdirs | 添加子工程目錄 | >= 1.0.1 |
add_subfiles | 添加子工程文件 | >= 1.0.1 |
add_moduledirs | 添加模塊目錄 | >= 2.1.5 |
add_plugindirs | 添加插件目錄 | >= 2.0.1 |
add_packagedirs | 添加包目錄 | >= 2.0.1 |
同時(shí)支持子工程文件和目錄的添加,用于替代add_subdirs和add_subfiles接口。
這個(gè)是可選接口,一般情況下不需要設(shè)置,目前僅用于對工程增加更加細(xì)致的描述信息,方便vs工程的多模式生成,以及其他xmake插件中獲取模式信息。
例如:
set_modes("debug", "release")
如果設(shè)置了這個(gè),xmake就知道當(dāng)前工程支持哪些編譯模式,這樣生成vs工程文件的時(shí)候,只需要:
$ xmake project -k vs2017
不再需要額外手動指定需要的編譯模式了,此外其他一些想要獲取工程信息的插件,也許也會需要這些設(shè)置信息。
<p class="tip">
當(dāng)然,對于is_mode接口,set_modes
不是必須的,就算不設(shè)置,也是可以通過is_mode
正常判斷當(dāng)前的編譯模式。
</p>
設(shè)置工程名,在doxygen自動文檔生成插件、工程文件生成插件中會用到,一般設(shè)置在xmake.lua的最開頭,當(dāng)然放在其他地方也是可以的
-- 設(shè)置工程名
set_project("tbox")
-- 設(shè)置工程版本
set_version("1.5.1")
設(shè)置項(xiàng)目版本,可以放在xmake.lua任何地方,一般放在最開頭,例如:
set_version("1.5.1")
以tbox為例,如果調(diào)用set_config_header設(shè)置了config.h
,那么會自動生成如下宏:
// version
#define TB_CONFIG_VERSION "1.5.1"
#define TB_CONFIG_VERSION_MAJOR 1
#define TB_CONFIG_VERSION_MINOR 5
#define TB_CONFIG_VERSION_ALTER 1
#define TB_CONFIG_VERSION_BUILD 201510220917
2.1.7版本支持buildversion的配置:
set_version("1.5.1", {build = "%Y%m%d%H%M"})
用于處理xmake版本兼容性問題,如果項(xiàng)目的xmake.lua
,通過這個(gè)接口設(shè)置了最小xmake版本支持,那么用戶環(huán)境裝的xmake低于要求的版本,就會提示錯(cuò)誤。
一般情況下,建議默認(rèn)對其進(jìn)行設(shè)置,這樣對用戶比較友好,如果xmake.lua
中用到了高版本的api接口,用戶那邊至少可以知道是否因?yàn)榘姹静粚?dǎo)致的構(gòu)建失敗。
設(shè)置如下:
-- 設(shè)置最小版本為:2.1.0,低于此版本的xmake編譯此工程將會提示版本錯(cuò)誤信息
set_xmakever("2.1.0")
每個(gè)子工程對應(yīng)一個(gè)xmake.lua
的工程描述文件。
雖然一個(gè)xmake.lua
也可以描述多個(gè)子工程模塊,但是如果工程越來越大,越來越復(fù)雜,適當(dāng)?shù)哪K化是很有必要的。。
這就需要add_subdirs
了,將每個(gè)子模塊放到不同目錄中,并為其建立一個(gè)新的xmake.lua
獨(dú)立去維護(hù)它,例如:
./tbox
├── src
│ ├── demo
│ │ └── xmake.lua (用來描述測試模塊)
│ └── tbox
│ └── xmake.lua(用來描述libtbox庫模塊)
└── xmake.lua(用該描述通用配置信息,以及對子模塊的維護(hù))
在tbox/xmake.lua
中通過add_subdirs
將擁有xmale.lua
的子模塊的目錄,添加進(jìn)來,就可以了,例如:
-- 添加libtbox庫模塊目錄
add_subdirs("src/tbox")
-- 如果xmake f --demo=y,啟用了demo模塊,那么包含demo目錄
if is_option("demo") then
add_subdirs("src/demo")
end
默認(rèn)情況下,xmake會去編譯在所有xmake.lua中描述的所有target目標(biāo),如果只想編譯指定目標(biāo),可以執(zhí)行:
## 僅僅編譯tbox庫模塊
$ xmake build tbox
需要注意的是,每個(gè)子xmake.lua
中所有的路徑設(shè)置都是相對于當(dāng)前這個(gè)子xmake.lua
所在的目錄的,都是相對路徑,這樣方便維護(hù)
add_subfiles
的作用與add_subdirs類似,唯一的區(qū)別就是:這個(gè)接口直接指定xmake.lua
文件所在的路徑,而不是目錄,例如:
add_subfiles("src/tbox/xmake.lua")
xmake內(nèi)置的擴(kuò)展模塊都在xmake/modules
目錄下,可通過import來導(dǎo)入他們,如果自己在工程里面實(shí)現(xiàn)了一些擴(kuò)展模塊,
可以放置在這個(gè)接口指定的目錄下,import也就會能找到,并且優(yōu)先進(jìn)行導(dǎo)入。
例如定義一個(gè)find_openssl.lua
的擴(kuò)展模塊,用于擴(kuò)展內(nèi)置的lib.detect.find_package接口,則只需要將它放置在:
projectdir/xmake/modules/detect/packages/find_openssl.lua
然后在工程xmake.lua
下指定這個(gè)模塊目錄,find_package
就可以自動找到了:
add_moduledirs("projectdir/xmake/modules")
xmake內(nèi)置的插件都是放在xmake/plugins
目錄下,但是對于用戶自定義的一些特定工程的插件,如果不想放置在xmake安裝目錄下,那么可以在xmake.lua
中進(jìn)行配置指定的其他插件路徑。
-- 將當(dāng)前工程下的plugins目錄設(shè)置為自定義插件目錄
add_plugindirs("$(projectdir)/plugins")
這樣,xmake在編譯此工程的時(shí)候,也就加載這些插件。
通過設(shè)置依賴包目錄,可以方便的集成一些第三方的依賴庫,以tbox工程為例,其包目錄如下:
tbox.pkg
- base.pkg
- zlib.pkg
- polarssl.pkg
- openssl.pkg
- mysql.pkg
- pcre.pkg
- ...
如果要讓當(dāng)前工程識別加載這些包,首先要指定包目錄路徑,例如:
add_packagedirs("pkg")
指定好后,就可以在target作用域中,通過add_packages接口,來添加集成包依賴了,例如:
target("tbox")
add_packages("zlib", "polarssl", "pcre", "mysql")
定義和設(shè)置子工程模塊,每個(gè)target
對應(yīng)一個(gè)子工程,最后會生成一個(gè)目標(biāo)程序,有可能是可執(zhí)行程序,也有可能是庫模塊。
<p class="tip"> target的接口,都是可以放置在target外面的全局作用域中的,如果在全局中設(shè)置,那么會影響所有子工程target。 </p>
例如:
-- 會同時(shí)影響test和test2目標(biāo)
add_defines("DEBUG")
target("test")
add_files("*.c")
target("test2")
add_files("*.c")
<p class="tip">
target
域是可以重復(fù)進(jìn)入來實(shí)現(xiàn)分離設(shè)置的。
</p>
接口 | 描述 | 支持版本 |
---|---|---|
target | 定義工程目標(biāo) | >= 1.0.1 |
target_end | 結(jié)束定義工程目標(biāo) | >= 2.1.1 |
set_kind | 設(shè)置目標(biāo)編譯類型 | >= 1.0.1 |
set_strip | 設(shè)置是否strip信息 | >= 1.0.1 |
set_default | 設(shè)置是否為默認(rèn)構(gòu)建安裝目標(biāo) | >= 2.1.3 |
set_options | 設(shè)置關(guān)聯(lián)選項(xiàng) | >= 1.0.1 |
set_symbols | 設(shè)置符號信息 | >= 1.0.1 |
set_basename | 設(shè)置目標(biāo)文件名 | >= 2.1.2 |
set_warnings | 設(shè)置警告級別 | >= 1.0.1 |
set_optimize | 設(shè)置優(yōu)化級別 | >= 1.0.1 |
set_languages | 設(shè)置代碼語言標(biāo)準(zhǔn) | >= 1.0.1 |
set_headerdir | 設(shè)置頭文件安裝目錄 | >= 1.0.1 |
set_targetdir | 設(shè)置生成目標(biāo)文件目錄 | >= 1.0.1 |
set_objectdir | 設(shè)置對象文件生成目錄 | >= 1.0.1 |
on_load | 自定義目標(biāo)加載腳本 | >= 2.1.5 |
on_build | 自定義編譯腳本 | >= 2.0.1 |
on_clean | 自定義清理腳本 | >= 2.0.1 |
on_package | 自定義打包腳本 | >= 2.0.1 |
on_install | 自定義安裝腳本 | >= 2.0.1 |
on_uninstall | 自定義卸載腳本 | >= 2.0.1 |
on_run | 自定義運(yùn)行腳本 | >= 2.0.1 |
before_build | 在構(gòu)建之前執(zhí)行一些自定義腳本 | >= 2.0.1 |
before_clean | 在清除之前執(zhí)行一些自定義腳本 | >= 2.0.1 |
before_package | 在打包之前執(zhí)行一些自定義腳本 | >= 2.0.1 |
before_install | 在安裝之前執(zhí)行一些自定義腳本 | >= 2.0.1 |
before_uninstall | 在卸載之前執(zhí)行一些自定義腳本 | >= 2.0.1 |
before_run | 在運(yùn)行之前執(zhí)行一些自定義腳本 | >= 2.0.1 |
after_build | 在構(gòu)建之后執(zhí)行一些自定義腳本 | >= 2.0.1 |
after_clean | 在清除之后執(zhí)行一些自定義腳本 | >= 2.0.1 |
after_package | 在打包之后執(zhí)行一些自定義腳本 | >= 2.0.1 |
after_install | 在安裝之后執(zhí)行一些自定義腳本 | >= 2.0.1 |
after_uninstall | 在卸載之后執(zhí)行一些自定義腳本 | >= 2.0.1 |
after_run | 在運(yùn)行之后執(zhí)行一些自定義腳本 | >= 2.0.1 |
set_config_h | 設(shè)置自動生成的配置頭文件路徑 | >= 1.0.1 < 2.1.5 已廢棄 |
set_config_h_prefix | 設(shè)置自動生成的頭文件中宏定義命名前綴 | >= 1.0.1 < 2.1.5 已廢棄 |
set_config_header | 設(shè)置自動生成的配置頭文件路徑和前綴 | >= 2.1.5 |
set_pcheader | 設(shè)置c預(yù)編譯頭文件 | >= 2.1.5 |
set_pcxxheader | 設(shè)置c++預(yù)編譯頭文件 | >= 2.1.5 |
add_deps | 添加子工程目標(biāo)依賴 | >= 1.0.1 |
add_links | 添加鏈接庫名 | >= 1.0.1 |
add_files | 添加源代碼文件 | >= 1.0.1 |
add_headers | 添加安裝的頭文件 | >= 1.0.1 |
add_linkdirs | 添加鏈接庫搜索目錄 | >= 1.0.1 |
add_rpathdirs | 添加運(yùn)行時(shí)候動態(tài)鏈接庫搜索目錄 | >= 2.1.3 |
add_includedirs | 添加頭文件搜索目錄 | >= 1.0.1 |
add_defines | 添加宏定義 | >= 1.0.1 |
add_undefines | 取消宏定義 | >= 1.0.1 |
add_defines_h | 添加宏定義到頭文件 | >= 1.0.1 |
add_undefines_h | 取消宏定義到頭文件 | >= 1.0.1 |
add_cflags | 添加c編譯選項(xiàng) | >= 1.0.1 |
add_cxflags | 添加c/c++編譯選項(xiàng) | >= 1.0.1 |
add_cxxflags | 添加c++編譯選項(xiàng) | >= 1.0.1 |
add_mflags | 添加objc編譯選項(xiàng) | >= 1.0.1 |
add_mxflags | 添加objc/objc++編譯選項(xiàng) | >= 1.0.1 |
add_mxxflags | 添加objc++編譯選項(xiàng) | >= 1.0.1 |
add_scflags | 添加swift編譯選項(xiàng) | >= 2.0.1 |
add_asflags | 添加匯編編譯選項(xiàng) | >= 2.0.1 |
add_gcflags | 添加go編譯選項(xiàng) | >= 2.1.1 |
add_ldflags | 添加鏈接選項(xiàng) | >= 1.0.1 |
add_arflags | 添加靜態(tài)庫歸檔選項(xiàng) | >= 1.0.1 |
add_shflags | 添加動態(tài)庫鏈接選項(xiàng) | >= 1.0.1 |
add_cfunc | 添加單個(gè)c庫函數(shù)檢測 | >= 2.0.1 |
add_cxxfunc | 添加單個(gè)c++庫函數(shù)檢測 | >= 2.0.1 |
add_cfuncs | 添加c庫函數(shù)檢測 | >= 2.0.1 |
add_cxxfuncs | 添加c++庫函數(shù)接口 | >= 2.0.1 |
add_packages | 添加包依賴 | >= 2.0.1 |
add_options | 添加關(guān)聯(lián)選項(xiàng) | >= 2.0.1 |
add_languages | 添加語言標(biāo)準(zhǔn) | >= 1.0.1 |
add_vectorexts | 添加向量擴(kuò)展指令 | >= 1.0.1 |
add_frameworks | 添加鏈接框架 | >= 2.1.1 |
add_frameworkdirs | 添加鏈接框架的搜索目錄 | >= 2.1.5 |
定義一個(gè)新的控制臺工程目標(biāo),工程名為test
,最后生成的目標(biāo)名也是test
。
target("test")
set_kind("binary")
add_files("src/*.c")
可以重復(fù)調(diào)用這個(gè)api,進(jìn)入target域修改設(shè)置
-- 定義目標(biāo)demo,并進(jìn)入demo設(shè)置模式
target("demo")
set_kind("binary")
add_files("src/demo.c")
-- 定義和設(shè)置其他目標(biāo)
target("other")
...
-- 重新進(jìn)入demo目標(biāo)域,添加test.c文件
target("demo")
add_files("src/test.c")
<p class="tip"> 所有根域的設(shè)置,會全局影響所有target目標(biāo),但是不會影響option的定義。 </p>
-- 在根域?qū)λ衪arget添加-DDEBUG的宏定義,影響所有target(demo和test都會加上此宏定義)
add_defines("DEBUG")
target("demo")
set_kind("binary")
add_files("src/demo.c")
target("test")
set_kind("binary")
add_files("src/test.c")
這是一個(gè)可選的api,如果不調(diào)用,那么target("xxx")
之后的所有設(shè)置都是針對這個(gè)target進(jìn)行的,除非進(jìn)入其他target
, option
, task
域。
如果想設(shè)置完當(dāng)前target
后,顯示離開target
域,進(jìn)入根域設(shè)置,那么可以通過這個(gè)api才操作,例如:
target("test")
set_kind("static")
add_files("src/*.c")
target_end()
-- 此處已在根域
-- ...
如果不調(diào)用這個(gè)api的話:
target("test")
set_kind("static")
add_files("src/*.c")
-- 此處還在上面target域中,之后的設(shè)置還是針對test進(jìn)行的設(shè)置
-- ...
-- 這個(gè)時(shí)候才離開test,進(jìn)入另外一個(gè)target域中
target("test2")
...
設(shè)置目標(biāo)類型,目前支持的類型有:
值 | 描述 |
---|---|
binary | 二進(jìn)制程序 |
static | 靜態(tài)庫程序 |
shared | 動態(tài)庫程序 |
target("demo")
set_kind("binary")
設(shè)置當(dāng)前目標(biāo)的strip模式,目前支持一下模式:
值 | 描述 |
---|---|
debug | 鏈接的時(shí)候,strip掉調(diào)試符號 |
all | 鏈接的時(shí)候,strip掉所有符號,包括調(diào)試符號 |
這個(gè)api一般在release模式下使用,可以生成更小的二進(jìn)制程序。。
target("xxxx")
set_strip("all")
<p class="tip"> 這個(gè)api不一定非得在target之后使用,如果沒有target指定,那么將會設(shè)置到全局模式。。 </p>
這個(gè)接口用于設(shè)置給定工程目標(biāo)是否作為默認(rèn)構(gòu)建,如果沒有調(diào)用此接口進(jìn)行設(shè)置,那么這個(gè)目標(biāo)就是默認(rèn)被構(gòu)建的,例如:
target("test1")
set_default(false)
target("test2")
set_default(true)
target("test3")
...
上述代碼的三個(gè)目標(biāo),在執(zhí)行xmake
, xmake install
, xmake package
, xmake run
等命令的時(shí)候,如果不指定目標(biāo)名,那么:
目標(biāo)名 | 行為 |
---|---|
test1 | 不會被默認(rèn)構(gòu)建、安裝、打包和運(yùn)行 |
test2 | 默認(rèn)構(gòu)建、安裝、打包和運(yùn)行 |
test3 | 默認(rèn)構(gòu)建、安裝、打包和運(yùn)行 |
通過上面的例子,可以看到默認(rèn)目標(biāo)可以設(shè)置多個(gè),運(yùn)行的時(shí)候也會依次運(yùn)行。
<p class="tip">
需要注意的是,xmake uninstall
和xmake clean
命令不受此接口設(shè)置影響,因?yàn)橛脩舸蟛糠智闆r下都是喜歡清除和卸載所有。
</p>
如果不想使用默認(rèn)的目標(biāo),那么可以手動指定需要構(gòu)建安裝的目標(biāo):
$ xmake build targetname
$ xmake install targetname
如果要強(qiáng)制構(gòu)建安裝所有目標(biāo),可以傳入[-a|--all]
參數(shù):
$ xmake build [-a|--all]
$ xmake install [-a|--all]
添加選項(xiàng)依賴,如果通過option接口自定義了一些選項(xiàng),那么只有在指定target
目標(biāo)域下,添加此選項(xiàng),才能進(jìn)行關(guān)聯(lián)生效。
-- 定義一個(gè)hello選項(xiàng)
option("hello")
set_default(false)
set_showmenu(true)
add_defines("HELLO_ENABLE")
target("test")
-- 如果hello選項(xiàng)被啟用了,這個(gè)時(shí)候就會將-DHELLO_ENABLE宏應(yīng)用到test目標(biāo)上去
set_options("hello")
<p class="warning">
只有調(diào)用set_options
進(jìn)行關(guān)聯(lián)生效后,option 中定義的一些設(shè)置才會影響到此target
目標(biāo),例如:宏定義、鏈接庫、編譯選項(xiàng)等等
</p>
設(shè)置目標(biāo)的符號模式,如果當(dāng)前沒有定義target,那么將會設(shè)置到全局狀態(tài)中,影響所有后續(xù)的目標(biāo)。
目前主要支持一下幾個(gè)級別:
值 | 描述 |
---|---|
debug | 添加調(diào)試符號 |
hidden | 設(shè)置符號不可見 |
這兩個(gè)值也可以同時(shí)被設(shè)置,例如:
-- 添加調(diào)試符號, 設(shè)置符號不可見
set_symbols("debug", "hidden")
如果沒有調(diào)用這個(gè)api,默認(rèn)是禁用調(diào)試符號的。。
默認(rèn)情況下,生成的目標(biāo)文件名基于target("name")
中配置的值,例如:
-- 目標(biāo)文件名為:libxxx.a
target("xxx")
set_kind("static")
-- 目標(biāo)文件名為:libxxx2.so
target("xxx2")
set_kind("shared")
默認(rèn)的命名方式,基本上可以滿足大部分情況下的需求,但是如果有時(shí)候想要更加定制化目標(biāo)文件名
例如,按編譯模式和架構(gòu)區(qū)分目標(biāo)名,這個(gè)時(shí)候可以使用這個(gè)接口,來設(shè)置:
target("xxx")
set_kind("static")
set_basename("xxx_$(mode)_$(arch)")
如果這個(gè)時(shí)候,編譯配置為:xmake f -m debug -a armv7
,那么生成的文件名為:libxxx_debug_armv7.a
如果還想進(jìn)一步定制目標(biāo)文件的目錄名,可參考:set_targetdir。
或者通過編寫自定義腳本,實(shí)現(xiàn)更高級的邏輯,具體見:after_build和os.mv。
設(shè)置當(dāng)前目標(biāo)的編譯的警告級別,一般支持一下幾個(gè)級別:
值 | 描述 |
---|---|
none | 禁用所有警告 |
less | 啟用較少的警告 |
more | 啟用較多的警告 |
all | 啟用所有警告 |
error | 將所有警告作為編譯錯(cuò)誤 |
這個(gè)api的參數(shù)是可以混合添加的,例如:
-- 啟用所有警告,并且作為編譯錯(cuò)誤處理
set_warnings("all", "error")
如果當(dāng)前沒有目標(biāo),調(diào)用這個(gè)api將會設(shè)置到全局模式。。
設(shè)置目標(biāo)的編譯優(yōu)化等級,如果當(dāng)前沒有設(shè)置目標(biāo),那么將會設(shè)置到全局狀態(tài)中,影響所有后續(xù)的目標(biāo)。
目前主要支持一下幾個(gè)級別:
值 | 描述 |
---|---|
none | 禁用優(yōu)化 |
fast | 快速優(yōu)化 |
faster | 更快的優(yōu)化 |
fastest | 最快運(yùn)行速度的優(yōu)化 |
smallest | 最小化代碼優(yōu)化 |
aggressive | 過度優(yōu)化 |
例如:
-- 最快運(yùn)行速度的優(yōu)化
set_optimize("fastest")
設(shè)置目標(biāo)代碼編譯的語言標(biāo)準(zhǔn),如果當(dāng)前沒有目標(biāo)存在,將會設(shè)置到全局模式中。。。
支持的語言標(biāo)準(zhǔn)目前主要有以下幾個(gè):
值 | 描述 |
---|---|
ansi | c語言標(biāo)準(zhǔn): ansi |
c89 | c語言標(biāo)準(zhǔn): c89 |
gnu89 | c語言標(biāo)準(zhǔn): gnu89 |
c99 | c語言標(biāo)準(zhǔn): c99 |
gnu99 | c語言標(biāo)準(zhǔn): gnu99 |
cxx98 | c++語言標(biāo)準(zhǔn): c++98 |
gnuxx98 | c++語言標(biāo)準(zhǔn): gnu++98 |
cxx11 | c++語言標(biāo)準(zhǔn): c++11 |
gnuxx11 | c++語言標(biāo)準(zhǔn): gnu++11 |
cxx14 | c++語言標(biāo)準(zhǔn): c++14 |
gnuxx14 | c++語言標(biāo)準(zhǔn): gnu++14 |
cxx1z | c++語言標(biāo)準(zhǔn): c++1z |
gnuxx1z | c++語言標(biāo)準(zhǔn): gnu++1z |
cxx17 | c++語言標(biāo)準(zhǔn): c++17 |
gnuxx17 | c++語言標(biāo)準(zhǔn): gnu++17 |
c標(biāo)準(zhǔn)和c++標(biāo)準(zhǔn)可同時(shí)進(jìn)行設(shè)置,例如:
-- 設(shè)置c代碼標(biāo)準(zhǔn):c99, c++代碼標(biāo)準(zhǔn):c++11
set_languages("c99", "cxx11")
<p class="warning"> 并不是設(shè)置了指定的標(biāo)準(zhǔn),編譯器就一定會按這個(gè)標(biāo)準(zhǔn)來編譯,畢竟每個(gè)編譯器支持的力度不一樣,但是xmake會盡最大可能的去適配當(dāng)前編譯工具的支持標(biāo)準(zhǔn)。。。 <br><br> 例如: <br> windows下vs的編譯器并不支持按c99的標(biāo)準(zhǔn)來編譯c代碼,只能支持到c89,但是xmake為了盡可能的支持它,所以在設(shè)置c99的標(biāo)準(zhǔn)后,xmake會強(qiáng)制按c++代碼模式去編譯c代碼,從一定程度上解決了windows下編譯c99的c代碼問題。。 用戶不需要去額外做任何修改。。 </p>
設(shè)置頭文件的輸出目錄,默認(rèn)輸出到build目錄中。
target("test")
set_headerdir("$(buildir)/include")
對于需要安裝哪些頭文件,可參考add_headers接口。
設(shè)置目標(biāo)程序文件的輸出目錄,一般情況下,不需要設(shè)置,默認(rèn)會輸出在build目錄下
而build的目錄可以在工程配置的時(shí)候,手動修改:
xmake f -o /tmp/build
修改成/tmp/build
后,目標(biāo)文件默認(rèn)輸出到/tmp/build
下面。
而如果用這個(gè)接口去設(shè)置,就不需要每次敲命令修改了,例如:
target("test")
set_targetdir("/tmp/build")
<p class="tip">
如果顯示設(shè)置了set_targetdir
, 那么優(yōu)先選擇set_targetdir
指定的目錄為目標(biāo)文件的輸出目錄。
</p>
設(shè)置目標(biāo)target的對象文件(*.o/obj
)的輸出目錄,例如:
target("test")
set_objectdir("$(buildir)/.objs")
在target初始化加載的時(shí)候,將會執(zhí)行此腳本,在里面可以做一些動態(tài)的目標(biāo)配置,實(shí)現(xiàn)更靈活的目標(biāo)描述定義,例如:
target("test")
on_load(function (target)
target:add("defines", "DEBUG", "TEST=\"hello\"")
target:add("linkdirs", "/usr/lib", "/usr/local/lib")
target:add({includedirs = "/usr/include", "links" = "pthread"})
end)
可以在on_load
里面,通過target:set
, target:add
來動態(tài)添加各種target屬性。
覆蓋target目標(biāo)默認(rèn)的構(gòu)建行為,實(shí)現(xiàn)自定義的編譯過程,一般情況下,并不需要這么做,除非確實(shí)需要做一些xmake默認(rèn)沒有提供的編譯操作。
你可以通過下面的方式覆蓋它,來自定義編譯操作:
target("test")
-- 設(shè)置自定義編譯腳本
on_build(function (target)
print("build it")
end)
注:2.1.5版本之后,所有target的自定義腳本都可以針對不同平臺和架構(gòu),分別處理,例如:
target("test")
on_build("iphoneos|arm*", function (target)
print("build for iphoneos and arm")
end)
其中如果第一個(gè)參數(shù)為字符串,那么就是指定這個(gè)腳本需要在哪個(gè)平臺|架構(gòu)
下,才會被執(zhí)行,并且支持模式匹配,例如arm*
匹配所有arm架構(gòu)。
當(dāng)然也可以只設(shè)置平臺,不設(shè)置架構(gòu),這樣就是匹配指定平臺下,執(zhí)行腳本:
target("test")
on_build("windows", function (target)
print("build for windows")
end)
<p class="tip"> 一旦對這個(gè)target目標(biāo)設(shè)置了自己的build過程,那么xmake默認(rèn)的構(gòu)建過程將不再被執(zhí)行。 </p>
覆蓋target目標(biāo)的xmake [c|clean}
的清理操作,實(shí)現(xiàn)自定義清理過程。
target("test")
-- 設(shè)置自定義清理腳本
on_clean(function (target)
-- 僅刪掉目標(biāo)文件
os.rm(target:targetfile())
end)
一些target接口描述如下:
target接口 | 描述 |
---|---|
target:name() | 獲取目標(biāo)名 |
target:targetfile() | 獲取目標(biāo)文件路徑 |
target:get("kind") | 獲取目標(biāo)的構(gòu)建類型 |
target:get("defines") | 獲取目標(biāo)的宏定義 |
target:get("xxx") | 其他通過 set_/add_ 接口設(shè)置的target信息,都可以通過此接口來獲取 |
target:add("links", "pthread") | 添加目標(biāo)設(shè)置 |
target:set("links", "pthread", "z") | 覆寫目標(biāo)設(shè)置 |
target:deps() | 獲取目標(biāo)的所有依賴目標(biāo) |
target:dep("depname") | 獲取指定的依賴目標(biāo) |
target:sourcebatches() | 獲取目標(biāo)的所有源文件列表 |
覆蓋target目標(biāo)的xmake [p|package}
的打包操作,實(shí)現(xiàn)自定義打包過程,如果你想對指定target打包成自己想要的格式,可以通過這個(gè)接口自定義它。
這個(gè)接口還是挺實(shí)用的,例如,編譯玩jni后,將生成的so,打包進(jìn)apk包中。
-- 定義一個(gè)android app的測試demo
target("demo")
-- 生成動態(tài)庫:libdemo.so
set_kind("shared")
-- 設(shè)置對象的輸出目錄,可選
set_objectdir("$(buildir)/.objs")
-- 每次編譯完的libdemo.so的生成目錄,設(shè)置為app/libs/armeabi
set_targetdir("libs/armeabi")
-- 添加jni的代碼文件
add_files("jni/*.c")
-- 設(shè)置自定義打包腳本,在使用xmake編譯完libdemo.so后,執(zhí)行xmake p進(jìn)行打包
-- 會自動使用ant將app編譯成apk文件
--
on_package(function (target)
-- 使用ant編譯app成apk文件,輸出信息重定向到日志文件
os.run("ant debug")
end)
覆蓋target目標(biāo)的xmake [i|install}
的安裝操作,實(shí)現(xiàn)自定義安裝過程。
例如,將生成的apk包,進(jìn)行安裝。
target("test")
-- 設(shè)置自定義安裝腳本,自動安裝apk文件
on_install(function (target)
-- 使用adb安裝打包生成的apk文件
os.run("adb install -r ./bin/Demo-debug.apk")
end)
覆蓋target目標(biāo)的xmake [u|uninstall}
的卸載操作,實(shí)現(xiàn)自定義卸載過程。
target("test")
on_uninstall(function (target)
...
end)
覆蓋target目標(biāo)的xmake [r|run}
的運(yùn)行操作,實(shí)現(xiàn)自定義運(yùn)行過程。
例如,運(yùn)行安裝好的apk程序:
target("test")
-- 設(shè)置自定義運(yùn)行腳本,自動運(yùn)行安裝好的app程序,并且自動獲取設(shè)備輸出信息
on_run(function (target)
os.run("adb shell am start -n com.demo/com.demo.DemoTest")
os.run("adb logcat")
end)
并不會覆蓋默認(rèn)的構(gòu)建操作,只是在構(gòu)建之前增加一些自定義的操作。
target("test")
before_build(function (target)
print("")
end)
并不會覆蓋默認(rèn)的清理操作,只是在清理之前增加一些自定義的操作。
target("test")
before_clean(function (target)
print("")
end)
并不會覆蓋默認(rèn)的打包操作,只是在打包之前增加一些自定義的操作。
target("test")
before_package(function (target)
print("")
end)
并不會覆蓋默認(rèn)的安裝操作,只是在安裝之前增加一些自定義的操作。
target("test")
before_install(function (target)
print("")
end)
并不會覆蓋默認(rèn)的卸載操作,只是在卸載之前增加一些自定義的操作。
target("test")
before_uninstall(function (target)
print("")
end)
并不會覆蓋默認(rèn)的運(yùn)行操作,只是在運(yùn)行之前增加一些自定義的操作。
target("test")
before_run(function (target)
print("")
end)
并不會覆蓋默認(rèn)的構(gòu)建操作,只是在構(gòu)建之后增加一些自定義的操作。
例如,對于ios的越獄開發(fā),構(gòu)建完程序后,需要用ldid
進(jìn)行簽名操作
target("test")
after_build(function (target)
os.run("ldid -S %s", target:targetfile())
end)
并不會覆蓋默認(rèn)的清理操作,只是在清理之后增加一些自定義的操作。
一般可用于清理編譯某target自動生成的一些額外的臨時(shí)文件,這些文件xmake默認(rèn)的清理規(guī)則可能沒有清理到,例如:
target("test")
after_clean(function (target)
os.rm("$(buildir)/otherfiles")
end)
并不會覆蓋默認(rèn)的打包操作,只是在打包之后增加一些自定義的操作。
target("test")
after_package(function (target)
print("")
end)
并不會覆蓋默認(rèn)的安裝操作,只是在安裝之后增加一些自定義的操作。
target("test")
after_install(function (target)
print("")
end)
并不會覆蓋默認(rèn)的卸載操作,只是在卸載之后增加一些自定義的操作。
target("test")
after_uninstall(function (target)
print("")
end)
并不會覆蓋默認(rèn)的運(yùn)行操作,只是在運(yùn)行之后增加一些自定義的操作。
target("test")
after_run(function (target)
print("")
end)
<p class="warning"> 2.1.5版本之后,此接口已廢棄,請使用set_config_header。 </p>
如果你想在xmake配置項(xiàng)目成功后,或者自動檢測某個(gè)選項(xiàng)通過后,把檢測的結(jié)果寫入配置頭文件,那么需要調(diào)用這個(gè)接口來啟用自動生成config.h
文件。
使用方式例如:
target("test")
-- 啟用并設(shè)置需要自動生成的config.h文件路徑
set_config_h("$(buildir)/config.h")
-- 設(shè)置自動檢測生成的宏開關(guān)的名字前綴
set_config_h_prefix("TB_CONFIG")
當(dāng)這個(gè)target中通過下面的這些接口,對這個(gè)target添加了相關(guān)的選項(xiàng)依賴、包依賴、接口依賴后,如果某依賴被啟用,那么對應(yīng)的一些宏定義配置,會自動寫入被設(shè)置的config.h
文件中去。
這些接口,其實(shí)底層都用到了option選項(xiàng)中的一些檢測設(shè)置,例如:
option("wchar")
-- 添加對wchar_t類型的檢測
add_ctypes("wchar_t")
-- 如果檢測通過,自動生成 TB_CONFIG_TYPE_HAVE_WCHAR的宏開關(guān)到config.h
add_defines_h("$(prefix)_TYPE_HAVE_WCHAR")
target("test")
-- 啟用頭文件自動生成
set_config_h("$(buildir)/config.h")
set_config_h_prefix("TB_CONFIG")
-- 添加對wchar選項(xiàng)的依賴關(guān)聯(lián),只有加上這個(gè)關(guān)聯(lián),wchar選項(xiàng)的檢測結(jié)果才會寫入指定的config.h中去
add_options("wchar")
<p class="warning"> 2.1.5版本之后,此接口已廢棄,請使用set_config_header。 </p>
具體使用見:set_config_h
如果設(shè)置了:
target("test")
set_config_h_prefix("TB_CONFIG")
那么,選項(xiàng)中add_defines_h("$(prefix)_TYPE_HAVE_WCHAR")
的$(prefix)會自動被替換成新的前綴值。
此接口是set_config_h和set_config_h_prefix的升級版本,2.1.5之后支持。
如果你想在xmake配置項(xiàng)目成功后,或者自動檢測某個(gè)選項(xiàng)通過后,把檢測的結(jié)果寫入配置頭文件,那么需要調(diào)用這個(gè)接口來啟用自動生成config.h
文件。
使用方式例如:
target("test")
set_config_header("$(buildir)/config.h", {prefix = "TB_CONFIG"})
上面的代碼,啟用并設(shè)置需要自動生成的config.h文件路徑,并且設(shè)置自動檢測生成的宏開關(guān)的名字前綴:TB_CONFIG
, 當(dāng)然這個(gè)前綴的設(shè)置是可選的。
target("test")
set_config_header("$(buildir)/config.h")
如果不設(shè)置前綴,將會自動根據(jù)target名生成一個(gè)唯一字串。
當(dāng)這個(gè)target中通過下面的這些接口,對這個(gè)target添加了相關(guān)的選項(xiàng)依賴、包依賴、接口依賴后,如果某依賴被啟用,那么對應(yīng)的一些宏定義配置,會自動寫入被設(shè)置的config.h
文件中去。
這些接口,其實(shí)底層都用到了option選項(xiàng)中的一些檢測設(shè)置,例如:
option("wchar")
-- 添加對wchar_t類型的檢測
add_ctypes("wchar_t")
-- 如果檢測通過,自動生成 TB_CONFIG_TYPE_HAVE_WCHAR的宏開關(guān)到config.h
add_defines_h("$(prefix)_TYPE_HAVE_WCHAR")
target("test")
-- 啟用頭文件自動生成
set_config_header("$(buildir)/config.h", {prefix = "TB_CONFIG"})
-- 添加對wchar選項(xiàng)的依賴關(guān)聯(lián),只有加上這個(gè)關(guān)聯(lián),wchar選項(xiàng)的檢測結(jié)果才會寫入指定的config.h中去
add_options("wchar")
xmake支持通過預(yù)編譯頭文件去加速c程序編譯,目前支持的編譯器有:gcc, clang和msvc。
使用方式如下:
target("test")
set_pcheader("header.h")
xmake支持通過預(yù)編譯頭文件去加速c++程序編譯,目前支持的編譯器有:gcc, clang和msvc。
使用方式如下:
target("test")
set_pcxxheader("header.h")
添加當(dāng)前目標(biāo)的依賴目標(biāo),編譯的時(shí)候,會去優(yōu)先編譯依賴的目標(biāo),然后再編譯當(dāng)前目標(biāo)。。。
target("test1")
set_kind("static")
set_files("*.c")
target("test2")
set_kind("static")
set_files("*.c")
target("demo")
-- 添加依賴目標(biāo):test1, test2
add_deps("test1", "test2")
-- 鏈接libtest1.a,libtest2.a
add_links("test1", "test2")
上面的例子,在編譯目標(biāo)demo的時(shí)候,需要先編譯test1, test2目標(biāo),因?yàn)閐emo會去用到他們
<p class="tip">
2.1.5版本后,target會自動繼承依賴目標(biāo)中的配置和屬性,不再需要額外調(diào)用add_links
, add_includedirs
和add_linkdirs
等接口去關(guān)聯(lián)依賴目標(biāo)了。
</p>
2.1.5版本之后,上述代碼可簡化為:
target("test1")
set_kind("static")
set_files("*.c")
target("test2")
set_kind("static")
set_files("*.c")
target("demo")
add_deps("test1", "test2") -- 會自動鏈接依賴目標(biāo)
并且繼承關(guān)系是支持級聯(lián)的,例如:
target("library1")
set_kind("static")
add_files("*.c")
add_headers("inc1/*.h")
target("library2")
set_kind("static")
add_deps("library1")
add_files("*.c")
add_headers("inc2/*.h")
target("test")
set_kind("binary")
add_deps("library2")
如果我們還是想以前那樣,并不想繼承依賴target的任何配置,如何操作呢?這個(gè)在2.1.6版本中也對其進(jìn)行了支持,通過:
add_deps("dep1", "dep2", {inherit = false})
通過顯示設(shè)置inherit配置,來告訴xmake,這兩個(gè)依賴的配置是否需要被繼承,如果不設(shè)置,默認(rèn)就是啟用繼承的。
為當(dāng)前目標(biāo)添加鏈接庫,一般這個(gè)要與add_linkdirs配對使用。
target("demo")
-- 添加對libtest.a的鏈接,相當(dāng)于 -ltest
add_links("test")
-- 添加鏈接搜索目錄
add_linkdirs("$(buildir)/lib")
用于添加目標(biāo)工程的源文件,甚至庫文件,目前支持的一些文件類型:
支持的源文件類型 | 描述 |
---|---|
.c/.cpp/.cc/.cxx | c++文件 |
.s/.S/.asm | 匯編文件 |
.m/.mm | objc文件 |
.swift | swift文件 |
.go | golang文件 |
.o/.obj | 對象文件 |
.a/.lib | 靜態(tài)庫文件,會自動合并庫到目標(biāo)程序 |
.rc | msvc的資源文件 |
其中通配符*
表示匹配當(dāng)前目錄下文件,而**
則匹配多級目錄下的文件。
例如:
add_files("src/test_*.c")
add_files("src/xxx/**.cpp")
add_files("src/asm/*.S", "src/objc/**/hello.m")
add_files
的使用其實(shí)是相當(dāng)靈活方便的,其匹配模式借鑒了premake的風(fēng)格,但是又對其進(jìn)行了改善和增強(qiáng)。
使得不僅可以匹配文件,還有可以在添加文件同時(shí),過濾排除指定模式的一批文件。
例如:
-- 遞歸添加src下的所有c文件,但是不包括src/impl/下的所有c文件
add_files("src/**.c|impl/*.c")
-- 添加src下的所有cpp文件,但是不包括src/test.cpp、src/hello.cpp以及src下所有帶xx_前綴的cpp文件
add_files("src/*.cpp|test.cpp|hello.cpp|xx_*.cpp")
其中分隔符|
之后的都是需要排除的文件,這些文件也同樣支持匹配模式,并且可以同時(shí)添加多個(gè)過濾模式,只要中間用|
分割就行了。。
添加文件的時(shí)候支持過濾一些文件的一個(gè)好處就是,可以為后續(xù)根據(jù)不同開關(guān)邏輯添加文件提供基礎(chǔ)。
<p class="tip">
為了使得描述上更加的精簡,|
之后的過濾描述都是基于起一個(gè)模式:src/*.cpp
中*
之前的目錄為基礎(chǔ)的。
所以上面的例子后面過濾的都是在src下的文件,這個(gè)是要注意的。
</p>
2.1.6版本之后,對add_files
進(jìn)行了改進(jìn),支持基于files更細(xì)粒度的編譯選項(xiàng)控制,例如:
target("test")
add_defines("TEST1")
add_files("src/*.c")
add_files("test/*.c", "test2/test2.c", {defines = "TEST2", languages = "c99", includedirs = ".", cflags = "-O0"})
可以在add_files
的最后一個(gè)參數(shù),傳入一個(gè)配置table,去控制指定files的編譯選項(xiàng),里面的配置參數(shù)跟target的一致,并且這些文件還會繼承target的通用配置-DTEST1
。
安裝指定的頭文件到build目錄,如果設(shè)置了set_headerdir, 則輸出到指定目錄。
安裝規(guī)則的語法跟add_files類似,例如:
-- 安裝tbox目錄下所有的頭文件(忽略impl目錄下的文件),并且按()指定部分作為相對路徑,進(jìn)行安裝
add_headers("../(tbox/**.h)|**/impl/**.h")
設(shè)置鏈接庫的搜索目錄,這個(gè)接口的使用方式如下:
target("test")
add_linkdirs("$(buildir)/lib")
此接口相當(dāng)于gcc的-Lxxx
鏈接選項(xiàng)。
一般他是與add_links配合使用的,當(dāng)然也可以直接通過add_ldflags或者add_shflags接口來添加,也是可以的。
<p class="tip">
如果不想在工程中寫死,可以通過:xmake f --linkdirs=xxx
或者xmake f --ldflags="-L/xxx"
的方式來設(shè)置,當(dāng)然這種手動設(shè)置的目錄搜索優(yōu)先級更高。
</p>
通過add_linkdirs設(shè)置動態(tài)庫的鏈接搜索目錄后,程序被正常鏈接,但是在linux平臺想要正常運(yùn)行編譯后的程序,會報(bào)加載動態(tài)庫失敗。
因?yàn)闆]找到動態(tài)庫的加載目錄,想要正常運(yùn)行依賴動態(tài)庫的程序,需要設(shè)置LD_LIBRARY_PATH
環(huán)境變量,指定需要加載的動態(tài)庫目錄。
但是這種方式是全局的,影響太廣,更好的方式是通過-rpath=xxx
的鏈接器選項(xiàng),在鏈接程序的時(shí)候設(shè)置好需要加載的動態(tài)庫搜索路徑,而xmake對其進(jìn)行了封裝,通過add_rpathdirs
更好的處理跨平臺問題。
具體使用如下:
target("test")
set_kind("binary")
add_linkdirs("$(buildir)/lib")
add_rpathdirs("$(buildir)/lib")
只需要在鏈接的時(shí)候,在設(shè)置下rpath目錄就好了,雖然也可以通過add_ldflags("-Wl,-rpath=xxx")
達(dá)到相同的目的,但是這個(gè)接口更加通用。
內(nèi)部會對不同平臺進(jìn)行處理,像在macOS下,是不需要-rpath
設(shè)置的,也是可以正常加載運(yùn)行程序,因此針對這個(gè)平臺,xmake內(nèi)部會直接忽略器設(shè)置,避免鏈接報(bào)錯(cuò)。
而在為dlang程序進(jìn)行動態(tài)庫鏈接時(shí),xmake會自動處理成-L-rpath=xxx
來傳入dlang的鏈接器,這樣就避免了直接使用add_ldflags
需要自己判斷和處理不同平臺和編譯器問題。
2.1.7版本對這個(gè)接口進(jìn)行了改進(jìn),支持:@loader_path
, @executable_path
和 $ORIGIN
的內(nèi)置變量,來指定程序的加載目錄,它們的效果基本上是一樣的,主要是為了同時(shí)兼容macho, elf。
例如:
target("test")
set_kind("binary")
add_linkdirs("$(buildir)/lib")
add_rpathdirs("@loader_path/lib")
指定test程序加載當(dāng)前執(zhí)行目錄下lib/*.[so|dylib]
的動態(tài)庫文件,這將有助于提升程序的可移植性,不用寫死絕對路徑和相對路徑,導(dǎo)致程序和目錄切換引起程序加載動態(tài)庫失敗。
設(shè)置頭文件的搜索目錄,這個(gè)接口的使用方式如下:
target("test")
add_includedirs("$(buildir)/include")
當(dāng)然也可以直接通過add_cxflags或者add_mxflags等接口來設(shè)置,也是可以的。
<p class="tip">
如果不想在工程中寫死,可以通過:xmake f --includedirs=xxx
或者xmake f --cxflags="-I/xxx"
的方式來設(shè)置,當(dāng)然這種手動設(shè)置的目錄搜索優(yōu)先級更高。
</p>
add_defines("DEBUG", "TEST=0", "TEST2=\"hello\"")
相當(dāng)于設(shè)置了編譯選項(xiàng):
-DDEBUG -DTEST=0 -DTEST2=\"hello\"
add_undefines("DEBUG")
相當(dāng)于設(shè)置了編譯選項(xiàng):-UDEBUG
在代碼中相當(dāng)于:#undef DEBUG
添加宏定義到config.h
配置文件,config.h
的設(shè)置,可參考set_config_h接口。
在config.h
配置文件中通過undef
禁用宏定義,config.h
的設(shè)置,可參考set_config_h接口。
僅對c代碼添加編譯選項(xiàng)
add_cflags("-g", "-O2", "-DDEBUG")
<p class="warning"> 所有選項(xiàng)值都基于gcc的定義為標(biāo)準(zhǔn),如果其他編譯器不兼容(例如:vc),xmake會自動內(nèi)部將其轉(zhuǎn)換成對應(yīng)編譯器支持的選項(xiàng)值。 用戶無需操心其兼容性,如果其他編譯器沒有對應(yīng)的匹配值,那么xmake會自動忽略器設(shè)置。 </p>
同時(shí)對c/c++代碼添加編譯選項(xiàng)
僅對c++代碼添加編譯選項(xiàng)
僅對objc代碼添加編譯選項(xiàng)
add_mflags("-g", "-O2", "-DDEBUG")
同時(shí)對objc/objc++代碼添加編譯選項(xiàng)
add_mxflags("-framework CoreFoundation")
僅對objc++代碼添加編譯選項(xiàng)
add_mxxflags("-framework CoreFoundation")
對swift代碼添加編譯選項(xiàng)
add_scflags("xxx")
對匯編代碼添加編譯選項(xiàng)
add_asflags("xxx")
對golang代碼添加編譯選項(xiàng)
add_gcflags("xxx")
對dlang代碼添加編譯選項(xiàng)
add_dcflags("xxx")
對rust代碼添加編譯選項(xiàng)
add_rcflags("xxx")
添加靜態(tài)鏈接庫選項(xiàng)
add_ldflags("-L/xxx", "-lxxx")
影響對靜態(tài)庫的生成
add_arflags("xxx")
影響對動態(tài)庫的生成
add_shflags("xxx")
與add_cfuncs類似,只是僅對單個(gè)函數(shù)接口進(jìn)行設(shè)置,并且僅對target
域生效,option
中不存在此接口。
此接口的目的主要是為了在config.h
中更加高度定制化的生成宏開關(guān),例如:
target("demo")
-- 設(shè)置和啟用config.h
set_config_h("$(buildir)/config.h")
set_config_h_prefix("TEST")
-- 僅通過參數(shù)一設(shè)置模塊名前綴
add_cfunc("libc", nil, nil, {"sys/select.h"}, "select")
-- 通過參數(shù)三,設(shè)置同時(shí)檢測鏈接庫:libpthread.a
add_cfunc("pthread", nil, "pthread", "pthread.h", "pthread_create")
-- 通過參數(shù)二設(shè)置接口別名
add_cfunc(nil, "PTHREAD", nil, "pthread.h", "pthread_create")
生成的結(jié)果如下:
#ifndef TEST_H
#define TEST_H
// 宏命名規(guī)則:$(prefix)前綴 _ 模塊名(如果非nil)_ HAVE _ 接口名或者別名 (大寫)
#define TEST_LIBC_HAVE_SELECT 1
#define TEST_PTHREAD_HAVE_PTHREAD_CREATE 1
#define TEST_HAVE_PTHREAD 1
#endif
如果要更加靈活的函數(shù)檢測,可以通過lib.detect.has_cfuncs在自定義腳本中實(shí)現(xiàn)。
與add_cfunc類似,只是檢測的函數(shù)接口是c++函數(shù)。
<p class="warning">
此接口是target
和option
共用的接口,但是接口行為稍有不同。
</p>
接口域 | 描述 | 例子 |
---|---|---|
target | 頭文件、鏈接庫和函數(shù)接口同時(shí)指定 | add_cfuncs("libc", nil, {"signal.h", "setjmp.h"}, "signal", "setjmp", "sigsetjmp{sigjmp_buf buf; sigsetjmp(buf, 0);}", "kill") |
option | 僅指定函數(shù)接口,頭文件依賴add_cincludes等獨(dú)立接口 | add_cincludes("setjmp.h") add_cfuncs("sigsetjmp") |
對于option
,這個(gè)接口的使用很簡單,跟add_cincludes類似,例如:
option("setjmp")
set_default(false)
add_cincludes("setjmp.h")
add_cfuncs("sigsetjmp", "setjmp")
add_defines("HAVE_SETJMP")
target("test")
add_options("setjmp")
此選項(xiàng)檢測是否存在setjmp
的一些接口,如果檢測通過那么test
目標(biāo)程序?qū)由?code>HAVE_SETJMP的宏定義。
<p class="warning">
需要注意的是,在option
中使用此接口檢測依賴函數(shù),需要同時(shí)使用獨(dú)立的add_cincludes增加頭文件搜索路徑,指定add_links鏈接庫(可選),否則檢測不到指定函數(shù)。
<br><br>
并且某些頭文件接口是通過宏開關(guān)分別定義的,那么檢測的時(shí)候最好通過add_defines帶上依賴的宏開關(guān)。
</p>
對于target
,此接口可以同時(shí)設(shè)置:依賴的頭文件、依賴的鏈接模塊、依賴的函數(shù)接口,保證檢測環(huán)境的完整性,例如:
target("test")
-- 添加libc庫接口相關(guān)檢測
-- 第一個(gè)參數(shù):模塊名,用于最后的宏定義前綴生成
-- 第二個(gè)參數(shù):鏈接庫
-- 第三個(gè)參數(shù):頭文件
-- 之后的都是函數(shù)接口列表
add_cfuncs("libc", nil, {"signal.h", "setjmp.h"}, "signal", "setjmp", "sigsetjmp{sigjmp_buf buf; sigsetjmp(buf, 0);}", "kill")
-- 添加pthread庫接口相關(guān)檢測,同時(shí)指定需要檢測`libpthread.a`鏈接庫是否存在
add_cfuncs("posix", "pthread", "pthread.h", "pthread_mutex_init",
"pthread_create",
"pthread_setspecific",
"pthread_getspecific",
"pthread_key_create",
"pthread_key_delete")
設(shè)置test
目標(biāo),依賴這些接口,構(gòu)建時(shí)會預(yù)先檢測他們,并且如果通過set_config_h接口設(shè)置的自動生成頭文件:config.h
那么,檢測結(jié)果會自動加到對應(yīng)的config.h
上去,這也是option
沒有的功能,例如:
#define TB_CONFIG_LIBC_HAVE_SIGNAL 1
#define TB_CONFIG_LIBC_HAVE_SETJMP 1
#define TB_CONFIG_LIBC_HAVE_SIGSETJMP 1
#define TB_CONFIG_LIBC_HAVE_KILL 1
#define TB_CONFIG_POSIX_HAVE_PTHREAD_MUTEX_INIT 1
#define TB_CONFIG_POSIX_HAVE_PTHREAD_CREATE 1
#define TB_CONFIG_POSIX_HAVE_PTHREAD_SETSPECIFIC 1
#define TB_CONFIG_POSIX_HAVE_PTHREAD_GETSPECIFIC 1
#define TB_CONFIG_POSIX_HAVE_PTHREAD_KEY_CREATE 1
#define TB_CONFIG_POSIX_HAVE_PTHREAD_KEY_DELETE 1
由于,不同頭文件中,函數(shù)的定義方式不完全相同,例如:宏函數(shù)、靜態(tài)內(nèi)聯(lián)函數(shù)、extern函數(shù)等。
要想完全檢測成功,檢測語法上需要一定程度的靈活性,下面是一些語法規(guī)則:
檢測語法 | 例子 |
---|---|
純函數(shù)名 | sigsetjmp |
單行調(diào)用 | sigsetjmp((void*)0, 0) |
函數(shù)塊調(diào)用 | sigsetjmp{sigsetjmp((void*)0, 0);} |
函數(shù)塊 + 變量 | sigsetjmp{int a = 0; sigsetjmp((void*)a, a);} |
與add_cfuncs類似,只是檢測的函數(shù)接口是c++函數(shù)。
這個(gè)接口跟set_options類似,唯一的區(qū)別就是,此處是追加選項(xiàng),而set_options每次設(shè)置會覆蓋先前的設(shè)置。
在target作用域中,添加集成包依賴,例如:
target("test")
add_packages("zlib", "polarssl", "pcre", "mysql")
這樣,在編譯test目標(biāo)時(shí),如果這個(gè)包存在的,將會自動追加包里面的宏定義、頭文件搜索路徑、鏈接庫目錄,也會自動鏈接包中所有庫。
用戶不再需要自己單獨(dú)調(diào)用add_links,add_includedirs, add_ldflags等接口,來配置依賴庫鏈接了。
對于如何設(shè)置包搜索目錄,可參考:add_packagedirs 接口
與set_languages類似,唯一區(qū)別是這個(gè)接口不會覆蓋掉之前的設(shè)置,而是追加設(shè)置。
添加擴(kuò)展指令優(yōu)化選項(xiàng),目前支持以下幾種擴(kuò)展指令集:
add_vectorexts("mmx")
add_vectorexts("neon")
add_vectorexts("avx", "avx2")
add_vectorexts("sse", "sse2", "sse3", "ssse3")
<p class="tip"> 如果當(dāng)前設(shè)置的指令集編譯器不支持,xmake會自動忽略掉,所以不需要用戶手動去判斷維護(hù),只需要將你需要的指令集全部設(shè)置上就行了。 </p>
目前主要用于ios
和macosx
平臺的objc
和swift
程序,例如:
target("test")
add_frameworks("Foundation", "CoreFoundation")
當(dāng)然也可以使用add_mxflags和add_ldflags來設(shè)置,不過比較繁瑣,不建議這樣設(shè)置。
target("test")
add_mxflags("-framework Foundation", "-framework CoreFoundation")
add_ldflags("-framework Foundation", "-framework CoreFoundation")
如果不是這兩個(gè)平臺,這些設(shè)置將會被忽略。
對于一些第三方framework,那么僅僅通過add_frameworks是沒法找到的,還需要通過這個(gè)接口來添加搜索目錄。
target("test")
add_frameworks("MyFramework")
add_frameworkdirs("/tmp/frameworkdir", "/tmp/frameworkdir2")
定義和設(shè)置選項(xiàng)開關(guān),每個(gè)option
對應(yīng)一個(gè)選項(xiàng),可用于自定義編譯配置選項(xiàng)、開關(guān)設(shè)置。
<p class="tip">
除了target
以外的所有域接口,例如option
,task
等的接口,默認(rèn)不能放置在外面的全局作用域中的(除非部分跟target共用的接口除外)。
如果要設(shè)置值影響所有option
,task
等選項(xiàng),可以通過匿名全局域來設(shè)置。
</p>
例如:
-- 進(jìn)入option的匿名全局域,里面的設(shè)置會同時(shí)影響test和test2選項(xiàng)
option()
add_defines("DEBUG")
option("test")
-- ...
-- 盡量保持縮進(jìn),因?yàn)檫@個(gè)之后的所有設(shè)置,都是針對test選項(xiàng)的
option("test2")
-- ...
<p class="tip">
option
域是可以重復(fù)進(jìn)入來實(shí)現(xiàn)分離設(shè)置的,如果要顯示離開當(dāng)前選項(xiàng)的作用域設(shè)置,可以手動調(diào)用option_end接口。
</p>
接口 | 描述 | 支持版本 |
---|---|---|
option | 定義選項(xiàng) | >= 2.0.1 |
option_end | 結(jié)束定義選項(xiàng) | >= 2.1.1 |
add_deps | 添加選項(xiàng)依賴 | >= 2.1.5 |
before_check | 選項(xiàng)檢測之前執(zhí)行此腳本 | >= 2.1.5 |
on_check | 自定義選項(xiàng)檢測腳本 | >= 2.1.5 |
after_check | 選項(xiàng)檢測之后執(zhí)行此腳本 | >= 2.1.5 |
set_default | 設(shè)置默認(rèn)值 | >= 2.0.1 |
set_showmenu | 設(shè)置是否啟用菜單顯示 | >= 1.0.1 |
set_category | 設(shè)置選項(xiàng)分類,僅用于菜單顯示 | >= 1.0.1 |
set_description | 設(shè)置菜單顯示描述 | >= 1.0.1 |
add_links | 添加鏈接庫檢測 | >= 1.0.1 |
add_linkdirs | 添加鏈接庫檢測需要的搜索目錄 | >= 1.0.1 |
add_rpathdirs | 添加運(yùn)行時(shí)候動態(tài)鏈接庫搜索目錄 | >= 2.1.3 |
add_cincludes | 添加c頭文件檢測 | >= 1.0.1 |
add_cxxincludes | 添加c++頭文件檢測 | >= 1.0.1 |
add_ctypes | 添加c類型檢測 | >= 1.0.1 |
add_cxxtypes | 添加c++類型檢測 | >= 1.0.1 |
add_csnippet | 添加c代碼片段檢測 | >= 2.1.5 |
add_cxxsnippet | 添加c++代碼片段檢測 | >= 2.1.5 |
set_warnings | 設(shè)置警告級別 | >= 1.0.1 |
set_optimize | 設(shè)置優(yōu)化級別 | >= 1.0.1 |
set_languages | 設(shè)置代碼語言標(biāo)準(zhǔn) | >= 1.0.1 |
add_includedirs | 添加頭文件搜索目錄 | >= 1.0.1 |
add_defines | 添加宏定義 | >= 1.0.1 |
add_undefines | 取消宏定義 | >= 1.0.1 |
add_defines_h | 添加宏定義到頭文件 | >= 1.0.1 |
add_undefines_h | 取消宏定義到頭文件 | >= 1.0.1 |
add_cflags | 添加c編譯選項(xiàng) | >= 1.0.1 |
add_cxflags | 添加c/c++編譯選項(xiàng) | >= 1.0.1 |
add_cxxflags | 添加c++編譯選項(xiàng) | >= 1.0.1 |
add_mflags | 添加objc編譯選項(xiàng) | >= 2.0.1 |
add_mxflags | 添加objc/objc++編譯選項(xiàng) | >= 2.0.1 |
add_mxxflags | 添加objc++編譯選項(xiàng) | >= 2.0.1 |
add_scflags | 添加swift編譯選項(xiàng) | >= 2.1.1 |
add_asflags | 添加匯編編譯選項(xiàng) | >= 2.1.1 |
add_gcflags | 添加go編譯選項(xiàng) | >= 2.1.1 |
add_dcflags | 添加dlang編譯選項(xiàng) | >= 2.1.1 |
add_rcflags | 添加rust編譯選項(xiàng) | >= 2.1.1 |
add_ldflags | 添加鏈接選項(xiàng) | >= 2.1.1 |
add_arflags | 添加靜態(tài)庫歸檔選項(xiàng) | >= 2.1.1 |
add_shflags | 添加動態(tài)庫鏈接選項(xiàng) | >= 2.0.1 |
add_cfuncs | 添加c庫函數(shù)檢測 | >= 1.0.1 |
add_cxxfuncs | 添加c++庫函數(shù)接口 | >= 1.0.1 |
add_languages | 添加語言標(biāo)準(zhǔn) | >= 2.0.1 |
add_vectorexts | 添加向量擴(kuò)展指令 | >= 2.0.1 |
add_frameworks | 添加鏈接框架 | >= 2.1.1 |
add_frameworkdirs | 添加鏈接框架 | >= 2.1.5 |
廢棄接口 | 描述 | 支持版本 |
---|---|---|
add_bindings | 添加正向關(guān)聯(lián)選項(xiàng),同步啟用和禁用 | >= 2.0.1 < 2.1.5 |
add_rbindings | 添加逆向關(guān)聯(lián)選項(xiàng),同步啟用和禁用 | >= 2.0.1 < 2.1.5 |
add_defines_if_ok | 如果檢測選項(xiàng)通過,則添加宏定義 | >= 1.0.1 < 2.1.5 |
add_defines_h_if_ok | 如果檢測選項(xiàng)通過,則添加宏定義到配置頭文件 | >= 1.0.1 < 2.1.5 |
add_undefines_if_ok | 如果檢測選項(xiàng)通過,則取消宏定義 | >= 1.0.1 < 2.1.5 |
add_undefines_h_if_ok | 如果檢測選項(xiàng)通過,則在配置頭文件中取消宏定義 | >= 1.0.1 < 2.1.5 |
定義和設(shè)置選項(xiàng)開關(guān),可用于自定義編譯配置選項(xiàng)、開關(guān)設(shè)置。
例如,定義一個(gè)是否啟用test的選項(xiàng):
option("test")
set_default(false)
set_showmenu(true)
add_defines("-DTEST")
然后關(guān)聯(lián)到指定的target中去:
target("demo")
add_options("test")
這樣,一個(gè)選項(xiàng)就算定義好了,如果這個(gè)選項(xiàng)被啟用,那么編譯這個(gè)target的時(shí)候,就會自動加上-DTEST
的宏定義。
## 手動啟用這個(gè)選項(xiàng)
$ xmake f --test=y
$ xmake
這是一個(gè)可選api,顯示離開選項(xiàng)作用域,用法和target_end類似。
通過設(shè)置依賴,可以調(diào)整選項(xiàng)的檢測順序,一般用于on_check等檢測腳本的調(diào)用時(shí)機(jī)。
option("small")
set_default(true)
on_check(function (option)
-- ...
end)
option("test")
add_deps("small")
set_default(true)
on_check(function (option)
if option:dep("small"):enabled() then
option:enable(false)
end
end)
當(dāng)依賴的small選項(xiàng)檢測完成后,通過判斷small選項(xiàng)的狀態(tài),來控制test的選項(xiàng)狀態(tài)。
例如:在檢測之前,通過find_package來查找包,將links
, includedirs
和linkdirs
等信息添加到option中去,
然后開始選項(xiàng)檢測,通過后就會自動鏈接到target上。
option("zlib")
before_check(function (option)
import("lib.detect.find_package")
option:add(find_package("zlib"))
end)
此腳本會覆蓋內(nèi)置的選項(xiàng)檢測邏輯。
option("test")
add_deps("small")
set_default(true)
on_check(function (option)
if option:dep("small"):enabled() then
option:enable(false)
end
end)
如果test依賴的選項(xiàng)通過,則禁用test選項(xiàng)。
在選項(xiàng)檢測完成后,執(zhí)行此腳本做一些后期處理,也可以在此時(shí)重新禁用選項(xiàng):
option("test")
add_deps("small")
add_links("pthread")
after_check(function (option)
option:enable(false)
end)
在沒有通過xmake f --option=[y|n}
等命令修改選項(xiàng)值的時(shí)候,這個(gè)選項(xiàng)本身也是有個(gè)默認(rèn)值的,可以通過這個(gè)接口來設(shè)置:
option("test")
-- 默認(rèn)禁用這個(gè)選項(xiàng)
set_default(false)
選項(xiàng)的值不僅支持boolean類型,也可以是字符串類型,例如:
option("test")
set_default("value")
值類型 | 描述 | 配置 |
---|---|---|
boolean | 一般用作參數(shù)開關(guān),值范圍:true/false |
xmake f --optionname=[y/n/yes/no/true/false] |
string | 可以是任意字符串,一般用于模式判斷 | xmake f --optionname=value |
如果是boolean
值的選項(xiàng),可以通過is_option來進(jìn)行判斷,選項(xiàng)是否被啟用。
如果是string
類型的選項(xiàng),可以在內(nèi)建變量中直接使用,例如:
-- 定義一個(gè)路徑配置選項(xiàng),默認(rèn)使用臨時(shí)目錄
option("rootdir")
set_default("$(tmpdir)")
set_showmenu(true)
target("test")
-- 添加指定選項(xiàng)目錄中的源文件
add_files("$(rootdir)/*.c")
其中,$(rootdir)
就是自定義的選項(xiàng)內(nèi)建變量,通過手動配置,可以動態(tài)修改它的值:
$ xmake f --rootdir=~/projectdir/src
$ xmake
給這個(gè)rootdir
選項(xiàng)指定一個(gè)其他的源碼目錄路徑,然后編譯。
選項(xiàng)的檢測行為:
default值 | 檢測行為 |
---|---|
沒有設(shè)置 | 優(yōu)先手動配置修改,默認(rèn)禁用,否則自動檢測,可根據(jù)手動傳入的值類型,自動切換boolean和string類型 |
false | 開關(guān)選項(xiàng),不自動檢測,默認(rèn)禁用,可手動配置修改 |
true | 開關(guān)選項(xiàng),不自動檢測,默認(rèn)啟用,可手動配置修改 |
string類型 | 無開關(guān)狀態(tài),不自動檢測,可手動配置修改,一般用于配置變量傳遞 |
如果設(shè)置為true
,那么在xmake f --help
里面就會出現(xiàn)這個(gè)選項(xiàng),也就能通過xmake f --optionname=xxx
進(jìn)行配置,否則只能在xmake.lua
內(nèi)部使用,無法手動配置修改。
option("test")
set_showmenu(true)
設(shè)置為啟用菜單后,執(zhí)行xmake f --help
可以看到,幫助菜單里面多了一項(xiàng):
Options:
...
--test=TEST
這個(gè)是個(gè)可選配置,僅用于在幫助菜單中,進(jìn)行分類顯示選項(xiàng),同一類別的選項(xiàng),會在同一個(gè)分組里面顯示,這樣菜單看起來更加的美觀。
例如:
option("test1")
set_showmenu(true)
set_category("test")
option("test2")
set_showmenu(true)
set_category("test")
option("demo1")
set_showmenu(true)
set_category("demo")
option("demo2")
set_showmenu(true)
set_category("demo")
這里四個(gè)選項(xiàng)分別歸類于兩個(gè)分組:test
和demo
,那么顯示的布局類似這樣:
Options:
...
--test1=TEST1
--test2=TEST2
--demo1=DEMO1
--demo2=DEMO2
這個(gè)接口,僅僅是為了調(diào)整顯示布局,更加美觀而已,沒其他用途。
設(shè)置選項(xiàng)菜單顯示時(shí),右邊的描述信息,用于幫助用戶更加清楚的知道這個(gè)選項(xiàng)的用途,例如:
option("test")
set_default(false)
set_showmenu(true)
set_description("Enable or disable test")
生成的菜單內(nèi)容如下:
Options:
...
--test=TEST Enable or disable test (default: false)
這個(gè)接口也支持多行顯示,輸出更加詳細(xì)的描述信息,例如:
option("mode")
set_default("debug")
set_showmenu(true)
set_description("Set build mode"
" - debug"
" - release"
" - profile")
生成的菜單內(nèi)容如下:
Options:
...
--mode=MODE Set build mode (default: debug)
- debug
- release
- profile
看到這個(gè)菜單,用戶就能清楚地知道,定義的這個(gè)mode
選項(xiàng)的具體用處,以及如何使用了:
$ xmake f --mode=release
<p class="tip"> 2.1.5版本之后已廢棄,請用add_deps, on_check, after_check等接口代替。 </p>
綁定關(guān)聯(lián)選項(xiàng),例如我想在命令行中配置一個(gè)smallest
的參數(shù):xmake f --smallest=y
這個(gè)時(shí)候,需要同時(shí)禁用多個(gè)其他的選項(xiàng)開關(guān),來禁止編譯多個(gè)模塊,就是這個(gè)需求,相當(dāng)于一個(gè)選項(xiàng) 與其他 多個(gè)選項(xiàng)之間 是有聯(lián)動效應(yīng)的。
而這個(gè)接口就是用來設(shè)置需要正向綁定的一些關(guān)聯(lián)選項(xiàng),例如:
-- 定義選項(xiàng)開關(guān): --smallest=y|n
option("smallest")
-- 添加正向綁定,如果smallest被啟用,下面的所有選項(xiàng)開關(guān)也會同步被啟用
add_bindings("nozip", "noxml", "nojson")
<p class="tip"> 2.1.5版本之后已廢棄,請用add_deps, on_check, after_check等接口代替。 </p>
逆向綁定關(guān)聯(lián)選項(xiàng),被關(guān)聯(lián)選項(xiàng)的開關(guān)狀態(tài)是相反的。
-- 定義選項(xiàng)開關(guān): --smallest=y|n
option("smallest")
-- 添加反向綁定,如果smallest被啟用,下面的所有模塊全部禁用
add_rbindings("xml", "zip", "asio", "regex", "object", "thread", "network", "charset", "database")
add_rbindings("zlib", "mysql", "sqlite3", "openssl", "polarssl", "pcre2", "pcre", "base")
<p class="warning"> 需要注意的是,命令行配置是有順序的,你可以先通過啟用smallest禁用所有模塊,然后添加其他選項(xiàng),逐一啟用。 </p>
例如:
-- 禁用所有模塊,然后僅僅啟用xml和zip模塊
$ xmake f --smallest=y --xml=y --zip=y
如果指定的鏈接庫檢測通過,此選項(xiàng)將被啟用,并且對應(yīng)關(guān)聯(lián)的target會自動加上此鏈接,例如:
option("pthread")
set_default(false)
add_links("pthread")
add_linkdirs("/usr/local/lib")
target("test")
add_options("pthread")
如果檢測通過,test
目標(biāo)編譯的時(shí)候就會自動加上:-L/usr/local/lib -lpthread
編譯選項(xiàng)
這個(gè)是可選的,一般系統(tǒng)庫不需要加這個(gè),也能檢測通過,如果確實(shí)沒找到,可以自己追加搜索目錄,提高檢測通過率。具體使用見:add_links
在選項(xiàng)通過檢測后,會自動添加到對應(yīng)的target上去,具體使用見:target.add_rpathdirs。
如果c頭文件檢測通過,此選項(xiàng)將被啟用,例如:
option("pthread")
set_default(false)
add_cincludes("pthread.h")
add_defines("ENABLE_PTHREAD")
target("test")
add_options("pthread")
此選項(xiàng)檢測是否存在pthread.h
的頭文件,如果檢測通過那么test
目標(biāo)程序?qū)由?code>ENABLE_PTHREAD的宏定義。
如果想要更加靈活的檢測,可以通過lib.detect.has_cincludes在option.on_check中去實(shí)現(xiàn)。
與add_cincludes類似,只是檢測的頭文件類型是c++頭文件。
如果c類型檢測通過,此選項(xiàng)將被啟用,例如:
option("wchar")
set_default(false)
add_cincludes("wchar_t")
add_defines("HAVE_WCHAR")
target("test")
add_options("wchar")
此選項(xiàng)檢測是否存在wchar_t
的類型,如果檢測通過那么test
目標(biāo)程序?qū)由?code>HAVE_WCHAR的宏定義。
如果想要更加靈活的檢測,可以通過lib.detect.has_ctypes在option.on_check中去實(shí)現(xiàn)。
與add_ctypes類似,只是檢測的類型是c++類型。
如果現(xiàn)有的add_ctypes, add_cfuncs等不能滿足當(dāng)前的檢測需求, 可以用這個(gè)接口實(shí)現(xiàn)更加定制化檢測一些編譯器特性檢測,具體見: add_cxxsnippet。
可以用這個(gè)接口實(shí)現(xiàn)更加定制化檢測一些編譯器特性檢測,尤其是c++的各種特性的檢測支持,例如:
option("constexpr")
add_cxxsnippet("constexpr int f(int x) { int sum=0; for (int i=0; i<=x; ++i) sum += i; return sum; } constexpr int x = f(5); static_assert(x == 15);")
上述代碼,實(shí)現(xiàn)對c++的constexpr特性的檢測,如果檢測通過,則啟用constexpr選項(xiàng),當(dāng)然這里只是個(gè)例子。
對于編譯器特性的檢測,有更加方便高效的檢測模塊,提供更強(qiáng)大的檢測支持,具體見:compiler.has_features和detect.check_cxsnippets
如果想要更加靈活的檢測,可以通過lib.detect.check_cxsnippets在option.on_check中去實(shí)現(xiàn)。
<p class="tip"> 2.1.5版本之后已廢棄,請用add_defines接口代替。 </p>
檢測選項(xiàng)通過后才會被設(shè)置,具體使用見add_cincludes中的例子。
<p class="tip"> 2.1.5版本之后已廢棄,請用add_defines_h接口代替。 </p>
跟add_defines_if_ok類似,只是檢測通過后,會在config.h
頭文件中自動加上被設(shè)置的宏定義。
例如:
option("pthread")
set_default(false)
add_cincludes("pthread.h")
add_defines_h_if_ok("ENABLE_PTHREAD")
target("test")
add_options("pthread")
通過后,會在config.h
中加上:
#define ENABLE_PTHREAD 1
具體config.h
如何設(shè)置,見:set_config_h
<p class="tip"> 2.1.5版本之后已廢棄,請用add_undefines接口代替。 </p>
跟add_defines_if_ok類似,只是檢測通過后,取消被設(shè)置的宏定義。
<p class="tip"> 2.1.5版本之后已廢棄,請用add_undefines_h接口代替。 </p>
跟add_defines_h_if_ok類似,只是檢測通過后,會在config.h
中取消被設(shè)置的宏定義。
#undef DEFINED_MACRO
具體config.h
如何設(shè)置,見:set_config_h
xmake可以實(shí)現(xiàn)自定義任務(wù)或者插件,其兩者的核心就是task
任務(wù),其兩者實(shí)際上是一樣的,xmake的插件都是用task
實(shí)現(xiàn)的。
本質(zhì)上都是任務(wù),只是set_category分類不同而已。
接口 | 描述 | 支持版本 |
---|---|---|
task | 定義插件或者任務(wù) | >= 2.0.1 |
task_end | 結(jié)束定義插件或任務(wù) | >= 2.1.1 |
set_menu | 設(shè)置任務(wù)菜單 | >= 2.0.1 |
set_category | 設(shè)置任務(wù)類別 | >= 2.0.1 |
on_run | 設(shè)置任務(wù)運(yùn)行腳本 | >= 2.0.1 |
task
域用于描述一個(gè)自定義的任務(wù)實(shí)現(xiàn),與target和option同級。
例如,這里定義一個(gè)最簡單的任務(wù):
task("hello")
-- 設(shè)置運(yùn)行腳本
on_run(function ()
print("hello xmake!")
end)
這個(gè)任務(wù)只需要打印hello xmake!
,那如何來運(yùn)行呢?
由于這里沒有使用set_menu設(shè)置菜單,因此這個(gè)任務(wù)只能再xmake.lua
的自定義腳本或者其他任務(wù)內(nèi)部調(diào)用,例如:
target("test")
after_build(function (target)
-- 導(dǎo)入task模塊
import("core.project.task")
-- 運(yùn)行hello任務(wù)
task.run("hello")
end)
在構(gòu)建完test
目標(biāo)后運(yùn)行hello
任務(wù)。
這是一個(gè)可選api,顯示離開選項(xiàng)作用域,用法和target_end類似。
通過設(shè)置一個(gè)菜單,這個(gè)任務(wù)就可以開放給用戶自己通過命令行手動調(diào)用,菜單的設(shè)置如下:
task("echo")
-- 設(shè)置運(yùn)行腳本
on_run(function ()
-- 導(dǎo)入?yún)?shù)選項(xiàng)模塊
import("core.base.option")
-- 初始化顏色模式
local modes = ""
for _, mode in ipairs({"bright", "dim", "blink", "reverse"}) do
if option.get(mode) then
modes = modes .. " " .. mode
end
end
-- 獲取參數(shù)內(nèi)容并且顯示信息
cprint("${%s%s}%s", option.get("color"), modes, table.concat(option.get("contents") or {}, " "))
end)
-- 設(shè)置插件的命令行選項(xiàng),這里沒有任何參數(shù)選項(xiàng),僅僅顯示插件描述
set_menu {
-- 設(shè)置菜單用法
usage = "xmake echo [options]"
-- 設(shè)置菜單描述
, description = "Echo the given info!"
-- 設(shè)置菜單選項(xiàng),如果沒有選項(xiàng),可以設(shè)置為{}
, options =
{
-- 設(shè)置k模式作為key-only型bool參數(shù)
{'b', "bright", "k", nil, "Enable bright." }
, {'d', "dim", "k", nil, "Enable dim." }
, {'-', "blink", "k", nil, "Enable blink." }
, {'r', "reverse", "k", nil, "Reverse color." }
-- 菜單顯示時(shí),空白一行
, {}
-- 設(shè)置kv作為key-value型參數(shù),并且設(shè)置默認(rèn)值:black
, {'c', "color", "kv", "black", "Set the output color."
, " - red"
, " - blue"
, " - yellow"
, " - green"
, " - magenta"
, " - cyan"
, " - white" }
-- 設(shè)置`vs`作為values多值型參數(shù),還有`v`單值類型
-- 一般放置在最后,用于獲取可變參數(shù)列表
, {}
, {nil, "contents", "vs", nil, "The info contents." }
}
}
定義完這個(gè)任務(wù)后,執(zhí)行xmake --help
,就會多出一個(gè)任務(wù)項(xiàng)來:
Tasks:
...
echo Echo the given info!
如果通過set_category設(shè)置分類為plugin
,那么這個(gè)任務(wù)就是一個(gè)插件了:
Plugins:
...
echo Echo the given info!
想要手動運(yùn)行這個(gè)任務(wù),可以執(zhí)行:
$ xmake echo hello xmake!
就行了,如果要看這個(gè)任務(wù)定義的菜單,只需要執(zhí)行:xmake echo [-h|--help]
,顯示結(jié)果如下:
Usage: $xmake echo [options]
Echo the given info!
Options:
-v, --verbose Print lots of verbose information.
--backtrace Print backtrace information for debugging.
--profile Print performance data for debugging.
--version Print the version number and exit.
-h, --help Print this help message and exit.
-F FILE, --file=FILE Read a given xmake.lua file.
-P PROJECT, --project=PROJECT Change to the given project directory.
Search priority:
1. The Given Command Argument
2. The Envirnoment Variable: XMAKE_PROJECT_DIR
3. The Current Directory
-b, --bright Enable bright.
-d, --dim Enable dim.
--, --blink Enable blink.
-r, --reverse Reverse color.
-c COLOR, --color=COLOR Set the output color. (default: black)
- red
- blue
- yellow
- green
- magenta
- cyan
- white
contents ... The info contents.
<p class="tip"> 其中菜單最開頭的部分選項(xiàng),是xmake內(nèi)置的常用選項(xiàng),基本上每個(gè)任務(wù)都會用到,不需要自己額外定義,簡化菜單定義。 </p>
下面,我們來實(shí)際運(yùn)行下這個(gè)任務(wù),例如我要顯示紅色的hello xmake!
,只需要:
$ xmake echo -c red hello xmake!
也可以使用選項(xiàng)全名,并且加上高亮:
$ xmake echo --color=red --bright hello xmake!
最后面的可變參數(shù)列表,在run
腳本中通過option.get("contents")
獲取,返回的是一個(gè)table
類型的數(shù)組。
僅僅用于菜單的分組顯示,當(dāng)然插件默認(rèn)會用plugin
,內(nèi)置任務(wù)默認(rèn)會用:action
,但也僅僅只是個(gè)約定。
<p class="tips">
你可以使用任何自己定義的名字,相同名字會分組歸類到一起顯示,如果設(shè)置為plugin
,就會顯示到xmake的Plugins分組中去。
</p>
例如:
Plugins:
l, lua Run the lua script.
m, macro Run the given macro.
doxygen Generate the doxygen document.
project Generate the project file.
hello Hello xmake!
app2ipa Generate .ipa file from the given .app
echo Echo the given info!
如果沒有調(diào)用這個(gè)接口設(shè)置分類,默認(rèn)使用Tasks
分組顯示,代表普通任務(wù)。
可以有兩種設(shè)置方式,最簡單的就是設(shè)置內(nèi)嵌函數(shù):
task("hello")
on_run(function ()
print("hello xmake!")
end)
這種對于小任務(wù)很方便,也很簡潔,但是對于大型任務(wù)就不太適用了,例如插件等,需要復(fù)雜的腳本支持。
這個(gè)時(shí)候就需要獨(dú)立的模塊文件來設(shè)置運(yùn)行腳本,例如:
task("hello")
on_run("main")
這里的main
設(shè)置為腳本運(yùn)行主入口模塊,文件名為main.lua
,放在定義task
的xmake.lua
的同目錄下,當(dāng)然你可以起其他文件名。
目錄結(jié)構(gòu)如下:
projectdir
- xmake.lua
- main.lua
main.lua
里面內(nèi)容如下:
function main(...)
print("hello xmake!")
end
就是一個(gè)簡單的帶main
主函數(shù)的腳本文件,你可以通過import導(dǎo)入各種擴(kuò)展模塊,實(shí)現(xiàn)復(fù)雜功能,例如:
-- 導(dǎo)入?yún)?shù)選項(xiàng)模塊
import("core.base.option")
-- 入口函數(shù)
function main(...)
-- 獲取參數(shù)內(nèi)容
print("color: %s", option.get("color"))
end
你也可以在當(dāng)前目錄下,創(chuàng)建多個(gè)自定義的模塊文件,通過import導(dǎo)入后使用,例如:
projectdir
- xmake.lua
- main.lua
- module.lua
module.lua
的內(nèi)容如下:
-- 定義一個(gè)導(dǎo)出接口
function hello()
print("hello xmake!")
end
<p class="tip">
私有接口,通過_hello
帶下滑線前綴命名,這樣導(dǎo)入的模塊就不會包含此接口,只在模塊自身內(nèi)部使用。
</p>
然后在main.lua
進(jìn)行調(diào)用:
import("module")
function main(...)
module.hello()
end
其中,main(...)
中參數(shù),是通過task.run
指定的,例如:
task.run("hello", {color="red"}, arg1, arg2, arg3)
里面的arg1, arg2
這些就是傳入hello
任務(wù)main(...)
入口的參數(shù)列表,而{color="red"}
用來指定任務(wù)菜單中的參數(shù)選項(xiàng)。
更加詳細(xì)的task.run
描述,見:task.run
xmake除了內(nèi)置的一些構(gòu)建平臺,還可以自己擴(kuò)展自定義構(gòu)建平臺,可以將自己實(shí)現(xiàn)的平臺放置在以下目錄即可, xmake會自動檢測并且加載他們:
平臺目錄 | 描述 |
---|---|
projectdir/.xmake/platforms | 當(dāng)前工程的平臺目錄, 只對當(dāng)前工程有效 |
globaldir/.xmake/platforms | 全局配置的平臺目錄,當(dāng)前主機(jī)全局有效 |
installdir/xmake/platforms | xmake安裝后內(nèi)置的平臺目錄 |
用戶可根據(jù)不同需求,將自定義的平臺放置在對應(yīng)的目錄中。
<p class="warning">
平臺的擴(kuò)展定義,盡量不要放到工程xmake.lua
中去,新建一個(gè)單獨(dú)的平臺目錄放置相關(guān)描述實(shí)現(xiàn)。
</p>
平臺描述的目錄結(jié)構(gòu):
platforms
- myplat1
- xmake.lua
- myplat2
- xmake.lua
其中xmake.lua
為每個(gè)平臺的主描述文件,相當(dāng)于入口描述。
接口 | 描述 | 支持版本 |
---|---|---|
platform | 定義平臺 | >= 2.0.1 |
platform_end | 結(jié)束定義平臺 | >= 2.1.1 |
set_os | 設(shè)置平臺系統(tǒng) | >= 2.0.1 |
set_menu | 設(shè)置平臺菜單 | >= 2.0.1 |
set_hosts | 設(shè)置平臺支持的主機(jī)環(huán)境 | >= 2.0.1 |
set_archs | 設(shè)置平臺支持的架構(gòu)環(huán)境 | >= 2.0.1 |
set_tooldirs | 設(shè)置平臺工具的搜索目錄 | >= 2.0.1 |
on_load | 設(shè)置加載平臺環(huán)境配置腳本 | >= 2.0.1 |
on_check | 設(shè)置平臺工具的檢測腳本 | >= 2.0.1 |
on_install | 設(shè)置平臺相關(guān)的工程目標(biāo)安裝腳本 | >= 2.0.5 |
on_uninstall | 設(shè)置平臺相關(guān)的工程目標(biāo)卸載腳本 | >= 2.0.5 |
自定義一個(gè)平臺域,例如:
platform("iphoneos")
-- 設(shè)置操作系統(tǒng)
set_os("ios")
-- 設(shè)置主機(jī)環(huán)境
set_hosts("macosx")
-- 設(shè)置支持的架構(gòu)
set_archs("armv7", "armv7s", "arm64", "i386", "x86_64")
-- 設(shè)置gcc, clang等平臺相關(guān)工具的搜索目錄
set_tooldirs("/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin")
-- 設(shè)置gcc,clang等工具的檢測腳本文件
on_check("check")
-- 設(shè)置平臺初始化加載腳本文件,如果實(shí)現(xiàn)不復(fù)雜的話,可以使用內(nèi)嵌函數(shù)
on_load("load")
-- 設(shè)置平臺的幫助菜單
set_menu {
config =
{
{}
, {nil, "xcode_dir", "kv", "auto", "the xcode application directory" }
, {nil, "xcode_sdkver", "kv", "auto", "the sdk version for xcode" }
, {nil, "target_minver", "kv", "auto", "the target minimal version" }
, {}
, {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
, {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
, {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
}
, global =
{
{}
, {nil, "xcode_dir", "kv", "auto", "the xcode application directory" }
, {}
, {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
, {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
, {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
}
}
<p class="warning">
是在platforms
目錄相關(guān)平臺的xmake.lua
中編寫,而不是在工程目錄的xmake.lua
中。
</p>
這是一個(gè)可選api,顯示離開選項(xiàng)作用域,用法和target_end類似。
設(shè)置目標(biāo)平臺的操作系統(tǒng),例如:ios
, android
, linux
, windows
等
platform("iphoneos")
set_os("ios")
這個(gè)一般用于在自定義腳本和插件開發(fā)中,core.platform.platform模塊中進(jìn)行訪問,獲取當(dāng)前平臺的操作系統(tǒng)。
先給個(gè)設(shè)置的例子:
platform("iphoneos")
...
-- 設(shè)置平臺的幫助菜單
set_menu {
config =
{
{}
, {nil, "xcode_dir", "kv", "auto", "the xcode application directory" }
, {nil, "xcode_sdkver", "kv", "auto", "the sdk version for xcode" }
, {nil, "target_minver", "kv", "auto", "the target minimal version" }
, {}
, {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
, {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
, {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
}
, global =
{
{}
, {nil, "xcode_dir", "kv", "auto", "the xcode application directory" }
, {}
, {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
, {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
, {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
}
}
其中config
組用來設(shè)置:xmake f --help
中的本地工程菜單,global
用來設(shè)置:xmake g --help
全局平臺配置中的菜單。
具體設(shè)置格式可參考:task:set_menu。
用來設(shè)置當(dāng)前目標(biāo)平臺支持主機(jī)構(gòu)建環(huán)境,例如iphoneos
平臺可以在macosx
主機(jī)系統(tǒng)上構(gòu)建,那么可以設(shè)置為:
platform("iphoneos")
set_hosts("macosx")
而android
平臺可以同時(shí)在linux
, "macosx", windows
主機(jī)環(huán)境中構(gòu)建,那么可以設(shè)置為:
platform("android")
set_hosts("linux", "macosx", "windows")
用來設(shè)置當(dāng)前目標(biāo)平臺支持的編譯架構(gòu)環(huán)境,例如iphoneos
平臺可以構(gòu)建armv7
, armv7s
, arm64
, i386
, x86_64
等架構(gòu),那么可以設(shè)置為:
platform("iphoneos")
set_archs("armv7", "armv7s", "arm64", "i386", "x86_64")
配置好架構(gòu)后,執(zhí)行:xmake f -h
,就會在對應(yīng)arch參數(shù)描述,自動顯示設(shè)置的架構(gòu)列表:
-a ARCH, --arch=ARCH Compile for the given architecture. (default: auto)
- android: armv5te armv6 armv7-a armv8-a arm64-v8a
- iphoneos: armv7 armv7s arm64 i386 x86_64
- linux: i386 x86_64
- macosx: i386 x86_64
- mingw: i386 x86_64
- watchos: armv7k i386
- windows: x86 x64 amd64 x86_amd64
xmake會自動檢測當(dāng)前平臺支持的一些構(gòu)建工具是否存在,例如編譯器、鏈接器等,如果要提高檢測通過率,可以在平臺配置的時(shí)候,設(shè)置一些工具環(huán)境搜索目錄,例如:
platform("linux")
-- 在linux下檢測這些目錄環(huán)境
set_tooldirs("/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin")
一般用于在平臺剛加載時(shí),設(shè)置一些基本配置:生成目標(biāo)文件命名格式、平臺相關(guān)編譯選項(xiàng)等
platform("windows")
-- on load
on_load(function ()
-- init the file formats
_g.formats = {}
_g.formats.static = {"", ".lib"}
_g.formats.object = {"", ".obj"}
_g.formats.shared = {"", ".dll"}
_g.formats.binary = {"", ".exe"}
_g.formats.symbol = {"", ".pdb"}
-- init flags for dlang
local dc_archs = { x86 = "-m32", x64 = "-m64", amd64 = "-m64", x86_amd64 = "-m64" }
_g.dcflags = { dc_archs[arch] or "" }
_g["dc-shflags"] = { dc_archs[arch] or "" }
_g["dc-ldflags"] = { dc_archs[arch] or "" }
-- ok
return _g
end)
如果加載邏輯比較復(fù)雜,可以獨(dú)立成單獨(dú)init.lua
文件,然后設(shè)置為:
platform("xxxx")
on_load("init")
通過這種方式,會自動加載平臺腳本目錄下對應(yīng)的init.lua
文件,調(diào)用function main() end
函數(shù)入口,完成復(fù)雜加載邏輯。
由于每個(gè)平臺檢測的工具非常多,腳本比較復(fù)雜,一般直接獨(dú)立成check.lua
文件來實(shí)現(xiàn)檢測邏輯,例如:
platform("xxx")
on_check("check")
具體的檢測代碼入口如下:
-- check it
function main(kind)
-- init the check list of config
_g.config =
{
__check_arch
, checker.check_ccache
, _check_toolchains
}
-- init the check list of global
_g.global =
{
checker.check_ccache
, _check_ndk_sdkver
}
-- check it
checker.check(kind, _g)
end
具體實(shí)現(xiàn)這里就不介紹了,可以參考xmake源碼目錄下的platforms
平臺配置代碼: check.lua
具體實(shí)現(xiàn)邏輯見xmake源碼:install.lua
具體實(shí)現(xiàn)邏輯見xmake源碼:uninstall.lua
有待后續(xù)完善。。
xmake提供了 $(varname)
的語法,來支持內(nèi)置變量的獲取,例如:
add_cxflags("-I$(buildir)")
它將會在在實(shí)際編譯的時(shí)候,將內(nèi)置的 buildir
變量轉(zhuǎn)換為實(shí)際的構(gòu)建輸出目錄:-I./build
一般內(nèi)置變量可用于在傳參時(shí)快速獲取和拼接變量字符串,例如:
target("test")
-- 添加工程源碼目錄下的源文件
add_files("$(projectdir)/src/*.c")
-- 添加構(gòu)建目錄下的頭文件搜索路徑
add_includedirs("$(buildir)/inc")
也可以在自定義腳本的模塊接口中使用,例如:
target("test")
on_run(function (target)
-- 復(fù)制當(dāng)前腳本目錄下的頭文件到輸出目錄
os.cp("$(scriptdir)/xxx.h", "$(buildir)/inc")
end)
所有的內(nèi)置變量,也可以通過val接口,來獲取他們的值。
這種使用內(nèi)置變量的方式,使得描述編寫更加的簡潔易讀,下面是一些xmake內(nèi)置的變量,可以直接獲?。?/p>
接口 | 描述 | 支持版本 |
---|---|---|
$(os) | 獲取當(dāng)前編譯平臺的操作系統(tǒng) | >= 2.0.1 |
$(host) | 獲取本機(jī)操作系統(tǒng) | >= 2.0.1 |
$(tmpdir) | 獲取臨時(shí)目錄 | >= 2.0.1 |
$(curdir) | 獲取當(dāng)前目錄 | >= 2.0.1 |
$(buildir) | 獲取構(gòu)建輸出目錄 | >= 2.0.1 |
$(scriptdir) | 獲取工程描述腳本目錄 | >= 2.1.1 |
$(globaldir) | 獲取全局配置目錄 | >= 2.0.1 |
$(configdir) | 獲取本地工程配置目錄 | >= 2.0.1 |
$(programdir) | xmake安裝腳本目錄 | >= 2.1.5 |
$(projectdir) | 獲取工程根目錄 | >= 2.0.1 |
$(shell) | 執(zhí)行外部shell命令 | >= 2.0.1 |
$(env) | 獲取外部環(huán)境變量 | >= 2.1.5 |
$(reg) | 獲取windows注冊表配置項(xiàng)的值 | >= 2.1.5 |
當(dāng)然這種變量模式,也是可以擴(kuò)展的,默認(rèn)通過xmake f --var=val
命令,配置的參數(shù)都是可以直接獲取,例如:
target("test")
add_defines("-DTEST=$(var)")
<p class="tip">
所有xmake f --xxx=...
配置的參數(shù)值,都是可以通過內(nèi)置變量獲取到,例如:xmake f --arch=x86
對應(yīng)$(arch)
,其他的還有$(plat)
, $(mode)
等等。
具體有哪些參數(shù),可以通過:xmake f -h
才查看。
</p>
既然支持直接從配置選項(xiàng)中獲取,那么當(dāng)然也就能很方便的擴(kuò)展自定義的選項(xiàng),來獲取自定義的變量了,具體如何自定義選項(xiàng)見:option
如果當(dāng)前編譯的是iphoneos,那么這個(gè)值就是:ios
,以此類推。
指的是當(dāng)前本機(jī)環(huán)境的主機(jī)系統(tǒng),如果你是在macOS上編譯,那么系統(tǒng)就是:macosx
一般用于臨時(shí)存放一些非永久性文件。
一般默認(rèn)是執(zhí)行xmake
命令時(shí)的工程根目錄,當(dāng)然如果通過os.cd改變了目錄的話,這個(gè)值也會一起改變。
默認(rèn)一般為當(dāng)前工程根目錄下的:./build
目錄,也可以通過執(zhí)行:xmake f -o /tmp/build
命令來修改默認(rèn)的輸出目錄。
也就是對應(yīng)xmake.lua
所在的目錄路徑。
xmake的xmake g|global
全局配置命令,數(shù)據(jù)存儲的目錄路徑,在里面可以放置一些自己的插件、平臺腳本。
默認(rèn)為:~/.config
當(dāng)前工程的配置存儲目錄,也就是xmake f|config
配置命令的存儲目錄,默認(rèn)為:projectdir/.config
也就是XMAKE_PROGRAM_DIR
環(huán)境變量所在目錄,我們也可以通過設(shè)置這個(gè)環(huán)境量,來修改xmake的加載腳本,實(shí)現(xiàn)版本切換。
也就是xmake -P xxx
命令中指定的目錄路徑,默認(rèn)不指定就是xmake
命令執(zhí)行時(shí)的當(dāng)前目錄,一般用于定位工程文件。
除了內(nèi)置的變量處理,xmake還支持原生shell的運(yùn)行,來處理一些xmake內(nèi)置不支持的功能
例如,現(xiàn)在有個(gè)需求,我想用在編譯linux程序時(shí),調(diào)用pkg-config
獲取到實(shí)際的第三方鏈接庫名,可以這么做:
target("test")
set_kind("binary")
if is_plat("linux") then
add_ldflags("$(shell pkg-config --libs sqlite3)")
end
當(dāng)然,xmake有自己的自動化第三庫檢測機(jī)制,一般情況下不需要這么麻煩,而且lua自身的腳本化已經(jīng)很不錯(cuò)了。。
但是這個(gè)例子可以說明,xmake是完全可以通過原生shell,來與一些第三方的工具進(jìn)行配合使用。。
例如,可以通過獲取環(huán)境變量中的路徑:
target("test")
add_includedirs("$(env PROGRAMFILES)/OpenSSL/inc")
通過 regpath; name
的方式獲取注冊表中某個(gè)項(xiàng)的值:
print("$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name)")
在自定義腳本、插件腳本、任務(wù)腳本、平臺擴(kuò)展、模板擴(kuò)展等腳本代碼中使用,也就是在類似下面的代碼塊中,可以使用這些模塊接口:
on_run(function (target)
print("hello xmake!")
end)
<p class="warning"> 為了保證外層的描述域盡可能簡潔、安全,一般不建議在這個(gè)域使用接口和模塊操作api,因此大部分模塊接口只能再腳本域使用,來實(shí)現(xiàn)復(fù)雜功能。</br> 當(dāng)然少部分只讀的內(nèi)置接口還是可以在描述域使用的,具體見下表: </p>
接口 | 描述 | 可使用域 | 支持版本 |
---|---|---|---|
val | 獲取內(nèi)置變量的值 | 腳本域 | >= 2.1.5 |
import | 導(dǎo)入擴(kuò)展摸塊 | 腳本域 | >= 2.0.1 |
inherit | 導(dǎo)入并繼承基類模塊 | 腳本域 | >= 2.0.1 |
ifelse | 類似三元條件判斷 | 描述域、腳本域 | >= 2.0.1 |
try-catch-finally | 異常捕獲 | 腳本域 | >= 2.0.1 |
pairs | 用于遍歷字典 | 描述域、腳本域 | >= 2.0.1 |
ipairs | 用于遍歷數(shù)組 | 描述域、腳本域 | >= 2.0.1 |
換行打印終端日志 | 描述域、腳本域 | >= 2.0.1 | |
printf | 無換行打印終端日志 | 腳本域 | >= 2.0.1 |
cprint | 換行彩色打印終端日志 | 腳本域 | >= 2.0.1 |
cprintf | 無換行彩色打印終端日志 | 腳本域 | >= 2.0.1 |
format | 格式化字符串 | 描述域、腳本域 | >= 2.0.1 |
vformat | 格式化字符串,支持內(nèi)置變量轉(zhuǎn)義 | 腳本域 | >= 2.0.1 |
raise | 拋出異常中斷程序 | 腳本域 | >= 2.0.1 |
os | 系統(tǒng)操作模塊 | 部分只讀操作描述域、腳本域 | >= 2.0.1 |
io | 文件操作模塊 | 腳本域 | >= 2.0.1 |
path | 路徑操作模塊 | 描述域、腳本域 | >= 2.0.1 |
table | 數(shù)組和字典操作模塊 | 描述域、腳本域 | >= 2.0.1 |
string | 字符串操作模塊 | 描述域、腳本域 | >= 2.0.1 |
process | 進(jìn)程操作模塊 | 腳本域 | >= 2.0.1 |
coroutine | 協(xié)程操作模塊 | 腳本域 | >= 2.0.1 |
在描述域使用接口調(diào)用的實(shí)例如下,一般僅用于條件控制:
-- 掃描當(dāng)前xmake.lua目錄下的所有子目錄,以每個(gè)目錄的名字定義一個(gè)task任務(wù)
for _, taskname in ipairs(os.dirs("*"), path.basename) do
task(taskname)
on_run(function ()
end)
end
上面所說的腳本域、描述域主要是指:
-- 描述域
target("test")
-- 描述域
set_kind("static")
add_files("src/*.c")
on_run(function (target)
-- 腳本域
end)
-- 描述域
內(nèi)置變量可以通過此接口直接獲取,而不需要再加$()
的包裹,使用更加簡單,例如:
print(val("host"))
print(val("env PATH"))
local s = val("shell echo hello")
而用vformat就比較繁瑣了:
local s = vformat("$(shell echo hello)")
不過vformat
支持字符串參數(shù)格式化,更加強(qiáng)大, 所以應(yīng)用場景不同。
import的主要用于導(dǎo)入xmake的擴(kuò)展類庫以及一些自定義的類庫模塊,一般用于:
導(dǎo)入機(jī)制如下:
導(dǎo)入的語法規(guī)則:
基于.
的類庫路徑規(guī)則,例如:
導(dǎo)入core核心擴(kuò)展模塊
import("core.base.option")
import("core.project")
import("core.base.task") -- 2.1.5 以前是 core.project.task
import("core")
function main()
-- 獲取參數(shù)選項(xiàng)
print(option.get("version"))
-- 運(yùn)行任務(wù)和插件
task.run("hello")
project.task.run("hello")
core.base.task.run("hello")
end
導(dǎo)入當(dāng)前目錄下的自定義模塊:
目錄結(jié)構(gòu):
plugin
- xmake.lua
- main.lua
- modules
- hello1.lua
- hello2.lua
在main.lua中導(dǎo)入modules
import("modules.hello1")
import("modules.hello2")
導(dǎo)入后就可以直接使用里面的所有公有接口,私有接口用_
前綴標(biāo)示,表明不會被導(dǎo)出,不會被外部調(diào)用到。。
除了當(dāng)前目錄,我們還可以導(dǎo)入其他指定目錄里面的類庫,例如:
import("hello3", {rootdir = "/home/xxx/modules"})
為了防止命名沖突,導(dǎo)入后還可以指定的別名:
import("core.platform.platform", {alias = "p"})
function main()
-- 這樣我們就可以使用p來調(diào)用platform模塊的plats接口,獲取所有xmake支持的平臺列表了
table.dump(p.plats())
end
import不僅可以導(dǎo)入類庫,還支持導(dǎo)入的同時(shí)作為繼承導(dǎo)入,實(shí)現(xiàn)模塊間的繼承關(guān)系
import("xxx.xxx", {inherit = true})
這樣導(dǎo)入的不是這個(gè)模塊的引用,而是導(dǎo)入的這個(gè)模塊的所有公有接口本身,這樣就會跟當(dāng)前模塊的接口進(jìn)行合并,實(shí)現(xiàn)模塊間的繼承。
2.1.5版本新增兩個(gè)新屬性:import("xxx.xxx", {try = true, anonymous = true})
try為true,則導(dǎo)入的模塊不存在的話,僅僅返回nil,并不會拋異常后中斷xmake. anonymous為true,則導(dǎo)入的模塊不會引入當(dāng)前作用域,僅僅在import接口返回導(dǎo)入的對象引用。
這個(gè)等價(jià)于import接口的inherit
模式,也就是:
import("xxx.xxx", {inherit = true})
用inherit
接口的話,會更簡潔些:
inherit("xxx.xxx")
使用實(shí)例,可以參看xmake的tools目錄下的腳本:clang.lua
這個(gè)就是clang工具模塊繼承了gcc的部分實(shí)現(xiàn)。
由于lua沒有內(nèi)置的三元運(yùn)算符,通過封裝ifelse
接口,實(shí)現(xiàn)更加簡潔的條件選擇:
local ok = ifelse(a == 0, "ok", "no")
lua原生并沒有提供try-catch的語法來捕獲異常處理,但是提供了pcall/xpcall
等接口,可在保護(hù)模式下執(zhí)行l(wèi)ua函數(shù)。
因此,可以通過封裝這兩個(gè)接口,來實(shí)現(xiàn)try-catch塊的捕獲機(jī)制。
我們可以先來看下,封裝后的try-catch使用方式:
try
{
-- try 代碼塊
function ()
error("error message")
end,
-- catch 代碼塊
catch
{
-- 發(fā)生異常后,被執(zhí)行
function (errors)
print(errors)
end
}
}
上面的代碼中,在try塊內(nèi)部認(rèn)為引發(fā)了一個(gè)異常,并且拋出錯(cuò)誤消息,在catch中進(jìn)行了捕獲,并且將錯(cuò)誤消息進(jìn)行輸出顯示。
而finally的處理,這個(gè)的作用是對于try{}
代碼塊,不管是否執(zhí)行成功,都會執(zhí)行到finally塊中
也就說,其實(shí)上面的實(shí)現(xiàn),完整的支持語法是:try-catch-finally
模式,其中catch和finally都是可選的,根據(jù)自己的實(shí)際需求提供
例如:
try
{
-- try 代碼塊
function ()
error("error message")
end,
-- catch 代碼塊
catch
{
-- 發(fā)生異常后,被執(zhí)行
function (errors)
print(errors)
end
},
-- finally 代碼塊
finally
{
-- 最后都會執(zhí)行到這里
function (ok, errors)
-- 如果try{}中存在異常,ok為true,errors為錯(cuò)誤信息,否則為false,errors為try中的返回值
end
}
}
或者只有finally塊:
try
{
-- try 代碼塊
function ()
return "info"
end,
-- finally 代碼塊
finally
{
-- 由于此try代碼沒發(fā)生異常,因此ok為true,errors為返回值: "info"
function (ok, errors)
end
}
}
處理可以在finally中獲取try里面的正常返回值,其實(shí)在僅有try的情況下,也是可以獲取返回值的:
-- 如果沒發(fā)生異常,result 為返回值:"xxxx",否則為nil
local result = try
{
function ()
return "xxxx"
end
}
在xmake的自定義腳本、插件開發(fā)中,也是完全基于此異常捕獲機(jī)制
這樣使得擴(kuò)展腳本的開發(fā)非常的精簡可讀,省去了繁瑣的if err ~= nil then
返回值判斷,在發(fā)生錯(cuò)誤時(shí),xmake會直接拋出異常進(jìn)行中斷,然后高亮提示詳細(xì)的錯(cuò)誤信息。
例如:
target("test")
set_kind("binary")
add_files("src/*.c")
-- 在編譯完ios程序后,對目標(biāo)程序進(jìn)行l(wèi)did簽名
after_build(function (target))
os.run("ldid -S %s", target:targetfile())
end
只需要一行os.run
就行了,也不需要返回值判斷是否運(yùn)行成功,因?yàn)檫\(yùn)行失敗后,xmake會自動拋異常,中斷程序并且提示錯(cuò)誤
如果你想在運(yùn)行失敗后,不直接中斷xmake,繼續(xù)往下運(yùn)行,可以自己加個(gè)try快就行了:
target("test")
set_kind("binary")
add_files("src/*.c")
after_build(function (target))
try
{
function ()
os.run("ldid -S %s", target:targetfile())
end
}
end
如果還想捕獲出錯(cuò)信息,可以再加個(gè)catch:
target("test")
set_kind("binary")
add_files("src/*.c")
after_build(function (target))
try
{
function ()
os.run("ldid -S %s", target:targetfile())
end,
catch
{
function (errors)
print(errors)
end
}
}
end
不過一般情況下,在xmake中寫自定義腳本,是不需要手動加try-catch的,直接調(diào)用各種api,出錯(cuò)后讓xmake默認(rèn)的處理程序接管,直接中斷就行了。。
這個(gè)是lua原生的內(nèi)置api,在xmake中,在原有的行為上對其進(jìn)行了一些擴(kuò)展,來簡化一些日常的lua遍歷代碼。
先看下默認(rèn)的原生寫法:
local t = {a = "a", b = "b", c = "c", d = "d", e = "e", f = "f"}
for key, val in pairs(t) do
print("%s: %s", key, val)
end
這對于通常的遍歷操作就足夠了,但是如果我們相對其中每個(gè)遍歷出來的元素,獲取其大寫,我們可以這么寫:
for key, val in pairs(t, function (v) return v:upper() end) do
print("%s: %s", key, val)
end
甚至傳入一些參數(shù)到第二個(gè)function
中,例如:
for key, val in pairs(t, function (v, a, b) return v:upper() .. a .. b end, "a", "b") do
print("%s: %s", key, val)
end
這個(gè)是lua原生的內(nèi)置api,在xmake中,在原有的行為上對其進(jìn)行了一些擴(kuò)展,來簡化一些日常的lua遍歷代碼。
先看下默認(rèn)的原生寫法:
for idx, val in ipairs({"a", "b", "c", "d", "e", "f"}) do
print("%d %s", idx, val)
end
擴(kuò)展寫法類似pairs接口,例如:
for idx, val in ipairs({"a", "b", "c", "d", "e", "f"}, function (v) return v:upper() end) do
print("%d %s", idx, val)
end
for idx, val in ipairs({"a", "b", "c", "d", "e", "f"}, function (v, a, b) return v:upper() .. a .. b end, "a", "b") do
print("%d %s", idx, val)
end
這樣可以簡化for
塊代碼的邏輯,例如我要遍歷指定目錄,獲取其中的文件名,但不包括路徑,就可以通過這種擴(kuò)展方式,簡化寫法:
for _, filename in ipairs(os.dirs("*"), path.filename) do
-- ...
end
此接口也是lua的原生接口,xmake在原有行為不變的基礎(chǔ)上也進(jìn)行了擴(kuò)展,同時(shí)支持:格式化輸出、多變量輸出。
先看下原生支持的方式:
print("hello xmake!")
print("hello", "xmake!", 123)
并且同時(shí)還支持?jǐn)U展的格式化寫法:
print("hello %s!", "xmake")
print("hello xmake! %d", 123)
xmake會同時(shí)支持這兩種寫法,內(nèi)部會去自動智能檢測,選擇輸出行為。
類似print接口,唯一的區(qū)別就是不換行。
行為類似print,區(qū)別就是此接口還支持彩色終端輸出,并且支持emoji
字符輸出。
例如:
cprint('${bright}hello xmake')
cprint('${red}hello xmake')
cprint('${bright green}hello ${clear}xmake')
cprint('${blue onyellow underline}hello xmake${clear}')
cprint('${red}hello ${magenta}xmake')
cprint('${cyan}hello ${dim yellow}xmake')
顯示結(jié)果如下:
跟顏色相關(guān)的描述,都放置在 ${ }
里面,可以同時(shí)設(shè)置多個(gè)不同的屬性,例如:
${bright red underline onyellow}
表示:高亮紅色,背景黃色,并且?guī)禄€
所有這些描述,都會影響后面一整行字符,如果只想顯示部分顏色的文字,可以在結(jié)束位置,插入${clear}
清楚前面顏色描述
例如:
${red}hello ${clear}xmake
這樣的話,僅僅hello是顯示紅色,其他還是正常默認(rèn)黑色顯示。
其他顏色屬于,我這里就不一一介紹,直接貼上xmake代碼里面的屬性列表吧:
colors.keys =
{
-- 屬性
reset = 0 -- 重置屬性
, clear = 0 -- 清楚屬性
, default = 0 -- 默認(rèn)屬性
, bright = 1 -- 高亮
, dim = 2 -- 暗色
, underline = 4 -- 下劃線
, blink = 5 -- 閃爍
, reverse = 7 -- 反轉(zhuǎn)顏色
, hidden = 8 -- 隱藏文字
-- 前景色
, black = 30
, red = 31
, green = 32
, yellow = 33
, blue = 34
, magenta = 35
, cyan = 36
, white = 37
-- 背景色
, onblack = 40
, onred = 41
, ongreen = 42
, onyellow = 43
, onblue = 44
, onmagenta = 45
, oncyan = 46
, onwhite = 47
除了可以色彩高亮顯示外,如果你的終端是在macosx下,lion以上的系統(tǒng),xmake還可以支持emoji表情的顯示哦,對于不支持系統(tǒng),會 忽略顯示,例如:
cprint("hello xmake${beer}")
cprint("hello${ok_hand} xmake")
上面兩行代碼,我打印了一個(gè)homebrew里面經(jīng)典的啤酒符號,下面那行打印了一個(gè)ok的手勢符號,是不是很炫哈。。
所有的emoji表情,以及xmake里面對應(yīng)的key,都可以通過emoji符號里面找到。。
2.1.7版本支持24位真彩色輸出,如果終端支持的話:
import("core.base.colors")
if colors.truecolor() then
cprint("${255;0;0}hello")
cprint("${on;255;0;0}hello${clear} xmake")
cprint("${bright 255;0;0 underline}hello")
cprint("${bright on;255;0;0 0;255;0}hello${clear} xmake")
end
xmake對于truecolor的檢測支持,是通過$COLORTERM
環(huán)境變量來實(shí)現(xiàn)的,如果你的終端支持truecolor,可以手動設(shè)置此環(huán)境變量,來告訴xmake啟用truecolor支持。
可以通過下面的命令來啟用和測試:
$ export COLORTERM=truecolor
$ xmake --version
此接口類似cprint,區(qū)別就是不換行輸出。
如果只是想格式化字符串,不進(jìn)行輸出,可以使用這個(gè)接口,此接口跟string.format接口等價(jià),只是個(gè)接口名簡化版。
local s = format("hello %s", xmake)
此接口跟format接口類似,只是增加對內(nèi)置變量的獲取和轉(zhuǎn)義支持。
local s = vformat("hello %s $(mode) $(arch) $(env PATH)", xmake)
如果想在自定義腳本、插件任務(wù)中中斷xmake運(yùn)行,可以使用這個(gè)接口拋出異常,如果上層沒有顯示調(diào)用try-catch捕獲的話,xmake就會中斷執(zhí)行,并且顯示出錯(cuò)信息。
if (errors) raise(errors)
如果在try塊中拋出異常,就會在catch和finally中進(jìn)行errors信息捕獲,具體見:try-catch
系統(tǒng)操作模塊,屬于內(nèi)置模塊,無需使用import導(dǎo)入,可直接腳本域調(diào)用其接口。
此模塊也是lua的原生模塊,xmake在其基礎(chǔ)上進(jìn)行了擴(kuò)展,提供更多實(shí)用的接口。
接口 | 描述 | 支持版本 |
---|---|---|
os.cp | 復(fù)制文件或目錄 | >= 2.0.1 |
os.mv | 移動重命名文件或目錄 | >= 2.0.1 |
os.rm | 刪除文件或目錄樹 | >= 2.0.1 |
os.trycp | 嘗試復(fù)制文件或目錄 | >= 2.1.6 |
os.trymv | 嘗試移動重命名文件或目錄 | >= 2.1.6 |
os.tryrm | 嘗試刪除文件或目錄樹 | >= 2.1.6 |
os.cd | 進(jìn)入指定目錄 | >= 2.0.1 |
os.rmdir | 刪除目錄樹 | >= 2.0.1 |
os.mkdir | 創(chuàng)建指定目錄 | >= 2.0.1 |
os.isdir | 判斷目錄是否存在 | >= 2.0.1 |
os.isfile | 判斷文件是否存在 | >= 2.0.1 |
os.exists | 判斷文件或目錄是否存在 | >= 2.0.1 |
os.dirs | 遍歷獲取指定目錄下的所有目錄 | >= 2.0.1 |
os.files | 遍歷獲取指定目錄下的所有文件 | >= 2.0.1 |
os.filedirs | 遍歷獲取指定目錄下的所有文件或目錄 | >= 2.0.1 |
os.run | 安靜運(yùn)行程序 | >= 2.0.1 |
os.runv | 安靜運(yùn)行程序,帶參數(shù)列表 | >= 2.1.5 |
os.exec | 回顯運(yùn)行程序 | >= 2.0.1 |
os.execv | 回顯運(yùn)行程序,帶參數(shù)列表 | >= 2.1.5 |
os.iorun | 運(yùn)行并獲取程序輸出內(nèi)容 | >= 2.0.1 |
os.iorunv | 運(yùn)行并獲取程序輸出內(nèi)容,帶參數(shù)列表 | >= 2.1.5 |
os.getenv | 獲取環(huán)境變量 | >= 2.0.1 |
os.setenv | 設(shè)置環(huán)境變量 | >= 2.0.1 |
os.tmpdir | 獲取臨時(shí)目錄路徑 | >= 2.0.1 |
os.tmpfile | 獲取臨時(shí)文件路徑 | >= 2.0.1 |
os.curdir | 獲取當(dāng)前目錄路徑 | >= 2.0.1 |
os.scriptdir | 獲取腳本目錄路徑 | >= 2.0.1 |
os.programdir | 獲取xmake安裝主程序腳本目錄 | >= 2.1.5 |
os.projectdir | 獲取工程主目錄 | >= 2.1.5 |
os.arch | 獲取當(dāng)前系統(tǒng)架構(gòu) | >= 2.0.1 |
os.host | 獲取當(dāng)前主機(jī)系統(tǒng) | >= 2.0.1 |
行為和shell中的cp
命令類似,支持路徑通配符匹配(使用的是lua模式匹配),支持多文件復(fù)制,以及內(nèi)置變量支持。
例如:
os.cp("$(scriptdir)/*.h", "$(projectdir)/src/test/**.h", "$(buildir)/inc")
上面的代碼將:當(dāng)前xmake.lua
目錄下的所有頭文件、工程源碼test目錄下的頭文件全部復(fù)制到$(buildir)
輸出目錄中。
其中$(scriptdir)
, $(projectdir)
這些變量是xmake的內(nèi)置變量,具體詳情見:內(nèi)置變量的相關(guān)文檔。
而*.h
和**.h
中的匹配模式,跟add_files中的類似,前者是單級目錄匹配,后者是遞歸多級目錄匹配。
此接口同時(shí)支持目錄的遞歸復(fù)制
,例如:
-- 遞歸復(fù)制當(dāng)前目錄到臨時(shí)目錄
os.cp("$(curdir)/test/", "$(tmpdir)/test")
<p class="tip">
盡量使用os.cp
接口,而不是os.run("cp ..")
,這樣更能保證平臺一致性,實(shí)現(xiàn)跨平臺構(gòu)建描述。
</p>
跟os.cp的使用類似,同樣支持多文件移動操作和模式匹配,例如:
-- 移動多個(gè)文件到臨時(shí)目錄
os.mv("$(buildir)/test1", "$(buildir)/test2", "$(tmpdir)")
-- 文件移動不支持批量操作,也就是文件重命名
os.mv("$(buildir)/libtest.a", "$(buildir)/libdemo.a")
支持遞歸刪除目錄,批量刪除操作,以及模式匹配和內(nèi)置變量,例如:
os.rm("$(buildir)/inc/**.h", "$(buildir)/lib/")
跟os.cp類似,唯一的區(qū)別就是,此接口操作失敗不會拋出異常中斷xmake,而是通過返回值標(biāo)示是否執(zhí)行成功。
if os.trycp("file", "dest/file") then
end
跟os.mv類似,唯一的區(qū)別就是,此接口操作失敗不會拋出異常中斷xmake,而是通過返回值標(biāo)示是否執(zhí)行成功。
if os.trymv("file", "dest/file") then
end
跟os.rm類似,唯一的區(qū)別就是,此接口操作失敗不會拋出異常中斷xmake,而是通過返回值標(biāo)示是否執(zhí)行成功。
if os.tryrm("file") then
end
這個(gè)操作用于目錄切換,同樣也支持內(nèi)置變量,但是不支持模式匹配和多目錄處理,例如:
-- 進(jìn)入臨時(shí)目錄
os.cd("$(tmpdir)")
如果要離開進(jìn)入之前的目錄,有多種方式:
-- 進(jìn)入上級目錄
os.cd("..")
-- 進(jìn)入先前的目錄,相當(dāng)于:cd -
os.cd("-")
-- 進(jìn)入目錄前保存之前的目錄,用于之后跨級直接切回
local oldir = os.cd("./src")
...
os.cd(oldir)
如果不是目錄就無法刪除。
支持批量創(chuàng)建和內(nèi)置變量,例如:
os.mkdir("$(tmpdir)/test", "$(buildir)/inc")
如果目錄不存在,則返回false
if os.isdir("src") then
-- ...
end
如果文件不存在,則返回false
if os.isfile("$(buildir)/libxxx.a") then
-- ...
end
如果文件或目錄不存在,則返回false
-- 判斷目錄存在
if os.exists("$(buildir)") then
-- ...
end
-- 判斷文件存在
if os.exists("$(buildir)/libxxx.a") then
-- ...
end
支持add_files中的模式匹配,支持遞歸和非遞歸模式遍歷,返回的結(jié)果是一個(gè)table數(shù)組,如果獲取不到,返回空數(shù)組,例如:
-- 遞歸遍歷獲取所有子目錄
for _, dir in ipairs(os.dirs("$(buildir)/inc/**")) do
print(dir)
end
支持add_files中的模式匹配,支持遞歸和非遞歸模式遍歷,返回的結(jié)果是一個(gè)table數(shù)組,如果獲取不到,返回空數(shù)組,例如:
-- 非遞歸遍歷獲取所有子文件
for _, filepath in ipairs(os.files("$(buildir)/inc/*.h")) do
print(filepath)
end
支持add_files中的模式匹配,支持遞歸和非遞歸模式遍歷,返回的結(jié)果是一個(gè)table數(shù)組,如果獲取不到,返回空數(shù)組,例如:
-- 遞歸遍歷獲取所有子文件和目錄
for _, filedir in ipairs(os.filedirs("$(buildir)/**")) do
print(filedir)
end
用于執(zhí)行第三方的shell命令,但不會回顯輸出,僅僅在出錯(cuò)后,高亮輸出錯(cuò)誤信息。
此接口支持參數(shù)格式化、內(nèi)置變量,例如:
-- 格式化參數(shù)傳入
os.run("echo hello %s!", "xmake")
-- 列舉構(gòu)建目錄文件
os.run("ls -l $(buildir)")
<p class="warning">
使用此接口執(zhí)行shell命令,容易使構(gòu)建跨平臺性降低,對于os.run("cp ..")
這種盡量使用os.cp
代替。<br>
如果必須使用此接口運(yùn)行shell程序,請自行使用config.plat接口判斷平臺支持。
</p>
更加高級的進(jìn)程運(yùn)行和控制,見process模塊接口。
跟os.run類似,只是傳遞參數(shù)的方式是通過參數(shù)列表傳遞,而不是字符串命令,例如:
os.runv("echo", {"hello", "xmake!"})
與os.run接口類似,唯一的不同是,此接口執(zhí)行shell程序時(shí),是帶回顯輸出的,一般調(diào)試的時(shí)候用的比較多
跟os.execv類似,只是傳遞參數(shù)的方式是通過參數(shù)列表傳遞,而不是字符串命令,例如:
os.execv("echo", {"hello", "xmake!"})
與os.run接口類似,唯一的不同是,此接口執(zhí)行shell程序后,會獲取shell程序的執(zhí)行結(jié)果,相當(dāng)于重定向輸出。
可同時(shí)獲取stdout
, stderr
中的內(nèi)容,例如:
local outdata, errdata = os.iorun("echo hello xmake!")
跟os.iorunv類似,只是傳遞參數(shù)的方式是通過參數(shù)列表傳遞,而不是字符串命令,例如:
local result, errors = os.iorunv("echo", {"hello", "xmake!"})
print(os.getenv("PATH"))
os.setenv("HOME", "/tmp/")
跟$(tmpdir)結(jié)果一致,只不過是直接獲取返回一個(gè)變量,可以用后續(xù)字符串維護(hù)。
print(path.join(os.tmpdir(), "file.txt"))
等價(jià)于:
print("$(tmpdir)/file.txt"))
用于獲取生成一個(gè)臨時(shí)文件路徑,僅僅是個(gè)路徑,文件需要自己創(chuàng)建。
跟$(curdir)結(jié)果一致,只不過是直接獲取返回一個(gè)變量,可以用后續(xù)字符串維護(hù)。
用法參考:os.tmpdir。
跟$(scriptdir)結(jié)果一致,只不過是直接獲取返回一個(gè)變量,可以用后續(xù)字符串維護(hù)。
用法參考:os.tmpdir。
跟$(programdir)結(jié)果一致,只不過是直接獲取返回一個(gè)變量,可以用后續(xù)字符串維護(hù)。
跟$(projectdir)結(jié)果一致,只不過是直接獲取返回一個(gè)變量,可以用后續(xù)字符串維護(hù)。
也就是當(dāng)前主機(jī)系統(tǒng)的默認(rèn)架構(gòu),例如我在linux x86_64
上執(zhí)行xmake進(jìn)行構(gòu)建,那么返回值是:x86_64
跟$(host)結(jié)果一致,例如我在linux x86_64
上執(zhí)行xmake進(jìn)行構(gòu)建,那么返回值是:linux
io操作模塊,擴(kuò)展了lua內(nèi)置的io模塊,提供更多易用的接口。
接口 | 描述 | 支持版本 |
---|---|---|
io.open | 打開文件用于讀寫 | >= 2.0.1 |
io.load | 從指定路徑文件反序列化加載所有table內(nèi)容 | >= 2.0.1 |
io.save | 序列化保存所有table內(nèi)容到指定路徑文件 | >= 2.0.1 |
io.readfile | 從指定路徑文件讀取所有內(nèi)容 | >= 2.1.3 |
io.writefile | 寫入所有內(nèi)容到指定路徑文件 | >= 2.1.3 |
io.gsub | 全文替換指定路徑文件的內(nèi)容 | >= 2.0.1 |
io.tail | 讀取和顯示文件的尾部內(nèi)容 | >= 2.0.1 |
io.cat | 讀取和顯示文件的所有內(nèi)容 | >= 2.0.1 |
io.print | 帶換行格式化輸出內(nèi)容到文件 | >= 2.0.1 |
io.printf | 無換行格式化輸出內(nèi)容到文件 | >= 2.0.1 |
這個(gè)是屬于lua的原生接口,詳細(xì)使用可以參看lua的官方文檔:The Complete I/O Model
如果要讀取文件所有內(nèi)容,可以這么寫:
local file = io.open("$(tmpdir)/file.txt", "r")
if file then
local data = file:read("*all")
file:close()
end
或者可以使用io.readfile更加快速地讀取。
如果要寫文件,可以這么操作:
-- 打開文件:w 為寫模式, a 為追加寫模式
local file = io.open("xxx.txt", "w")
if file then
-- 用原生的lua接口寫入數(shù)據(jù)到文件,不支持格式化,無換行,不支持內(nèi)置變量
file:write("hello xmake\n")
-- 用xmake擴(kuò)展的接口寫入數(shù)據(jù)到文件,支持格式化,無換行,不支持內(nèi)置變量
file:writef("hello %s\n", "xmake")
-- 使用xmake擴(kuò)展的格式化傳參寫入一行,帶換行符,并且支持內(nèi)置變量
file:print("hello %s and $(buildir)", "xmake")
-- 使用xmake擴(kuò)展的格式化傳參寫入一行,無換行符,并且支持內(nèi)置變量
file:printf("hello %s and $(buildir) \n", "xmake")
-- 關(guān)閉文件
file:close()
end
可以從文件中加載序列化好的table內(nèi)容,一般與io.save配合使用,例如:
-- 加載序列化文件的內(nèi)容到table
local data = io.load("xxx.txt")
if data then
-- 在終端中dump打印整個(gè)table中內(nèi)容,格式化輸出
table.dump(data)
end
可以序列化存儲table內(nèi)容到指定文件,一般與io.load配合使用,例如:
io.save("xxx.txt", {a = "a", b = "b", c = "c"})
存儲結(jié)果為:
{
["b"] = "b"
, ["a"] = "a"
, ["c"] = "c"
}
可在不打開文件的情況下,直接讀取整個(gè)文件的內(nèi)容,更加的方便,例如:
local data = io.readfile("xxx.txt")
可在不打開文件的情況下,直接寫入整個(gè)文件的內(nèi)容,更加的方便,例如:
io.writefile("xxx.txt", "all data")
類似string.gsub接口,全文模式匹配替換內(nèi)容,不過這里是直接操作文件,例如:
-- 移除文件所有的空白字符
io.gsub("xxx.txt", "%s+", "")
讀取文件尾部指定行數(shù)的數(shù)據(jù),并顯示,類似cat xxx.txt | tail -n 10
命令,例如:
-- 顯示文件最后10行內(nèi)容
io.tail("xxx.txt", 10)
讀取文件的所有內(nèi)容并顯示,類似cat xxx.txt
命令,例如:
io.cat("xxx.txt")
直接格式化傳參輸出一行字符串到文件,并且?guī)Q行,例如:
io.print("xxx.txt", "hello %s!", "xmake")
直接格式化傳參輸出一行字符串到文件,不帶換行,例如:
io.printf("xxx.txt", "hello %s!\n", "xmake")
路徑操作模塊,實(shí)現(xiàn)跨平臺的路徑操作,這是xmake的一個(gè)自定義的模塊。
接口 | 描述 | 支持版本 |
---|---|---|
path.join | 拼接路徑 | >= 2.0.1 |
path.translate | 轉(zhuǎn)換路徑到當(dāng)前平臺的路徑風(fēng)格 | >= 2.0.1 |
path.basename | 獲取路徑最后不帶后綴的文件名 | >= 2.0.1 |
path.filename | 獲取路徑最后帶后綴的文件名 | >= 2.0.1 |
path.extension | 獲取路徑的后綴名 | >= 2.0.1 |
path.directory | 獲取路徑最后的目錄名 | >= 2.0.1 |
path.relative | 轉(zhuǎn)換成相對路徑 | >= 2.0.1 |
path.absolute | 轉(zhuǎn)換成絕對路徑 | >= 2.0.1 |
path.is_absolute | 判斷是否為絕對路徑 | >= 2.0.1 |
將多個(gè)路徑項(xiàng)進(jìn)行追加拼接,由于windows/unix
風(fēng)格的路徑差異,使用api來追加路徑更加跨平臺,例如:
print(path.join("$(tmpdir)", "dir1", "dir2", "file.txt"))
上述拼接在unix上相當(dāng)于:$(tmpdir)/dir1/dir2/file.txt
,而在windows上相當(dāng)于:$(tmpdir)\\dir1\\dir2\\file.txt
如果覺得這樣很繁瑣,不夠清晰簡潔,可以使用:path.translate方式,格式化轉(zhuǎn)換路徑字符串到當(dāng)前平臺支持的格式。
格式化轉(zhuǎn)化指定路徑字符串到當(dāng)前平臺支持的路徑風(fēng)格,同時(shí)支持windows/unix
格式的路徑字符串參數(shù)傳入,甚至混合傳入,例如:
print(path.translate("$(tmpdir)/dir/file.txt"))
print(path.translate("$(tmpdir)\\dir\\file.txt"))
print(path.translate("$(tmpdir)\\dir/dir2//file.txt"))
上面這三種不同格式的路徑字符串,經(jīng)過translate
規(guī)范化后,就會變成當(dāng)前平臺支持的格式,并且會去掉冗余的路徑分隔符。
print(path.basename("$(tmpdir)/dir/file.txt"))
顯示結(jié)果為:file
print(path.filename("$(tmpdir)/dir/file.txt"))
顯示結(jié)果為:file.txt
print(path.extensione("$(tmpdir)/dir/file.txt"))
顯示結(jié)果為:.txt
print(path.directory("$(tmpdir)/dir/file.txt"))
顯示結(jié)果為:dir
print(path.relative("$(tmpdir)/dir/file.txt", "$(tmpdir)"))
顯示結(jié)果為:dir/file.txt
第二個(gè)參數(shù)是指定相對的根目錄,如果不指定,則默認(rèn)相對當(dāng)前目錄:
os.cd("$(tmpdir)")
print(path.relative("$(tmpdir)/dir/file.txt"))
這樣結(jié)果是一樣的。
print(path.absolute("dir/file.txt", "$(tmpdir)"))
顯示結(jié)果為:$(tmpdir)/dir/file.txt
第二個(gè)參數(shù)是指定相對的根目錄,如果不指定,則默認(rèn)相對當(dāng)前目錄:
os.cd("$(tmpdir)")
print(path.absolute("dir/file.txt"))
這樣結(jié)果是一樣的。
if path.is_absolute("/tmp/file.txt") then
-- 如果是絕對路徑
end
table屬于lua原生提供的模塊,對于原生接口使用可以參考:lua官方文檔
xmake中對其進(jìn)行了擴(kuò)展,增加了一些擴(kuò)展接口:
接口 | 描述 | 支持版本 |
---|---|---|
table.join | 合并多個(gè)table并返回 | >= 2.0.1 |
table.join2 | 合并多個(gè)table到第一個(gè)table | >= 2.0.1 |
table.dump | 輸出table的所有內(nèi)容 | >= 2.0.1 |
table.unique | 對table中的內(nèi)容進(jìn)行去重 | >= 2.0.1 |
table.slice | 獲取table的切片 | >= 2.0.1 |
可以將多個(gè)table里面的元素進(jìn)行合并后,返回到一個(gè)新的table中,例如:
local newtable = table.join({1, 2, 3}, {4, 5, 6}, {7, 8, 9})
結(jié)果為:{1, 2, 3, 4, 5, 6, 7, 8, 9}
并且它也支持字典的合并:
local newtable = table.join({a = "a", b = "b"}, {c = "c"}, {d = "d"})
結(jié)果為:{a = "a", b = "b", c = "c", d = "d"}
類似table.join,唯一的區(qū)別是,合并的結(jié)果放置在第一個(gè)參數(shù)中,例如:
local t = {0, 9}
table.join2(t, {1, 2, 3})
結(jié)果為:t = {0, 9, 1, 2, 3}
遞歸格式化打印table中的所有內(nèi)容,一般用于調(diào)試, 例如:
table.dump({1, 2, 3})
結(jié)果為:{1, 2, 3}
去重table的元素,一般用于數(shù)組table,例如:
local newtable = table.unique({1, 1, 2, 3, 4, 4, 5})
結(jié)果為:{1, 2, 3, 4, 5}
用于提取數(shù)組table的部分元素,例如:
-- 提取第4個(gè)元素后面的所有元素,結(jié)果:{4, 5, 6, 7, 8, 9}
table.slice({1, 2, 3, 4, 5, 6, 7, 8, 9}, 4)
-- 提取第4-8個(gè)元素,結(jié)果:{4, 5, 6, 7, 8}
table.slice({1, 2, 3, 4, 5, 6, 7, 8, 9}, 4, 8)
-- 提取第4-8個(gè)元素,間隔步長為2,結(jié)果:{4, 6, 8}
table.slice({1, 2, 3, 4, 5, 6, 7, 8, 9}, 4, 8, 2)
字符串模塊為lua原生自帶的模塊,具體使用見:lua官方手冊
xmake中對其進(jìn)行了擴(kuò)展,增加了一些擴(kuò)展接口:
接口 | 描述 | 支持版本 |
---|---|---|
string.startswith | 判斷字符串開頭是否匹配 | >= 1.0.1 |
string.endswith | 判斷字符串結(jié)尾是否匹配 | >= 1.0.1 |
string.split | 分割字符串 | >= 1.0.1 |
string.trim | 去掉字符串左右空白字符 | >= 1.0.1 |
string.ltrim | 去掉字符串左邊空白字符 | >= 1.0.1 |
string.rtrim | 去掉字符串右邊空白字符 | >= 1.0.1 |
local s = "hello xmake"
if s:startswith("hello") then
print("match")
end
local s = "hello xmake"
if s:endswith("xmake") then
print("match")
end
通過指定的分隔符進(jìn)行字符串分割,分隔符可以是:字符,字符串、模式匹配字符串,例如:
local s = "hello xmake!"
s:split("%s+")
根據(jù)連續(xù)空白字符進(jìn)行分割,結(jié)果為:hello
, xmake!
local s = "hello,xmake:123"
s:split("[,:]")
上面的代碼根據(jù),
或者:
字符進(jìn)行分割,結(jié)果為:hello
, xmake
, 123
string.trim(" hello xmake! ")
結(jié)果為:"hello xmake!"
string.ltrim(" hello xmake! ")
結(jié)果為:"hello xmake! "
string.rtrim(" hello xmake! ")
結(jié)果為:" hello xmake!"
這個(gè)是xmake擴(kuò)展的進(jìn)程控制模塊,用于更加靈活的控制進(jìn)程,比起:os.run系列靈活性更高,也更底層。
接口 | 描述 | 支持版本 |
---|---|---|
process.open | 打開進(jìn)程 | >= 2.0.1 |
process.wait | 等待進(jìn)程結(jié)束 | >= 2.0.1 |
process.close | 關(guān)閉進(jìn)程對象 | >= 2.0.1 |
process.waitlist | 同時(shí)等待多個(gè)進(jìn)程 | >= 2.0.1 |
通過路徑創(chuàng)建運(yùn)行一個(gè)指定程序,并且返回對應(yīng)的進(jìn)程對象:
-- 打開進(jìn)程,后面兩個(gè)參數(shù)指定需要捕獲的stdout, stderr文件路徑
local proc = process.open("echo hello xmake!", outfile, errfile)
if proc then
-- 等待進(jìn)程執(zhí)行完成
--
-- 參數(shù)二為等待超時(shí),-1為永久等待,0為嘗試獲取進(jìn)程狀態(tài)
-- 返回值waitok為等待狀態(tài):1為等待進(jìn)程正常結(jié)束,0為進(jìn)程還在運(yùn)行中,-1位等待失敗
-- 返回值status為,等待進(jìn)程結(jié)束后,進(jìn)程返回的狀態(tài)碼
local waitok, status = process.wait(proc, -1)
-- 釋放進(jìn)程對象
process.close(proc)
end
具體使用見:process.open
具體使用見:process.open
-- 第二個(gè)參數(shù)是等待超時(shí),返回進(jìn)程狀態(tài)列表
for _, procinfo in ipairs(process.waitlist(procs, -1)) do
-- 每個(gè)進(jìn)程的:進(jìn)程對象、進(jìn)程pid、進(jìn)程結(jié)束狀態(tài)碼
local proc = procinfo[1]
local procid = procinfo[2]
local status = procinfo[3]
end
協(xié)程模塊是lua原生自帶的模塊,具使用見:lua官方手冊
所有擴(kuò)展模塊的使用,都需要通過import接口,進(jìn)行導(dǎo)入后才能使用。
一般用于獲取xmake命令參數(shù)選項(xiàng)的值,常用于插件開發(fā)。
接口 | 描述 | 支持版本 |
---|---|---|
option.get | 獲取參數(shù)選項(xiàng)值 | >= 2.0.1 |
在插件開發(fā)中用于獲取參數(shù)選項(xiàng)值,例如:
-- 導(dǎo)入選項(xiàng)模塊
import("core.base.option")
-- 插件入口函數(shù)
function main(...)
print(option.get("info"))
end
上面的代碼獲取hello插件,執(zhí)行:xmake hello --info=xxxx
命令時(shí)候傳入的--info=
選項(xiàng)的值,并顯示:xxxx
對于非main入口的task任務(wù)或插件,可以這么使用:
task("hello")
on_run(function ())
import("core.base.option")
print(option.get("info"))
end)
用于獲取xmake全局的配置信息,也就是xmake g|global --xxx=val
傳入的參數(shù)選項(xiàng)值。
接口 | 描述 | 支持版本 |
---|---|---|
global.get | 獲取指定配置值 | >= 2.0.1 |
global.load | 加載配置 | >= 2.0.1 |
global.directory | 獲取全局配置信息目錄 | >= 2.0.1 |
global.dump | 打印輸出所有全局配置信息 | >= 2.0.1 |
<p class="tip">
2.1.5版本之前為core.project.global
。
</p>
類似config.get,唯一的區(qū)別就是這個(gè)是從全局配置中獲取。
類似global.get,唯一的區(qū)別就是這個(gè)是從全局配置中加載。
默認(rèn)為~/.config
目錄。
輸出結(jié)果如下:
{
clean = true
, ccache = "ccache"
, xcode_dir = "/Applications/Xcode.app"
}
用于任務(wù)操作,一般用于在自定義腳本中、插件任務(wù)中,調(diào)用運(yùn)行其他task任務(wù)。
接口 | 描述 | 支持版本 |
---|---|---|
task.run | 運(yùn)行指定任務(wù) | >= 2.0.1 |
<p class="tip">
2.1.5版本之前為core.project.task
。
</p>
用于在自定義腳本、插件任務(wù)中運(yùn)行task定義的任務(wù)或插件,例如:
task("hello")
on_run(function ()
print("hello xmake!")
end)
target("demo")
on_clean(function(target)
-- 導(dǎo)入task模塊
import("core.base.task")
-- 運(yùn)行這個(gè)hello task
task.run("hello")
end)
我們還可以在運(yùn)行任務(wù)時(shí),增加參數(shù)傳遞,例如:
task("hello")
on_run(function (arg1, arg2)
print("hello xmake: %s %s!", arg1, arg2)
end)
target("demo")
on_clean(function(target)
-- 導(dǎo)入task
import("core.base.task")
-- {} 這個(gè)是給第一種選項(xiàng)傳參使用,這里置空,這里在最后面?zhèn)魅肓藘蓚€(gè)參數(shù):arg1, arg2
task.run("hello", {}, "arg1", "arg2")
end)
對于task.run
的第二個(gè)參數(shù),用于傳遞命令行菜單中的選項(xiàng),而不是直接傳入function (arg, ...)
函數(shù)入口中,例如:
-- 導(dǎo)入task
import("core.base.task")
-- 插件入口
function main(...)
-- 運(yùn)行內(nèi)置的xmake配置任務(wù),相當(dāng)于:xmake f|config --plat=iphoneos --arch=armv7
task.run("config", {plat="iphoneos", arch="armv7"})
emd
鏈接器相關(guān)操作,常用于插件開發(fā)。
接口 | 描述 | 支持版本 |
---|---|---|
linker.link | 執(zhí)行鏈接 | >= 2.0.1 |
linker.linkcmd | 獲取鏈接命令行 | >= 2.0.1 |
linker.linkargv | 獲取鏈接命令行列表 | >= 2.1.5 |
linker.linkflags | 獲取鏈接選項(xiàng) | >= 2.0.1 |
linker.has_flags | 判斷指定鏈接選項(xiàng)是否支持 | >= 2.1.5 |
針對target,鏈接指定對象文件列表,生成對應(yīng)的目標(biāo)文件,例如:
linker.link({"a.o", "b.o", "c.o"}, target:targetfile(), {target = target})
其中target,為工程目標(biāo),這里傳入,主要用于獲取target特定的鏈接選項(xiàng),具體如果獲取工程目標(biāo)對象,見:core.project.project
當(dāng)然也可以不指定target,例如:
linker.link("binary", "cc", {"a.o", "b.o", "c.o"}, "/tmp/targetfile")
直接獲取linker.link中執(zhí)行的命令行字符串,相當(dāng)于:
local cmdstr = linker.linkcmd("static", "cxx", {"a.o", "b.o", "c.o"}, target:targetfile(), {target = target})
注:后面{target = target}
擴(kuò)展參數(shù)部分是可選的,如果傳遞了target對象,那么生成的鏈接命令,會加上這個(gè)target配置對應(yīng)的鏈接選項(xiàng)。
并且還可以自己傳遞各種配置,例如:
local cmdstr = linker.linkcmd("static", "cxx", {"a.o", "b.o", "c.o"}, target:targetfile(), {config = {linkdirs = "/usr/lib"}})
跟linker.linkcmd稍微有點(diǎn)區(qū)別的是,此接口返回的是參數(shù)列表,table表示,更加方便操作:
local program, argv = linker.linkargv("static", "cxx", {"a.o", "b.o", "c.o"}, target:targetfile(), {target = target})
其中返回的第一個(gè)值是主程序名,后面是參數(shù)列表,而os.args(table.join(program, argv))
等價(jià)于linker.linkcmd
。
我們也可以通過傳入返回值給os.runv來直接運(yùn)行它:os.runv(linker.linkargv(..))
獲取linker.linkcmd中的鏈接選項(xiàng)字符串部分,不帶shellname和對象文件列表,并且是按數(shù)組返回,例如:
local flags = linker.linkflags("shared", "cc", {target = target})
for _, flag in ipairs(flags) do
print(flag)
end
返回的是flags的列表數(shù)組。
雖然通過lib.detect.has_flags也能判斷,但是那個(gè)接口更加底層,需要指定鏈接器名稱 而此接口只需要指定target的目標(biāo)類型,源文件類型,它會自動切換選擇當(dāng)前支持的鏈接器。
if linker.has_flags(target:targetkind(), target:sourcekinds(), "-L/usr/lib -lpthread") then
-- ok
end
編譯器相關(guān)操作,常用于插件開發(fā)。
接口 | 描述 | 支持版本 |
---|---|---|
compiler.compile | 執(zhí)行編譯 | >= 2.0.1 |
compiler.compcmd | 獲取編譯命令行 | >= 2.0.1 |
compiler.compargv | 獲取編譯命令行列表 | >= 2.1.5 |
compiler.compflags | 獲取編譯選項(xiàng) | >= 2.0.1 |
compiler.has_flags | 判斷指定編譯選項(xiàng)是否支持 | >= 2.1.5 |
compiler.features | 獲取所有編譯器特性 | >= 2.1.5 |
compiler.has_features | 判斷指定編譯特性是否支持 | >= 2.1.5 |
針對target,鏈接指定對象文件列表,生成對應(yīng)的目標(biāo)文件,例如:
compiler.compile("xxx.c", "xxx.o", "xxx.h.d", {target = target})
其中target,為工程目標(biāo),這里傳入主要用于獲取taeget的特定編譯選項(xiàng),具體如果獲取工程目標(biāo)對象,見:core.project.project
而xxx.h.d
文件用于存儲為此源文件的頭文件依賴文件列表,最后這兩個(gè)參數(shù)都是可選的,編譯的時(shí)候可以不傳他們:
compiler.compile("xxx.c", "xxx.o")
來單純編譯一個(gè)源文件。
直接獲取compiler.compile中執(zhí)行的命令行字符串,相當(dāng)于:
local cmdstr = compiler.compcmd("xxx.c", "xxx.o", {target = target})
注:后面{target = target}
擴(kuò)展參數(shù)部分是可選的,如果傳遞了target對象,那么生成的編譯命令,會加上這個(gè)target配置對應(yīng)的鏈接選項(xiàng)。
并且還可以自己傳遞各種配置,例如:
local cmdstr = compiler.compcmd("xxx.c", "xxx.o", {config = {includedirs = "/usr/include", defines = "DEBUG"}})
通過target,我們可以導(dǎo)出指定目標(biāo)的所有源文件編譯命令:
import("core.project.project")
for _, target in pairs(project.targets()) do
for sourcekind, sourcebatch in pairs(target:sourcebatches()) do
for index, objectfile in ipairs(sourcebatch.objectfiles) do
local cmdstr = compiler.compcmd(sourcebatch.sourcefiles[index], objectfile, {target = target})
end
end
end
跟compiler.compargv稍微有點(diǎn)區(qū)別的是,此接口返回的是參數(shù)列表,table表示,更加方便操作:
local program, argv = compiler.compargv("xxx.c", "xxx.o")
獲取compiler.compcmd中的編譯選項(xiàng)字符串部分,不帶shellname和文件列表,例如:
local flags = compiler.compflags(sourcefile, {target = target})
for _, flag in ipairs(flags) do
print(flag)
end
返回的是flags的列表數(shù)組。
雖然通過lib.detect.has_flags也能判斷,但是那個(gè)接口更加底層,需要指定編譯器名稱。 而此接口只需要指定語言類型,它會自動切換選擇當(dāng)前支持的編譯器。
-- 判斷c語言編譯器是否支持選項(xiàng): -g
if compiler.has_flags("c", "-g") then
-- ok
end
-- 判斷c++語言編譯器是否支持選項(xiàng): -g
if compiler.has_flags("cxx", "-g") then
-- ok
end
雖然通過lib.detect.features也能獲取,但是那個(gè)接口更加底層,需要指定編譯器名稱。 而此接口只需要指定語言類型,它會自動切換選擇當(dāng)前支持的編譯器,然后獲取當(dāng)前的編譯器特性列表。
-- 獲取當(dāng)前c語言編譯器的所有特性
local features = compiler.features("c")
-- 獲取當(dāng)前c++語言編譯器的所有特性,啟用c++11標(biāo)準(zhǔn),否則獲取不到新標(biāo)準(zhǔn)的特性
local features = compiler.features("cxx", {config = {cxxflags = "-std=c++11"}})
-- 獲取當(dāng)前c++語言編譯器的所有特性,傳遞工程target的所有配置信息
local features = compiler.features("cxx", {target = target, config = {defines = "..", includedirs = ".."}})
所有c編譯器特性列表:
特性名 |
---|
c_static_assert |
c_restrict |
c_variadic_macros |
c_function_prototypes |
所有c++編譯器特性列表:
特性名 |
---|
cxx_variable_templates |
cxx_relaxed_constexpr |
cxx_aggregate_default_initializers |
cxx_contextual_conversions |
cxx_attribute_deprecated |
cxx_decltype_auto |
cxx_digit_separators |
cxx_generic_lambdas |
cxx_lambda_init_captures |
cxx_binary_literals |
cxx_return_type_deduction |
cxx_decltype_incomplete_return_types |
cxx_reference_qualified_functions |
cxx_alignof |
cxx_attributes |
cxx_inheriting_constructors |
cxx_thread_local |
cxx_alias_templates |
cxx_delegating_constructors |
cxx_extended_friend_declarations |
cxx_final |
cxx_nonstatic_member_init |
cxx_override |
cxx_user_literals |
cxx_constexpr |
cxx_defaulted_move_initializers |
cxx_enum_forward_declarations |
cxx_noexcept |
cxx_nullptr |
cxx_range_for |
cxx_unrestricted_unions |
cxx_explicit_conversions |
cxx_lambdas |
cxx_local_type_template_args |
cxx_raw_string_literals |
cxx_auto_type |
cxx_defaulted_functions |
cxx_deleted_functions |
cxx_generalized_initializers |
cxx_inline_namespaces |
cxx_sizeof_member |
cxx_strong_enums |
cxx_trailing_return_types |
cxx_unicode_literals |
cxx_uniform_initialization |
cxx_variadic_templates |
cxx_decltype |
cxx_default_function_template_args |
cxx_long_long_type |
cxx_right_angle_brackets |
cxx_rvalue_references |
cxx_static_assert |
cxx_extern_templates |
cxx_func_identifier |
cxx_variadic_macros |
cxx_template_template_parameters |
雖然通過lib.detect.has_features也能獲取,但是那個(gè)接口更加底層,需要指定編譯器名稱。 而此接口只需要指定需要檢測的特姓名稱列表,就能自動切換選擇當(dāng)前支持的編譯器,然后判斷指定特性在當(dāng)前的編譯器中是否支持。
if compiler.has_features("c_static_assert") then
-- ok
end
if compiler.has_features({"c_static_assert", "cxx_constexpr"}, {languages = "cxx11"}) then
-- ok
end
if compiler.has_features("cxx_constexpr", {target = target, defines = "..", includedirs = ".."}) then
-- ok
end
具體特性名有哪些,可以參考:compiler.features。
用于獲取工程編譯時(shí)候的配置信息,也就是xmake f|config --xxx=val
傳入的參數(shù)選項(xiàng)值。
接口 | 描述 | 支持版本 |
---|---|---|
config.get | 獲取指定配置值 | >= 2.0.1 |
config.load | 加載配置 | >= 2.0.1 |
config.arch | 獲取當(dāng)前工程的架構(gòu)配置 | >= 2.0.1 |
config.plat | 獲取當(dāng)前工程的平臺配置 | >= 2.0.1 |
config.mode | 獲取當(dāng)前工程的編譯模式配置 | >= 2.0.1 |
config.buildir | 獲取當(dāng)前工程的輸出目錄配置 | >= 2.0.1 |
config.directory | 獲取當(dāng)前工程的配置信息目錄 | >= 2.0.1 |
config.dump | 打印輸出當(dāng)前工程的所有配置信息 | >= 2.0.1 |
用于獲取xmake f|config --xxx=val
的配置值,例如:
target("test")
on_run(function (target)
-- 導(dǎo)入配置模塊
import("core.project.config")
-- 獲取配置值
print(config.get("xxx"))
end)
一般用于插件開發(fā)中,插件任務(wù)中不像工程的自定義腳本,環(huán)境需要自己初始化加載,默認(rèn)工程配置是沒有被加載的,如果要用config.get接口獲取工程配置,那么需要先:
-- 導(dǎo)入配置模塊
import("core.project.config")
function main(...)
-- 先加載工程配置
config.load()
-- 獲取配置值
print(config.get("xxx"))
end
也就是獲取xmake f|config --arch=armv7
的平臺配置,相當(dāng)于config.get("arch")
。
也就是獲取xmake f|config --plat=iphoneos
的平臺配置,相當(dāng)于config.get("plat")
。
也就是獲取xmake f|config --mode=debug
的平臺配置,相當(dāng)于config.get("mode")
。
也就是獲取xmake f|config -o /tmp/output
的平臺配置,相當(dāng)于config.get("buildir")
。
獲取工程配置的存儲目錄,默認(rèn)為:projectdir/.config
輸出結(jié)果例如:
{
sh = "xcrun -sdk macosx clang++"
, xcode_dir = "/Applications/Xcode.app"
, ar = "xcrun -sdk macosx ar"
, small = true
, object = false
, arch = "x86_64"
, xcode_sdkver = "10.12"
, ex = "xcrun -sdk macosx ar"
, cc = "xcrun -sdk macosx clang"
, rc = "rustc"
, plat = "macosx"
, micro = false
, host = "macosx"
, as = "xcrun -sdk macosx clang"
, dc = "dmd"
, gc = "go"
, openssl = false
, ccache = "ccache"
, cxx = "xcrun -sdk macosx clang"
, sc = "xcrun -sdk macosx swiftc"
, mm = "xcrun -sdk macosx clang"
, buildir = "build"
, mxx = "xcrun -sdk macosx clang++"
, ld = "xcrun -sdk macosx clang++"
, mode = "release"
, kind = "static"
}
<p class="tip"> 此模塊自2.1.5版本后遷移至core.base.global。 </p>
<p class="tip"> 此模塊自2.1.5版本后遷移至core.base.task。 </p>
用于獲取當(dāng)前工程的一些描述信息,也就是在xmake.lua
工程描述文件中定義的配置信息,例如:target、option等。
接口 | 描述 | 支持版本 |
---|---|---|
project.load | 加載工程配置 | >= 2.0.1 (2.1.5廢棄) |
project.directory | 獲取工程目錄 | >= 2.0.1 |
project.target | 獲取指定工程目標(biāo)對象 | >= 2.0.1 |
project.targets | 獲取工程目標(biāo)對象列表 | >= 2.0.1 |
project.option | 獲取指定的選項(xiàng)對象 | >= 2.1.5 |
project.options | 獲取工程所有的選項(xiàng)對象 | >= 2.1.5 |
project.name | 獲取當(dāng)前工程名 | >= 2.0.1 |
project.version | 獲取當(dāng)前工程版本號 | >= 2.0.1 |
僅在插件中使用,因?yàn)檫@個(gè)時(shí)候還沒有加載工程配置信息,在工程目標(biāo)的自定義腳本中,不需要執(zhí)行此操作,就可以直接訪問工程配置。
-- 導(dǎo)入工程模塊
import("core.project.project")
-- 插件入口
function main(...)
-- 加載工程描述配置
project.load()
-- 訪問工程描述,例如獲取指定工程目標(biāo)
local target = project.target("test")
end
<p class="tip"> 2.1.5版本后,不在需要,工程加載會自動在合適時(shí)機(jī)延遲加載。 </p>
獲取當(dāng)前工程目錄,也就是xmake -P xxx
中指定的目錄,否則為默認(rèn)當(dāng)前xmake
命令執(zhí)行目錄。
<p class="tip"> 2.1.5版本后,建議使用os.projectdir來獲取。 </p>
獲取和訪問指定工程目標(biāo)配置,例如:
local target = project.target("test")
if target then
-- 獲取目標(biāo)文件名
print(target:targetfile())
-- 獲取目標(biāo)類型,也就是:binary, static, shared
print(target:targetkind())
-- 獲取目標(biāo)名
print(target:name())
-- 獲取目標(biāo)源文件
local sourcefiles = target:sourcefiles()
-- 獲取目標(biāo)安裝頭文件列表
local srcheaders, dstheaders = target:headerfiles()
-- 獲取目標(biāo)依賴
print(target:get("deps"))
end
返回當(dāng)前工程的所有編譯目標(biāo),例如:
for targetname, target in pairs(project.targets())
print(target:targetfile())
end
獲取和訪問工程中指定的選項(xiàng)對象,例如:
local option = project.option("test")
if option:enabled() then
option:enable(false)
end
返回當(dāng)前工程的所有編譯目標(biāo),例如:
for optionname, option in pairs(project.options())
print(option:enabled())
end
也就是獲取set_project的工程名配置。
print(project.name())
也就是獲取set_version的工程版本配置。
print(project.version())
用于獲取編譯語言相關(guān)信息,一般用于代碼文件的操作。
接口 | 描述 | 支持版本 |
---|---|---|
language.extensions | 獲取所有語言的代碼后綴名列表 | >= 2.1.1 |
language.targetkinds | 獲取所有語言的目標(biāo)類型列表 | >= 2.1.1 |
language.sourcekinds | 獲取所有語言的源文件類型列表 | >= 2.1.1 |
language.sourceflags | 加載所有語言的源文件編譯選項(xiàng)名列表 | >= 2.1.1 |
language.load | 加載指定語言 | >= 2.1.1 |
language.load_sk | 從源文件類型加載指定語言 | >= 2.1.1 |
language.load_ex | 從源文件后綴名加載指定語言 | >= 2.1.1 |
language.sourcekind_of | 獲取指定源文件的源文件類型 | >= 2.1.1 |
獲取結(jié)果如下:
{
[".c"] = cc
, [".cc"] = cxx
, [".cpp"] = cxx
, [".m"] = mm
, [".mm"] = mxx
, [".swift"] = sc
, [".go"] = gc
}
獲取結(jié)果如下:
{
binary = {"ld", "gc-ld", "dc-ld"}
, static = {"ar", "gc-ar", "dc-ar"}
, shared = {"sh", "dc-sh"}
}
獲取結(jié)果如下:
{
cc = ".c"
, cxx = {".cc", ".cpp", ".cxx"}
, mm = ".m"
, mxx = ".mm"
, sc = ".swift"
, gc = ".go"
, rc = ".rs"
, dc = ".d"
, as = {".s", ".S", ".asm"}
}
獲取結(jié)果如下:
{
cc = {"cflags", "cxflags"}
, cxx = {"cxxflags", "cxflags"}
, ...
}
從語言名稱加載具體語言對象,例如:
local lang = language.load("c++")
if lang then
print(lang:name())
end
從源文件類型:cc, cxx, mm, mxx, sc, gc, as ..
加載具體語言對象,例如:
local lang = language.load_sk("cxx")
if lang then
print(lang:name())
end
從源文件后綴名:.cc, .c, .cpp, .mm, .swift, .go ..
加載具體語言對象,例如:
local lang = language.load_sk(".cpp")
if lang then
print(lang:name())
end
也就是從給定的一個(gè)源文件路徑,獲取它是屬于那種源文件類型,例如:
print(language.sourcekind_of("/xxxx/test.cpp"))
顯示結(jié)果為:cxx
,也就是c++
類型,具體對應(yīng)列表見:language.sourcekinds
平臺信息相關(guān)操作
接口 | 描述 | 支持版本 |
---|---|---|
platform.get | 獲取指定平臺相關(guān)配置信息 | >= 2.0.1 |
獲取平臺配置xmake.lua
中設(shè)置的信息,一般只有在寫插件的時(shí)候會用到,例如:
-- 獲取當(dāng)前平臺的所有支持架構(gòu)
print(platform.get("archs"))
-- 獲取指定iphoneos平臺的目標(biāo)文件格式信息
local formats = platform.get("formats", "iphoneos")
table.dump(formats)
具體有哪些可讀的平臺配置信息,可參考:platform
環(huán)境相關(guān)操作,用于進(jìn)入和離開指定環(huán)境變量對應(yīng)的終端環(huán)境,一般用于path
環(huán)境的進(jìn)入和離開,尤其是一些需要特定環(huán)境的構(gòu)建工具,例如:msvc的工具鏈。
接口 | 描述 | 支持版本 |
---|---|---|
environment.enter | 進(jìn)入指定環(huán)境 | >= 2.0.1 |
environment.leave | 離開指定環(huán)境 | >= 2.0.1 |
目前支持的環(huán)境有:
接口 | 描述 | 支持版本 |
---|---|---|
toolchains | 工具鏈執(zhí)行環(huán)境 | >= 2.0.1 |
進(jìn)入指定環(huán)境,例如msvc有自己的環(huán)境變量環(huán)境用于運(yùn)行構(gòu)建工具,例如:cl.exe
, link.exe
這些,這個(gè)時(shí)候想要在xmake里面運(yùn)行他們,需要:
-- 進(jìn)入工具鏈環(huán)境
environment.enter("toolchains")
-- 這個(gè)時(shí)候運(yùn)行cl.exe才能正常運(yùn)行,這個(gè)時(shí)候的path等環(huán)境變量都會進(jìn)入msvc的環(huán)境模式
os.run("cl.exe ..")
-- 離開工具鏈環(huán)境
environment.leave("toolchains")
因此為了通用性,默認(rèn)xmake編譯事都會設(shè)置這個(gè)環(huán)境,在linux下基本上內(nèi)部環(huán)境不需要特殊切換,目前僅對windows下msvc進(jìn)行了處理。
具體使用見:environment.enter
此模塊提供了非常強(qiáng)大的探測功能,用于探測程序、編譯器、語言特性、依賴包等。
<p class="tip">
此模塊的接口分散在多個(gè)模塊目錄中,盡量通過導(dǎo)入單個(gè)接口來使用,這樣效率更高,例如:import("lib.detect.find_package")
,而不是通過import("lib.detect")
導(dǎo)入所有來調(diào)用。
</p>
接口 | 描述 | 支持版本 |
---|---|---|
detect.find_file | 查找文件 | >= 2.1.5 |
detect.find_path | 查找文件路徑 | >= 2.1.5 |
detect.find_library | 查找?guī)煳募?/td> | >= 2.1.5 |
detect.find_program | 查找可執(zhí)行程序 | >= 2.1.5 |
detect.find_programver | 查找可執(zhí)行程序版本號 | >= 2.1.5 |
detect.find_package | 查找包文件,包含庫文件和搜索路徑 | >= 2.1.5 |
detect.find_tool | 查找工具 | >= 2.1.5 |
detect.find_toolname | 查找工具名 | >= 2.1.5 |
detect.features | 獲取指定工具的所有特性 | >= 2.1.5 |
detect.has_features | 判斷指定特性是否支持 | >= 2.1.5 |
detect.has_flags | 判斷指定參數(shù)選項(xiàng)是否支持 | >= 2.1.5 |
detect.has_cfuncs | 判斷指定c函數(shù)是否存在 | >= 2.1.5 |
detect.has_cxxfuncs | 判斷指定c++函數(shù)是否存在 | >= 2.1.5 |
detect.has_cincludes | 判斷指定c頭文件是否存在 | >= 2.1.5 |
detect.has_cxxincludess | 判斷指定c++頭文件是否存在 | >= 2.1.5 |
detect.has_ctypes | 判斷指定c類型是否存在 | >= 2.1.5 |
detect.has_cxxtypes | 判斷指定c++類型是否存在 | >= 2.1.5 |
detect.check_cxsnippets | 檢測c/c++代碼片段是否能夠編譯通過 | >= 2.1.5 |
這個(gè)接口提供了比os.files更加強(qiáng)大的工程, 可以同時(shí)指定多個(gè)搜索目錄,并且還能對每個(gè)目錄指定附加的子目錄,來模式匹配查找,相當(dāng)于是os.files的增強(qiáng)版。
例如:
import("lib.detect.find_file")
local file = find_file("ccache", { "/usr/bin", "/usr/local/bin"})
如果找到,返回的結(jié)果是:/usr/bin/ccache
它同時(shí)也支持模式匹配路徑,進(jìn)行遞歸查找,類似os.files
:
local file = find_file("test.h", { "/usr/include", "/usr/local/include/**"})
不僅如此,里面的路徑也支持內(nèi)建變量,來從環(huán)境變量和注冊表中獲取路徑進(jìn)行查找:
local file = find_file("xxx.h", { "$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name)"})
如果路徑規(guī)則比較復(fù)雜多變,還可以通過自定義腳本來動態(tài)生成路徑傳入:
local file = find_file("xxx.h", { "$(env PATH)", function () return val("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name"):match("\"(.-)\"") end})
大部分場合下,上面的使用已經(jīng)滿足各種需求了,如果還需要一些擴(kuò)展功能,可以通過傳入第三個(gè)參數(shù),自定義一些可選配置,例如:
local file = find_file("test.h", { "/usr", "/usr/local"}, {suffixes = {"/include", "/lib"}})
通過指定suffixes子目錄列表,可以擴(kuò)展路徑列表(第二個(gè)參數(shù)),使得實(shí)際的搜索目錄擴(kuò)展為:
/usr/include
/usr/lib
/usr/local/include
/usr/local/lib
并且不用改變路徑列表,就能動態(tài)切換子目錄來搜索文件。
<p class="tip">
我們也可以通過xmake lua
插件來快速調(diào)用和測試此接口:xmake lua lib.detect.find_file test.h /usr/local
</p>
這個(gè)接口的用法跟lib.detect.find_file類似,唯一的區(qū)別是返回的結(jié)果不同。 此接口查找到傳入的文件路徑后,返回的是對應(yīng)的搜索路徑,而不是文件路徑本身,一般用于查找文件對應(yīng)的父目錄位置。
import("lib.detect.find_path")
local p = find_path("include/test.h", { "/usr", "/usr/local"})
上述代碼如果查找成功,則返回:/usr/local
,如果test.h
在/usr/local/include/test.h
的話。
還有一個(gè)區(qū)別就是,這個(gè)接口傳入不只是文件路徑,還可以傳入目錄路徑來查找:
local p = find_path("lib/xxx", { "$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name)"})
同樣,此接口也支持模式匹配和后綴子目錄:
local p = find_path("include/*.h", { "/usr", "/usr/local/**"}, {suffixes = "/subdir"})
此接口用于指定的搜索目錄中查找?guī)煳募o態(tài)庫,動態(tài)庫),例如:
import("lib.detect.find_library")
local library = find_library("crypto", {"/usr/lib", "/usr/local/lib"})
在macosx上運(yùn)行,返回的結(jié)果如下:
{
filename = libcrypto.dylib
, linkdir = /usr/lib
, link = crypto
, kind = shared
}
如果不指定是否需要靜態(tài)庫還是動態(tài)庫,那么此接口會自動選擇一個(gè)存在的庫(有可能是靜態(tài)庫、也有可能是動態(tài)庫)進(jìn)行返回。
如果需要強(qiáng)制指定需要查找的庫類型,可以指定kind參數(shù)為(static/shared
):
local library = find_library("crypto", {"/usr/lib", "/usr/local/lib"}, {kind = "static"})
此接口也支持suffixes后綴子目錄搜索和模式匹配操作:
local library = find_library("cryp*", {"/usr", "/usr/local"}, {suffixes = "/lib"})
這個(gè)接口比lib.detect.find_tool較為原始底層,通過指定的參數(shù)目錄來查找可執(zhí)行程序。
import("lib.detect.find_program")
local program = find_program("ccache")
上述代碼猶如沒有傳遞搜索目錄,所以它會嘗試直接執(zhí)行指定程序,如果運(yùn)行ok,那么直接返回:ccache
,表示查找成功。
指定搜索目錄,修改嘗試運(yùn)行的檢測命令參數(shù)(默認(rèn)是:ccache --version
):
local program = find_program("ccache", {"/usr/bin", "/usr/local/bin"}, "--help")
上述代碼會嘗試運(yùn)行:/usr/bin/ccache --help
,如果運(yùn)行成功,則返回:/usr/bin/ccache
。
如果--help
也沒法滿足需求,有些程序沒有--version/--help
參數(shù),那么可以自定義運(yùn)行腳本,來運(yùn)行檢測:
local program = find_program("ccache", {"/usr/bin", "/usr/local/bin"}, function (program) os.run("%s -h", program) end)
同樣,搜索路徑列表支持內(nèi)建變量和自定義腳本:
local program = find_program("ccache", {"$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug;Debugger)"})
local program = find_program("ccache", {"$(env PATH)", function () return "/usr/local/bin" end})
<p class="tip">
為了加速頻發(fā)查找的效率,此接口是默認(rèn)自帶cache的,所以就算頻繁查找相同的程序,也不會花太多時(shí)間。
如果要禁用cache,可以在工程目錄執(zhí)行xmake f -c
清除本地cache。
</p>
我們也可以通過xmake lua lib.detect.find_program ccache
來快速測試。
import("lib.detect.find_programver")
local programver = find_programver("ccache")
返回結(jié)果為:3.2.2
默認(rèn)它會通過ccache --version
嘗試獲取版本,如果不存在此參數(shù),可以自己指定其他參數(shù):
local version = find_programver("ccache", "-v")
甚至自定義版本獲取腳本:
local version = find_programver("ccache", function () return os.iorun("ccache --version") end)
對于版本號的提取規(guī)則,如果內(nèi)置的匹配模式不滿足要求,也可以自定義:
local version = find_programver("ccache", "--version", "(%d+%.?%d*%.?%d*.-)%s")
local version = find_programver("ccache", "--version", function (output) return output:match("(%d+%.?%d*%.?%d*.-)%s") end)
<p class="tip">
為了加速頻發(fā)查找的效率,此接口是默認(rèn)自帶cache的,如果要禁用cache,可以在工程目錄執(zhí)行xmake f -c
清除本地cache。
</p>
我們也可以通過xmake lua lib.detect.find_programver ccache
來快速測試。
此接口也是用于查找?guī)煳募?,但是?a href="#detect-find_library">lib.detect.find_library更加上層,也更為強(qiáng)大和簡單易用,因?yàn)樗且园鼮榱Χ冗M(jìn)行查找。
那怎樣算是一個(gè)完整的包,它包含:
defines
等例如我們查找一個(gè)openssl包:
import("lib.detect.find_package")
local package = find_package("openssl")
返回的結(jié)果如下:
{links = {"ssl", "crypto", "z"}, linkdirs = {"/usr/local/lib"}, includedirs = {"/usr/local/include"}}
如果查找成功,則返回一個(gè)包含所有包信息的table,如果失敗返回nil
這里的返回結(jié)果可以直接作為target:add
, option:add
的參數(shù)傳入,用于動態(tài)增加target/option
的配置:
option("zlib")
set_showmenu(true)
before_check(function (option)
import("lib.detect.find_package")
option:add(find_package("zlib"))
end)
target("test")
on_load(function (target)
import("lib.detect.find_package")
target:add(find_package("zlib"))
end)
如果系統(tǒng)上裝有homebrew
, pkg-config
等第三方工具,那么此接口會嘗試使用它們?nèi)ジ倪M(jìn)查找結(jié)果。
我們也可以通過指定版本號,來選擇查找指定版本的包(如果這個(gè)包獲取不到版本信息或者沒有匹配版本的包,則返回nil):
local package = find_package("openssl", {version = "1.0.1"})
默認(rèn)情況下查找的包是根據(jù)如下規(guī)則匹配平臺,架構(gòu)和模式的:
{plat = "iphoneos", arch = "arm64", mode = "release"}
,則優(yōu)先匹配,例如:find_package("openssl", {plat = "iphoneos"})
。config.get("plat")
, config.get("arch")
和config.get("mode")
獲取平臺架構(gòu)進(jìn)行匹配。os.host()
和os.arch()
中進(jìn)行匹配,也就是當(dāng)前主機(jī)的平臺架構(gòu)環(huán)境。
如果系統(tǒng)的庫目錄以及pkg-config
都不能滿足需求,找不到包,那么可以自己手動設(shè)置搜索路徑:
local package = find_package("openssl", {linkdirs = {"/usr/lib", "/usr/local/lib"}, includedirs = "/usr/local/include"})
也可以同時(shí)指定需要搜索的鏈接名,頭文件名:
local package = find_package("openssl", {links = {"ssl", "crypto"}, includes = "ssl.h"}})
甚至可以指定xmake的packagedir/*.pkg
包目錄,用于查找對應(yīng)的openssl.pkg
包,一般用于查找內(nèi)置在工程目錄中的本地包。
例如,tbox工程內(nèi)置了pkg/openssl.pkg
本地包載項(xiàng)目中,我們可以通過下面的腳本,傳入{packagedirs = ""}
參數(shù)優(yōu)先查找本地包,如果找不到再去找系統(tǒng)包。
target("test")
on_load(function (target)
import("lib.detect.find_package")
target:add(find_package("openssl", {packagedirs = path.join(os.projectdir(), "pkg")}))
end)
總結(jié)下,現(xiàn)在的查找順序:
{packagedirs = ""}
參數(shù),優(yōu)先從這個(gè)參數(shù)指定的路徑中查找本地包*.pkg
xmake/modules
下面存在detect.packages.find_xxx
腳本,那么嘗試調(diào)用此腳本來改進(jìn)查找結(jié)果pkg-config
,并且查找的是系統(tǒng)環(huán)境的庫,則嘗試使用pkg-config
提供的路徑和鏈接信息進(jìn)行查找homebrew
,并且查找的是系統(tǒng)環(huán)境的庫,則嘗試使用brew --prefix xxx
提供的信息進(jìn)行查找/usr/lib
, /usr/include
中進(jìn)行查找
這里需要著重說下第二點(diǎn),通過在detect.packages.find_xxx
腳本來改進(jìn)查找結(jié)果,很多時(shí)候自動的包探測是沒法完全探測到包路徑的,
尤其是針對windows平臺,沒有默認(rèn)的庫目錄,也沒有包管理app,很多庫裝的時(shí)候,都是自己所處放置在系統(tǒng)目錄,或者添加注冊表項(xiàng)。
因此查找起來沒有同意的規(guī)則,這個(gè)時(shí)候,就可以自定義一個(gè)查找腳本,去改進(jìn)find_package
的查找機(jī)制,對指定包進(jìn)行更精準(zhǔn)的查找。
在xmake自帶的xmake/modules/detect/packages
目錄下,已經(jīng)有許多的內(nèi)置包腳本,來對常用的包進(jìn)行更好的查找支持。
當(dāng)然這不可能滿足所有用戶的需求,如果用戶需要的包還是找不到,那么可以自己定義一個(gè)查找腳本,例如:
查找一個(gè)名為openssl
的包,可以編寫一個(gè)find_openssl.lua
的腳本放置在工程目錄:
projectdir
- xmake
- modules
- detect/package/find_openssl.lua
然后在工程的xmake.lua
文件的開頭指定下這個(gè)modules的目錄:
add_moduledirs("$(projectdir)/xmake/modules")
這樣xmake就能找到自定義的擴(kuò)展模塊了。
接下來我們看下find_openssl.lua
的實(shí)現(xiàn):
-- imports
import("lib.detect.find_path")
import("lib.detect.find_library")
-- find openssl
--
-- @param opt the package options. e.g. see the options of find_package()
--
-- @return see the return value of find_package()
--
function main(opt)
-- for windows platform
--
-- http://www.slproweb.com/products/Win32OpenSSL.html
--
if opt.plat == "windows" then
-- init bits
local bits = ifelse(opt.arch == "x64", "64", "32")
-- init search pathes
local pathes = {"$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL %(" .. bits .. "-bit%)_is1;Inno Setup: App Path)",
"$(env PROGRAMFILES)/OpenSSL",
"$(env PROGRAMFILES)/OpenSSL-Win" .. bits,
"C:/OpenSSL",
"C:/OpenSSL-Win" .. bits}
-- find library
local result = {links = {}, linkdirs = {}, includedirs = {}}
for _, name in ipairs({"libssl", "libcrypto"}) do
local linkinfo = find_library(name, pathes, {suffixes = "lib"})
if linkinfo then
table.insert(result.links, linkinfo.link)
table.insert(result.linkdirs, linkinfo.linkdir)
end
end
-- not found?
if #result.links ~= 2 then
return
end
-- find include
table.insert(result.includedirs, find_path("openssl/ssl.h", pathes, {suffixes = "include"}))
-- ok
return result
end
end
里面對windows平臺進(jìn)行注冊表讀取,去查找指定的庫文件,其底層其實(shí)也是調(diào)用的find_library等接口。
<p class="tip">
為了加速頻發(fā)查找的效率,此接口是默認(rèn)自帶cache的,如果要禁用cache,可以在工程目錄執(zhí)行xmake f -c
清除本地cache。
也可以通過指定force參數(shù),來禁用cache,強(qiáng)制重新查找:find_package("openssl", {force = true})
</p>
我們也可以通過xmake lua lib.detect.find_package openssl
來快速測試。
此接口也是用于查找可執(zhí)行程序,不過比lib.detect.find_program更加的高級,功能也更加強(qiáng)大,它對可執(zhí)行程序進(jìn)行了封裝,提供了工具這個(gè)概念:
gcc
, clang
等xcrun -sdk macosx clang
其對應(yīng)關(guān)系如下:
toolname | program |
---|---|
clang | xcrun -sdk macosx clang |
gcc | /usr/toolchains/bin/arm-linux-gcc |
link | link.exe -lib |
lib.detect.find_program只能通過傳入的原始program命令或路徑,去判斷該程序是否存在。
而find_tool
則可以通過更加一致的toolname去查找工具,并且返回對應(yīng)的program完整命令路徑,例如:
import("lib.detect.find_tool")
local tool = find_tool("clang")
返回的結(jié)果為:{name = "clang", program = "clang"}
,這個(gè)時(shí)候還看不出區(qū)別,我們可以手動指定可執(zhí)行的命令:
local tool = find_tool("clang", {program = "xcrun -sdk macosx clang"})
返回的結(jié)果為:{name = "clang", program = "xcrun -sdk macosx clang"}
而在macosx下,gcc就是clang,如果我們執(zhí)行gcc --version
可以看到就是clang的一個(gè)馬甲,我們可以通過find_tool
接口進(jìn)行智能識別:
local tool = find_tool("gcc")
返回的結(jié)果為:{name = "clang", program = "gcc"}
通過這個(gè)結(jié)果就可以看的區(qū)別來了,工具名實(shí)際會被標(biāo)示為clang,但是可執(zhí)行的命令用的是gcc。
我們也可以指定{version = true}
參數(shù)去獲取工具的版本,并且指定一個(gè)自定義的搜索路徑,也支持內(nèi)建變量和自定義腳本哦:
local tool = find_tool("clang", {version = true, {pathes = {"/usr/bin", "/usr/local/bin", "$(env PATH)", function () return "/usr/xxx/bin" end}})
返回的結(jié)果為:{name = "clang", program = "/usr/bin/clang", version = "4.0"}
這個(gè)接口是對find_program
的上層封裝,因此也支持自定義腳本檢測:
local tool = find_tool("clang", {check = "--help"})
local tool = find_tool("clang", {check = function (tool) os.run("%s -h", tool) end})
最后總結(jié)下,find_tool
的查找流程:
{program = "xxx"}
的參數(shù)來嘗試運(yùn)行和檢測。xmake/modules/detect/tools
下存在detect.tools.find_xxx
腳本,則調(diào)用此腳本進(jìn)行更加精準(zhǔn)的檢測。/usr/bin
,/usr/local/bin
等系統(tǒng)目錄進(jìn)行檢測。
我們也可以在工程xmake.lua
中add_moduledirs
指定的模塊目錄中,添加自定義查找腳本,來改進(jìn)檢測機(jī)制:
projectdir
- xmake/modules
- detect/tools/find_xxx.lua
例如我們自定義一個(gè)find_7z.lua
的查找腳本:
import("lib.detect.find_program")
import("lib.detect.find_programver")
function main(opt)
-- init options
opt = opt or {}
-- find program
local program = find_program(opt.program or "7z", opt.pathes, opt.check or "--help")
-- find program version
local version = nil
if program and opt and opt.version then
version = find_programver(program, "--help", "(%d+%.?%d*)%s")
end
-- ok?
return program, version
end
將它放置到工程的模塊目錄下后,執(zhí)行:xmake l lib.detect.find_tool 7z
就可以查找到了。
<p class="tip">
為了加速頻發(fā)查找的效率,此接口是默認(rèn)自帶cache的,如果要禁用cache,可以在工程目錄執(zhí)行xmake f -c
清除本地cache。
</p>
我們也可以通過xmake lua lib.detect.find_tool clang
來快速測試。
通過program命令匹配對應(yīng)的工具名,例如:
program | toolname |
---|---|
xcrun -sdk macosx clang |
clang |
/usr/bin/arm-linux-gcc |
gcc |
link.exe -lib |
link |
gcc-5 |
gcc |
arm-android-clang++ |
clangxx |
pkg-config |
pkg_config |
toolname相比program,更能唯一標(biāo)示某個(gè)工具,也方便查找和加載對應(yīng)的腳本find_xxx.lua
。
此接口跟compiler.features類似,區(qū)別就是此接口更加的原始,傳入的參數(shù)是實(shí)際的工具名toolname。
并且此接口不僅能夠獲取編譯器的特性,任何工具的特性都可以獲取,因此更加通用。
import("lib.detect.features")
local features = features("clang")
local features = features("clang", {flags = "-O0", program = "xcrun -sdk macosx clang"})
local features = features("clang", {flags = {"-g", "-O0", "-std=c++11"}})
通過傳入flags,可以改變特性的獲取結(jié)果,例如一些c++11的特性,默認(rèn)情況下獲取不到,通過啟用-std=c++11
后,就可以獲取到了。
所有編譯器的特性列表,可以見:compiler.features。
此接口跟compiler.has_features類似,但是更加原始,傳入的參數(shù)是實(shí)際的工具名toolname。
并且此接口不僅能夠判斷編譯器的特性,任何工具的特性都可以判斷,因此更加通用。
import("lib.detect.has_features")
local features = has_features("clang", "cxx_constexpr")
local features = has_features("clang", {"cxx_constexpr", "c_static_assert"}, {flags = {"-g", "-O0"}, program = "xcrun -sdk macosx clang"})
local features = has_features("clang", {"cxx_constexpr", "c_static_assert"}, {flags = "-g"})
如果指定的特性列表存在,則返回實(shí)際支持的特性子列表,如果都不支持,則返回nil,我們也可以通過指定flags去改變特性的獲取規(guī)則。
所有編譯器的特性列表,可以見:compiler.features。
此接口跟compiler.has_flags類似,但是更加原始,傳入的參數(shù)是實(shí)際的工具名toolname。
import("lib.detect.has_flags")
local ok = has_flags("clang", "-g")
local ok = has_flags("clang", {"-g", "-O0"}, {program = "xcrun -sdk macosx clang"})
local ok = has_flags("clang", "-g -O0", {toolkind = "cxx"})
如果檢測通過,則返回true。
此接口的檢測做了一些優(yōu)化,除了cache機(jī)制外,大部分場合下,會去拉取工具的選項(xiàng)列表(--help
)直接判斷,如果選項(xiàng)列表里獲取不到的話,才會通過嘗試運(yùn)行的方式來檢測。
此接口是lib.detect.check_cxsnippets的簡化版本,僅用于檢測函數(shù)。
import("lib.detect.has_cfuncs")
local ok = has_cfuncs("setjmp")
local ok = has_cfuncs({"sigsetjmp((void*)0, 0)", "setjmp"}, {includes = "setjmp.h"})
對于函數(shù)的描述規(guī)則如下:
函數(shù)描述 | 說明 |
---|---|
sigsetjmp |
純函數(shù)名 |
sigsetjmp((void*)0, 0) |
函數(shù)調(diào)用 |
sigsetjmp{int a = 0; sigsetjmp((void*)a, a);} |
函數(shù)名 + {}塊 |
在最后的可選參數(shù)中,除了可以指定includes
外,還可以指定其他的一些參數(shù)用于控制編譯檢測的選項(xiàng)條件:
{ verbose = false, target = [target|option], includes = .., config = {linkdirs = .., links = .., defines = ..}}
其中verbose用于回顯檢測信息,target用于在檢測前追加target中的配置信息, 而config用于自定義配置跟target相關(guān)的編譯選項(xiàng)。
此接口跟lib.detect.has_cfuncs類似,請直接參考它的使用說明,唯一區(qū)別是這個(gè)接口用于檢測c++函數(shù)。
此接口是lib.detect.check_cxsnippets的簡化版本,僅用于檢測頭文件。
import("lib.detect.has_cincludes")
local ok = has_cincludes("stdio.h")
local ok = has_cincludes({"stdio.h", "stdlib.h"}, {target = target})
local ok = has_cincludes({"stdio.h", "stdlib.h"}, {config = {defines = "_GNU_SOURCE=1", languages = "cxx11"}})
此接口跟lib.detect.has_cincludess類似,請直接參考它的使用說明,唯一區(qū)別是這個(gè)接口用于檢測c++頭文件。
此接口是lib.detect.check_cxsnippets的簡化版本,僅用于檢測函數(shù)。
import("lib.detect.has_ctypes")
local ok = has_ctypes("wchar_t")
local ok = has_ctypes({"char", "wchar_t"}, {includes = "stdio.h"})
local ok = has_ctypes("wchar_t", {includes = {"stdio.h", "stdlib.h"}, config = {"defines = "_GNU_SOURCE=1", languages = "cxx11"}})
此接口跟lib.detect.has_ctypess類似,請直接參考它的使用說明,唯一區(qū)別是這個(gè)接口用于檢測c++類型。
通用的c/c++代碼片段檢測接口,通過傳入多個(gè)代碼片段列表,它會自動生成一個(gè)編譯文件,然后常識對它進(jìn)行編譯,如果編譯通過返回true。
對于一些復(fù)雜的編譯器特性,連compiler.has_features都無法檢測到的時(shí)候,可以通過此接口通過嘗試編譯來檢測它。
import("lib.detect.check_cxsnippets")
local ok = check_cxsnippets("void test() {}")
local ok = check_cxsnippets({"void test(){}", "#define TEST 1"}, {types = "wchar_t", includes = "stdio.h"})
此接口是detect.has_cfuncs, detect.has_cincludes和detect.has_ctypes等接口的通用版本,也更加底層。
因此我們可以用它來檢測:types, functions, includes 還有 links,或者是組合起來一起檢測。
第一個(gè)參數(shù)為代碼片段列表,一般用于一些自定義特性的檢測,如果為空,則可以僅僅檢測可選參數(shù)中條件,例如:
local ok = check_cxsnippets({}, {types = {"wchar_t", "char*"}, includes = "stdio.h", funcs = {"sigsetjmp", "sigsetjmp((void*)0, 0)"}})
上面那個(gè)調(diào)用,會去同時(shí)檢測types, includes和funcs是否都滿足,如果通過返回true。
還有其他一些可選參數(shù):
{ verbose = false, target = [target|option], sourcekind = "[cc|cxx]"}
其中verbose用于回顯檢測信息,target用于在檢測前追加target中的配置信息, sourcekind 用于指定編譯器等工具類型,例如傳入cxx
強(qiáng)制作為c++代碼來檢測。
此模塊提供http的各種操作支持,目前提供的接口如下:
接口 | 描述 | 支持版本 |
---|---|---|
http.download | 下載http文件 | >= 2.1.5 |
這個(gè)接口比較簡單,就是單純的下載文件。
import("net.http")
http.download("http://xmake.io", "/tmp/index.html")
此接口用于通過sudo
來運(yùn)行命令,并且提供了平臺一致性處理,對于一些需要root權(quán)限運(yùn)行的腳本,可以使用此接口。
<p class="warning"> 為了保證安全性,除非必須使用的場合,其他情況下盡量不要使用此接口。 </p>
接口 | 描述 | 支持版本 |
---|---|---|
sudo.has | 判斷sudo是否支持 | >= 2.1.5 |
sudo.run | 安靜運(yùn)行程序 | >= 2.1.5 |
sudo.runv | 安靜運(yùn)行程序,帶參數(shù)列表 | >= 2.1.5 |
sudo.exec | 回顯運(yùn)行程序 | >= 2.1.5 |
sudo.execv | 回顯運(yùn)行程序,帶參數(shù)列表 | >= 2.1.5 |
sudo.iorun | 運(yùn)行并獲取程序輸出內(nèi)容 | >= 2.1.5 |
sudo.iorunv | 運(yùn)行并獲取程序輸出內(nèi)容,帶參數(shù)列表 | >= 2.1.5 |
目前僅在macosx/linux
下支持sudo,windows上的管理員權(quán)限運(yùn)行暫時(shí)還不支持,因此建議使用前可以通過此接口判斷支持情況后,針對性處理。
import("privilege.sudo")
if sudo.has() then
sudo.run("rm /system/file")
end
具體用法可參考:os.run。
import("privilege.sudo")
sudo.run("rm /system/file")
具體用法可參考:os.runv。
具體用法可參考:os.exec。
具體用法可參考:os.execv。
具體用法可參考:os.iorun。
具體用法可參考:os.iorunv。
此接口提供了git各種命令的訪問接口,相對于直接調(diào)用git命令,此模塊提供了更加上層易用的封裝接口,并且提供對git的自動檢測和跨平臺處理。
<p class="tip"> 目前windows上,需要手動安裝git包后,才能檢測到,后續(xù)版本會提供自動集成git功能,用戶將不用關(guān)心如何安裝git,就可以直接使用。 </p>
接口 | 描述 | 支持版本 |
---|---|---|
git.clone | clone代碼庫 | >= 2.1.5 |
git.pull | 拉取代碼庫最新提交 | >= 2.1.5 |
git.clean | 清理代碼庫文件 | >= 2.1.5 |
git.checkout | 簽出指定分支版本 | >= 2.1.5 |
git.refs | 獲取所有引用列表 | >= 2.1.5 |
git.tags | 獲取所有標(biāo)記列表 | >= 2.1.5 |
git.branches | 獲取所有分支列表 | >= 2.1.5 |
此接口對應(yīng)git clone
命令
import("devel.git")
git.clone("git@github.com:tboox/xmake.git")
git.clone("git@github.com:tboox/xmake.git", {depth = 1, branch = "master", outputdir = "/tmp/xmake"})
此接口對應(yīng)git pull
命令
import("devel.git")
git.pull()
git.pull({remote = "origin", tags = true, branch = "master", repodir = "/tmp/xmake"})
此接口對應(yīng)git clean
命令
import("devel.git")
git.clean()
git.clean({repodir = "/tmp/xmake", force = true})
此接口對應(yīng)git checkout
命令
import("devel.git")
git.checkout("master", {repodir = "/tmp/xmake"})
git.checkout("v1.0.1", {repodir = "/tmp/xmake"})
此接口對應(yīng)git ls-remote --refs
命令
import("devel.git")
local refs = git.refs(url)
此接口對應(yīng)git ls-remote --tags
命令
import("devel.git")
local tags = git.tags(url)
此接口對應(yīng)git ls-remote --heads
命令
import("devel.git")
local branches = git.branches(url)
此模塊用于壓縮和解壓縮文件。
接口 | 描述 | 支持版本 |
---|---|---|
archive.extract | 解壓文件 | >= 2.1.5 |
支持大部分常用壓縮文件的解壓,它會自動檢測系統(tǒng)提供了哪些解壓工具,然后適配到最合適的解壓器對指定壓縮文件進(jìn)行解壓操作。
import("utils.archive")
archive.extract("/tmp/a.zip", "/tmp/outputdir")
archive.extract("/tmp/a.7z", "/tmp/outputdir")
archive.extract("/tmp/a.gzip", "/tmp/outputdir")
archive.extract("/tmp/a.tar.bz2", "/tmp/outputdir")
更多建議: