XMake 插件開(kāi)發(fā)

2018-10-12 19:52 更新

插件開(kāi)發(fā)

簡(jiǎn)介

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.

  • lua: 運(yùn)行l(wèi)ua腳本的插件
  • macro: 這個(gè)很實(shí)用,宏腳本插件,可以手動(dòng)錄制多條xmake命令并且回放,也可以通過(guò)腳本實(shí)現(xiàn)一些復(fù)雜的宏腳本,這個(gè)我們后續(xù)會(huì)更加詳細(xì)的介紹
  • doxygen:一鍵生成doxygen文檔的插件
  • hello: 插件demo,僅僅顯示一句話:'hello xmake!'
  • project: 生成工程文件的插件,目前僅支持(makefile),后續(xù)還會(huì)支持(vs,xcode等工程)的生成

快速開(kāi)始

接下來(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è)到呢,有三種方式:

  1. 把 hello 這個(gè)文件夾放置在 xmake的插件安裝目錄 xmake/plugins,這個(gè)里面都是些內(nèi)建的插件
  2. 把 hello 文件夾放置在 ~/.xmake/plugins 用戶(hù)全局目錄,這樣對(duì)當(dāng)前xmake 全局生效
  3. 把 hello 文件夾放置在任意地方,通過(guò)在工程描述文件xmake.lua中調(diào)用add_plugindirs("./hello") 添加當(dāng)前的工程的插件搜索目錄,這樣只對(duì)當(dāng)前工程生效

運(yùn)行插件

接下來(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)

內(nèi)置插件

宏記錄和回放

簡(jiǎn)介

我們可以通過(guò)這個(gè)插件,快速記錄和回放我們平常頻繁使用到的一些xmake操作,來(lái)簡(jiǎn)化我們?nèi)粘5拈_(kāi)發(fā)工作。

它提供了一些功能:

  • 手動(dòng)記錄和回放多條執(zhí)行過(guò)的xmake命令
  • 支持快速的匿名宏創(chuàng)建和回放
  • 支持命名宏的長(zhǎng)久記錄和重用
  • 支持宏腳本的批量導(dǎo)入和導(dǎo)出
  • 支持宏腳本的刪除、顯示等管理功能
  • 支持自定義高級(jí)宏腳本,以及參數(shù)配置

記錄操作

## 開(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)入導(dǎo)出宏

導(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]

內(nèi)置的宏腳本

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 

高級(jí)的宏腳本編寫(xiě)

以上面提到的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>

運(yùn)行自定義lua腳本

這個(gè)跟宏腳本類(lèi)似,只是省去了導(dǎo)入導(dǎo)出操作,直接指定lua腳本來(lái)加載運(yùn)行,這對(duì)于想要快速測(cè)試一些接口模塊,驗(yàn)證自己的某些思路,都是一個(gè)不錯(cuò)的方式。

運(yùn)行指定的腳本文件

我們先寫(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)行內(nèi)置的腳本命令

你可以運(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

運(yùn)行交互命令 (REPL)

有時(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

生成IDE工程文件

簡(jiǎn)介

XMake跟cmake, premake等其他一些構(gòu)建工具的區(qū)別在于:

<p class="warning"> xmake默認(rèn)是直接構(gòu)建運(yùn)行的,生成第三方的IDE的工程文件僅僅作為插件來(lái)提供。 </p>

這樣做的一個(gè)好處是:插件更加容易擴(kuò)展,維護(hù)也更加獨(dú)立和方便。

生成Makefile

$ xmake project -k makefile

生成compiler_commands

導(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

生成VisualStudio工程

$ 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è)文檔。

生成doxygen文檔

請(qǐng)先確保本機(jī)已安裝doxygen工具,然后在工程目錄下運(yùn)行:

$ xmake doxygen

更多插件

請(qǐng)到插件倉(cāng)庫(kù)進(jìn)行下載安裝: xmake-plugins.

從app生成ipa包

這僅僅是一個(gè)小插件,ios開(kāi)發(fā)的同學(xué),可能會(huì)用的到。

$ xmake app2ipa --icon=/xxx.png /xxx/ios.app -o /xxx.ios.ipa
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)