xmake的工程描述文件xmake.lua虽然基于lua语法,可是为了使得更加方便简洁得编写项目构建逻辑,xmake对其进行了一层封装,使得编写xmake.lua不会像些makefile那样繁琐ios
基本上写个简单的工程构建描述,只需三行就能搞定,例如:git
target("test") set_kind("binary") add_files("src/*.c")
而后只须要执行编译而且运行它:github
$ xmake run test
这对于想要临时写些测试代码来说,极大地提高了开发效率。。编程
xmake的描述语法是按做用域划分的,主要分为:api
那哪些属于外部,哪些又属于内部呢,看看下面的注释,就知道个大概了:安全
-- 外部做用域 target("test") -- 外部做用域 set_kind("binary") add_files("src/*.c") on_run(function () -- 内部做用域 end) after_package(function () -- 内部做用域 end) -- 外部做用域 task("hello") -- 外部做用域 on_run(function () -- 内部做用域 end)
简单的说,就是在自定义脚本function () end
以内的都属于内部做用域,也就是脚本做用域,其余地方都是都属于于外部做用域。。bash
对于大部分工程来讲,并不须要很复杂的工程描述,也不须要自定义脚本支持,只须要简单的 set_xxx
或者 add_xxx
就能知足需求了iphone
那么根据二八定律,80%的状况下,咱们只须要这么写:函数
target("test") set_kind("static") add_files("src/test/*.c") target("demo") add_deps("test") set_kind("binary") add_links("test") add_files("src/demo/*.c")
不须要复杂的api调用,也不须要各类繁琐的变量定义,以及 if
判断 和 for
循环,要的就是简洁可读,一眼看过去,就算不懂lua语法也不要紧测试
就当作简单的描述语法,看上去有点像函数调用而已,会点编程的基本一看就知道怎么配置。
为了作到简洁、安全,在这个做用域内,不少lua 内置api是不开放出来的,尤为是跟写文件、修改操做环境相关的,仅仅提供一些基本的只读接口,和逻辑操做
目前外部做用域开放的lua内置api有:
固然虽然内置lua api提供很少,但xmake还提供了不少扩展api,像描述api就很少说,详细可参考:工程描述api文档
还有些辅助api,例如:
还有变量定义、逻辑操做也是可使用的,毕竟是基于lua的,该有的基础语法,仍是要有的,咱们能够经过if来切换编译文件:
target("test") set_kind("static") if is_plat("iphoneos") then add_files("src/test/ios/*.c") else add_files("src/test/*.c") end
咱们也能够启用和禁用某个子工程target:
if is_arch("arm*") then target("test1") set_kind("static") add_files("src/*.c") else target("test2") set_kind("static") add_files("src/*.c") end
须要注意的是,变量定义分全局变量和局部变量,局部变量只对当前xmake.lua有效,不影响子xmake.lua
-- 局部变量,只对当前xmake.lua有效 local var1 = 0 -- 全局变量,影响全部以后 add_subfiles(), add_subdirs() 包含的子 xmake.lua var2 = 1 add_subdirs("src")
也称插件、脚本做用域,提供更加复杂、灵活的脚本支持,通常用于编写一些自定义脚本、插件开发、自定义task任务、自定义模块等等
通常经过 function () end
包含,而且被传入到 on_xxx
, before_xxx
和after_xxx
接口内的,都属于自做用域。
例如:
-- 自定义脚本 target("hello") after_build(function () -- 内部做用域 end) -- 自定义任务、插件 task("hello") on_run(function () -- 内部做用域 end)
在此做用域中,不只可使用大部分lua的api,还可使用不少xmake提供的扩展模块,全部扩展模块,经过import
来导入
具体可参考:插件开发之import类库
这里咱们给个简单的例子,在编译完成后,对ios目标程序进行ldid签名:
target("iosdemo") set_kind("binary") add_files("*.m") after_build( function (target) -- 执行签名,若是失败,自动中断,给出高亮错误信息 os.run("ldid -S$(projectdir)/entitlements.plist %s", target:targetfile()) end)
须要注意的是,在内部做用域中,全部的调用都是启用异常捕获机制的,若是运行出错,会自动中断xmake,并给出错误提示信息
所以,脚本写起来,不须要繁琐的if retval then
判断,脚本逻辑更加一目了然
在外部做用域中的全部描述api设置,自己也是有做用域之分的,在不一样地方调用,影响范围也不相同,例如:
-- 全局根做用域,影响全部target,包括 add_subdirs() 中的子工程target设置 add_defines("DEBUG") -- 定义或者进入demo目标做用域(支持屡次进入来追加设置) target("demo") set_kind("shared") add_files("src/*.c") -- 当前target做用域,仅仅影响当前target add_defines("DEBUG2") -- 选项设置,仅支持局部设置,不受全局api设置所影响 option("test") -- 当前选项的局部做用域 set_default(false) -- 其余target设置,-DDEBUG 也会被设置上 target("demo2") set_kind("binary") add_files("src/*.c") -- 从新进入demo目标做用域 target("demo") -- 追加宏定义,只对当前demo目标有效 add_defines("DEBUG3")
xmake里面还有些全局api,仅提供全局做用域支持,例如:
等等,这些调用不要放置在 target 或者 option 的局部做用域之间,虽然没什么实际区别,可是会影响可读性,容易被误导
使用方式,以下:
target("xxxx") set_kind("binary") add_files("*.c") -- 包含子模块文件 add_subdirs("src")
xmake.lua里面缩进,只是个编写规范,用于更加清楚的区分,当前的设置 是针对 那个做用域的,虽然就算不缩进,也同样ok,可是可读性上 并非很好。。
例如:
target("xxxx") set_kind("binary") add_files("*.c")
和
target("xxxx") set_kind("binary") add_files("*.c")
上述两种方式,效果上都是同样的,可是理解上,第一种更加直观,一看就知道 add_files 仅仅只是针对 target 设置的,并非全局设置
所以,适当的进行缩进,有助于更好的维护xmake.lua
最后附上,tbox的xmake.lua和src/tbox/xmake.lua描述,仅供参考。。