XMake完全支持插件模式,我們可以很方便的擴(kuò)展實(shí)現(xiàn)自己的插件,并且xmake也提供了一些內(nèi)建的使用插件。
我們可以執(zhí)行下 xmake -h
看下當(dāng)前支持的插件:
Plugins:
l, lua Run the lua script.
m, macro Run the given macro.
doxygen Generate the doxygen document.
hello Hello xmake!
project Create the project file.
接下來(lái)我們介紹下本文的重點(diǎn),一個(gè)簡(jiǎn)單的hello xmake插件的開(kāi)發(fā),代碼如下:
-- 定義一個(gè)名叫hello的插件任務(wù)
task("hello")
-- 設(shè)置類(lèi)型為插件
set_category("plugin")
-- 插件運(yùn)行的入口
on_run(function ()
-- 顯示hello xmake!
print("hello xmake!")
end)
-- 設(shè)置插件的命令行選項(xiàng),這里沒(méi)有任何參數(shù)選項(xiàng),僅僅顯示插件描述
set_menu {
-- usage
usage = "xmake hello [options]"
-- description
, description = "Hello xmake!"
-- options
, options = {}
}
這個(gè)插件的文件結(jié)構(gòu)如下:
hello
- xmake.lua
現(xiàn)在一個(gè)最簡(jiǎn)單的插件寫(xiě)完了,那怎么讓它被xmake檢測(cè)到呢,有三種方式:
xmake/plugins
,這個(gè)里面都是些內(nèi)建的插件~/.xmake/plugins
用戶(hù)全局目錄,這樣對(duì)當(dāng)前xmake 全局生效add_plugindirs("./hello")
添加當(dāng)前的工程的插件搜索目錄,這樣只對(duì)當(dāng)前工程生效接下來(lái),我們嘗試運(yùn)行下這個(gè)插件:
xmake hello
顯示結(jié)果:
hello xmake!
最后我們還可以在target自定義的腳本中運(yùn)行這個(gè)插件:
target("demo")
-- 構(gòu)建之后運(yùn)行插件
after_build(function (target)
-- 導(dǎo)入task模塊
import("core.project.task")
-- 運(yùn)行插件任務(wù)
task.run("hello")
end)
我們可以通過(guò)這個(gè)插件,快速記錄和回放我們平常頻繁使用到的一些xmake操作,來(lái)簡(jiǎn)化我們?nèi)粘5拈_(kāi)發(fā)工作。
它提供了一些功能:
## 開(kāi)始記錄宏
$ xmake macro --begin
## 執(zhí)行一些xmake命令
$ xmake f -p android --ndk=/xxx/ndk -a armv7-a
$ xmake p
$ xmake f -p mingw --sdk=/mingwsdk
$ xmake p
$ xmake f -p linux --sdk=/toolsdk --toolchains=/xxxx/bin
$ xmake p
$ xmake f -p iphoneos -a armv7
$ xmake p
$ xmake f -p iphoneos -a arm64
$ xmake p
$ xmake f -p iphoneos -a armv7s
$ xmake p
$ xmake f -p iphoneos -a i386
$ xmake p
$ xmake f -p iphoneos -a x86_64
$ xmake p
## 結(jié)束宏記錄,這里不設(shè)置宏名字,所以記錄的是一個(gè)匿名宏
xmake macro --end
## 回放一個(gè)匿名宏
$ xmake macro .
匿名宏的好處就是快速記錄,快速回放,如果需要長(zhǎng)久保存,就需要給宏取個(gè)名字。
$ xmake macro --begin
$ ...
$ xmake macro --end macroname
$ xmake macro macroname
導(dǎo)入指定的宏腳本或者宏目錄:
$ xmake macro --import=/xxx/macro.lua macroname
$ xmake macro --import=/xxx/macrodir
導(dǎo)出指定的宏到腳本或者目錄:
$ xmake macro --export=/xxx/macro.lua macroname
$ xmake macro --export=/xxx/macrodir
列舉所有xmake
內(nèi)置的宏腳本:
$ xmake macro --list
顯示指定的宏腳本內(nèi)容:
$ xmake macro --show macroname
我們也可以自己編寫(xiě)個(gè)宏腳本 macro.lua
然后導(dǎo)入到xmake中去。
function main()
os.exec("xmake f -p android --ndk=/xxx/ndk -a armv7-a")
os.exec("xmake p")
os.exec("xmake f -p mingw --sdk=/mingwsdk")
os.exec("xmake p")
os.exec("xmake f -p linux --sdk=/toolsdk --toolchains=/xxxx/bin")
os.exec("xmake p")
os.exec("xmake f -p iphoneos -a armv7")
os.exec("xmake p")
os.exec("xmake f -p iphoneos -a arm64")
os.exec("xmake p")
os.exec("xmake f -p iphoneos -a armv7s")
os.exec("xmake p")
os.exec("xmake f -p iphoneos -a i386")
os.exec("xmake p")
os.exec("xmake f -p iphoneos -a x86_64")
os.exec("xmake p")
end
導(dǎo)入到xmake,并且定義宏名字:
$ xmake macro --import=/xxx/macro.lua [macroname]
回放這個(gè)宏腳本:
$ xmake macro [.|macroname]
XMake 提供了一些內(nèi)置的宏腳本,來(lái)簡(jiǎn)化我們的日常開(kāi)發(fā)工作。
例如,我們可以使用 package
宏來(lái)對(duì)iphoneos
平臺(tái)的所有架構(gòu),一次性批量構(gòu)建和打包:
$ xmake macro package -p iphoneos
以上面提到的package
宏為例,我們看下其具體代碼,里面通過(guò)import
導(dǎo)入一些擴(kuò)展模塊,實(shí)現(xiàn)了復(fù)雜的腳本操作。
-- imports
import("core.base.option")
import("core.project.config")
import("core.project.project")
import("core.platform.platform")
-- the options
local options =
{
{'p', "plat", "kv", os.host(), "Set the platform." }
, {'f', "config", "kv", nil, "Pass the config arguments to \"xmake config\" .." }
, {'o', "outputdir", "kv", nil, "Set the output directory of the package." }
}
-- package all
--
-- .e.g
-- xmake m package
-- xmake m package -f "-m debug"
-- xmake m package -p linux
-- xmake m package -p iphoneos -f "-m debug --xxx ..." -o /tmp/xxx
-- xmake m package -f \"--mode=debug\"
--
function main(argv)
-- parse arguments
local args = option.parse(argv, options, "Package all architectures for the given the platform."
, ""
, "Usage: xmake macro package [options]")
-- package all archs
local plat = args.plat
for _, arch in ipairs(platform.archs(plat)) do
-- config it
os.exec("xmake f -p %s -a %s %s -c %s", plat, arch, args.config or "", ifelse(option.get("verbose"), "-v", ""))
-- package it
if args.outputdir then
os.exec("xmake p -o %s %s", args.outputdir, ifelse(option.get("verbose"), "-v", ""))
else
os.exec("xmake p %s", ifelse(option.get("verbose"), "-v", ""))
end
end
-- package universal for iphoneos, watchos ...
if plat == "iphoneos" or plat == "watchos" then
-- load configure
config.load()
-- load project
project.load()
-- enter the project directory
os.cd(project.directory())
-- the outputdir directory
local outputdir = args.outputdir or config.get("buildir")
-- package all targets
for _, target in pairs(project.targets()) do
-- get all modes
local modedirs = os.match(format("%s/%s.pkg/lib/*", outputdir, target:name()), true)
for _, modedir in ipairs(modedirs) do
-- get mode
local mode = path.basename(modedir)
-- make lipo arguments
local lipoargs = nil
for _, arch in ipairs(platform.archs(plat)) do
local archfile = format("%s/%s.pkg/lib/%s/%s/%s/%s", outputdir, target:name(), mode, plat, arch, path.filename(target:targetfile()))
if os.isfile(archfile) then
lipoargs = format("%s -arch %s %s", lipoargs or "", arch, archfile)
end
end
if lipoargs then
-- make full lipo arguments
lipoargs = format("-create %s -output %s/%s.pkg/lib/%s/%s/universal/%s", lipoargs, outputdir, target:name(), mode, plat, path.filename(target:targetfile()))
-- make universal directory
os.mkdir(format("%s/%s.pkg/lib/%s/%s/universal", outputdir, target:name(), mode, plat))
-- package all archs
os.execv("xmake", {"l", "lipo", lipoargs})
end
end
end
end
end
<p class="tip">
如果你想要獲取更多宏參數(shù)選項(xiàng)信息,請(qǐng)運(yùn)行: xmake macro --help
</p>
這個(gè)跟宏腳本類(lèi)似,只是省去了導(dǎo)入導(dǎo)出操作,直接指定lua腳本來(lái)加載運(yùn)行,這對(duì)于想要快速測(cè)試一些接口模塊,驗(yàn)證自己的某些思路,都是一個(gè)不錯(cuò)的方式。
我們先寫(xiě)個(gè)簡(jiǎn)單的lua腳本:
function main()
print("hello xmake!")
end
然后直接運(yùn)行它就行了:
$ xmake lua /tmp/test.lua
<p class="tip">
當(dāng)然,你也可以像宏腳本那樣,使用import
接口導(dǎo)入擴(kuò)展模塊,實(shí)現(xiàn)復(fù)雜的功能。
</p>
你可以運(yùn)行 xmake lua -l
來(lái)列舉所有內(nèi)置的腳本名,例如:
$ xmake lua -l
scripts:
cat
cp
echo
versioninfo
...
并且運(yùn)行它們:
$ xmake lua cat ~/file.txt
$ xmake lua echo "hello xmake"
$ xmake lua cp /tmp/file /tmp/file2
$ xmake lua versioninfo
有時(shí)候在交互模式下,運(yùn)行命令更加的方便測(cè)試和驗(yàn)證一些模塊和api,也更加的靈活,不需要再去額外寫(xiě)一個(gè)腳本文件來(lái)加載。
我們先看下,如何進(jìn)入交互模式:
## 不帶任何參數(shù)執(zhí)行,就可以進(jìn)入
$ xmake lua
>
## 進(jìn)行表達(dá)式計(jì)算
> 1 + 2
3
## 賦值和打印變量值
> a = 1
> a
1
## 多行輸入和執(zhí)行
> for _, v in pairs({1, 2, 3}) do
>> print(v)
>> end
1
2
3
我們也能夠通過(guò) import
來(lái)導(dǎo)入擴(kuò)展模塊:
> task = import("core.project.task")
> task.run("hello")
hello xmake!
如果要中途取消多行輸入,只需要輸入字符:q
就行了
> for _, v in ipairs({1, 2}) do
>> print(v)
>> q <-- 取消多行輸入,清空先前的輸入數(shù)據(jù)
> 1 + 2
3
XMake跟cmake
, premake
等其他一些構(gòu)建工具的區(qū)別在于:
<p class="warning">
xmake
默認(rèn)是直接構(gòu)建運(yùn)行的,生成第三方的IDE的工程文件僅僅作為插件
來(lái)提供。
</p>
這樣做的一個(gè)好處是:插件更加容易擴(kuò)展,維護(hù)也更加獨(dú)立和方便。
$ xmake project -k makefile
導(dǎo)出每個(gè)源文件的編譯信息,生成基于clang的編譯數(shù)據(jù)庫(kù)文件,json格式,可用于跟ide,編輯器,靜態(tài)分析工具進(jìn)行交互。
$ xmake project -k compile_commands
輸出的內(nèi)容格式如下:
[
{ "directory": "/home/user/llvm/build",
"command": "/usr/bin/clang++ -Irelative -DSOMEDEF=\"With spaces, quotes and \\-es.\" -c -o file.o file.cc",
"file": "file.cc" },
...
]
對(duì)于compile_commands
的詳細(xì)說(shuō)明見(jiàn):JSONCompilationDatabase
$ xmake project -k [vs2008|vs2013|vs2015|..]
v2.1.2以上版本,增強(qiáng)了vs201x版本工程的生成,支持多模式+多架構(gòu)生成,生成的時(shí)候只需要指定:
$ xmake project -k vs2017 -m "debug,release"
生成后的工程文件,同時(shí)支持debug|x86
, debug|x64
, release|x86
, release|x64
四種配置模式。
如果不想每次生成的時(shí)候,指定模式,可以把模式配置加到xmake.lua
的中,例如:
-- 配置當(dāng)前的工程,支持哪些編譯模式
set_modes("debug", "release")
具體set_modes
的使用,可以參考對(duì)應(yīng)的接口手冊(cè)文檔。
請(qǐng)先確保本機(jī)已安裝doxygen
工具,然后在工程目錄下運(yùn)行:
$ xmake doxygen
請(qǐng)到插件倉(cāng)庫(kù)進(jìn)行下載安裝: xmake-plugins.
這僅僅是一個(gè)小插件,ios開(kāi)發(fā)的同學(xué),可能會(huì)用的到。
$ xmake app2ipa --icon=/xxx.png /xxx/ios.app -o /xxx.ios.ipa
更多建議: