flow(项目构建工具)(outdate)
2015年03月09日 08:12GMT+8
flow 目前作为 luxe 项目的构建, 源码是 nodejs 的。
作为项目构建工具它通过解析当前目录下的 project.flow
做如下事情:
-
icons - 嵌入和转换 icons 为所有目标(target)(除了 linux)
-
package - 快速打包 builds 为 zip 或 tar
-
clean - 删除 build 或项目输出, 或全部
-
upx - 针对桌面平台, 最终二进制文件可以自动压缩
-
files - 灵活的复制和模板系统
-
build - 将 haxe 代码生成部署应用
-
launch - 使用 flow 自带的 web server 加载, 以文件同步的方式(即修改了源码将立即反应)运行 web app,
安装
-
haxelib install flow
即可 -
通过 git 克隆其源码, 然后以
haxelib dev flow DIR
的方式安装
由于 haxelib run flow
这个命令实在有些长, 因此你可能想要一个更短的命令。
对于 window 平台, 将文件保存为 bat,然后存放于 path 目录.
@echo off
haxelib run flow %*
Linux/Mac平台, 复制到文件保存到 /usr/local/bin 或 path 路径.
#!/bin/sh
haxelib run flow "$@"
基础命令
在命令行中输入 flow usage
来获取帮助信息. 可以详细到命令,如: flow usage run
command list :
run, launch, build, compile, hooks, clean, package,
setup, files, icons, config, upx, info, sync, usage
options:
--version : 与 flow version 一样
--log<level> : 默值的 level 值为 2, 如果调试建议改为 3 或 4
--json : 输出 json 值仅用于特别的command及特别的usage选项
关于 usage 的帮助信息也可以查看 src/flow/cmd
目录下相应 .md 文件。
首先简单描术 build 和 compile 的区别:
- compile(编译)指将 haxe 源码转换成目标代码,它对应于 output 目录
- 而 build(构建)指使用各平台工具(例如: msvc)编译目标代码, 它对应于 output.build 目录
注: 一些命令将(command)依赖于 project.flow
配置文件
-
flow build [target] [--debug]
: 编译并且构建, 生成 output 和 output.build- options: 任何 clean, hooks, files 命令的 options 都可用
- –clean 在构建之前先执行 clean 命令
- –output-path
覆盖 project.app.output 所指定的输出目录
-
flow compile [target] --options
: 仅编译, 即仅生成 output- options:
- –clean 在编译之前先执行 clean .
-
flow files [target] --options
: “复制/模板处理”文件到 output 和 output.build,- options:
- –no-build-files 将不会 “复制/模板处理” output.build
- –no-files 将不会 “复制/模板处理” output
- –no-list
- –list-name
- –error-on-missing
-
flow hooks [target] <--options>
: 执行project.flow
文件中project.build.pre
项所定义的 nodejs 脚本// 示例来自: src/flow/cmd/hooks/hooks.js pre : { priority : 1, name : 'ios-project-sync', desc : 'checks the ios project project.app flags are synced up', script : 'pre/pre.js', }
-
flow icons [target] [--options]
: 转换project.app.icon
到 output -
flow info [target] [--options]
:解析config文件并返回指定平台的信息- options: –hxml 仅输出 hxml
-
flow launch [target] [--options]
: 将启动最后成功构建的 app- options: 一些针对平台的特别选项, 自行参考 flow usage launch
- –with-files 当仅更新 assets 和 config 时可以不需要编译,直接执行 launch 加上这个参数即可。
-
flow run [target] [--options]
将依次执行 files, build, launch- options: 所有依次执行命令的 options
-
flow package [target] [--options]
: 打包 output 文件夹为压缩文件,默认为 zip- options:
--archive <tar, zip>
指定压缩格式--archive-name <target/path/packagename>
指定打包后的路径及名称--archive-root <subfolder>
指定压缩包的根目录, 默认情况下 output 下的文件将直接位于(archive)下
-
flow clean [target] --options
: 清除指定目标文件夹,并且不会有任何警告- options:
- –all 清除输出文件夹, 例如: (project)/bin 目录下文件将被完全删除
- –clean-build 清除指定目标的输出文件夹下的 build 目录下所有文件
- –clean-outout 清除指定目标的输出文件夹下所有文件
-
flow sync [target] --options
将执行 files 以及监视文件改变, options 见 files -
flow config [leaf] [value] [--options]
只能设置或获得 config 已经定义了的 leaf,- 当给定 value 时, leaf 的值将被存储到
.flow.config.json
文件中去 - 当没有指定 value 时, 仅输出 leaf 当前的 value,
- options: –list 当 leaf 值为 Object 类型时,打印它的所有值
- 当给定 value 时, leaf 的值将被存储到
target 目前支持如下平台, 如果未指定则使用你的当前系统, 例如在 mac 中执行 flow build 则表现为 flow build mac --arch 64
// src/config.json
target : {
"web" : "js",
"mac" : "cpp",
"windows" : "cpp",
"linux" : "cpp",
"android" : "cpp",
"ios" : "cpp",
"tvos" : "cpp",
"neko" : "neko"
}
flow config
对于 flow 的配置文件, 分别有:
- 原始 位于”flow/src/config.json”, 这个文件可以看下,在致了解下有些什么
- 用户 对于 win7 很可能位于 “C:\Users\USERNAME.flow.config.json”, 如果没有需要自已新建。 比如使用这个文件用来配置 android 的 SDK 路径。
- 项目 当前工作目录下的 “project.flow” 文件
并且这些配置从下往上覆盖, 通常对于一个项目来说 project.flow 是必须的. 一些命令依赖这个文件的配置
文件格式
https://snowkit.github.io/flow/flow.html flow 下使用如下约定:
-
node
指一个对象, 例如:{}
-
list
表示数组, 例:[]
-
key
为一对key/value ,例:name: 'value'
Root nodes
包含 3 个保留 nodes,分别为:
-
flow, 根据需要配置 flow 命令行本身. 配置细节参看
src/flow/config.json
- 例如: 覆盖
build.android.sdk 或 build.android.ant_path
的路径设置
- 例如: 覆盖
-
project, 项目的根节点, flow文件格式主要的部分
-
if, 同 project, 但允许条件检测.
custom root nodes
除了以上3个node, 整个flow文件可随意定制, flow文件处于于项目依赖树中. flow文件将被简单地处理, 并把这些值传递到 hooks,文件模板等等.
Project defines
在 haxe 代码常见的 defines 条件检测:
#if desktop
desktop_code();
#else
other_code();
#end
在flow文件中同样可以使用 defines 条件检测:
if:{
desktop: {
files: { desktop_config:'config/desktop.json => config.json' }
}
}
Build in defines
内建的defines
-
dependency
依赖, 任何依赖将会成为 define,- 参考 haxelib,只是引用define时,使用下滑线”_“代替减号”-“
-
desktop
当编译为 mac,windows,或linux时 -
mobile
: 当编译为 andoird或ios -
target
: 当前目标(target)将自动为 define- web,android,ios,mac,linux,windows….
-
arch-
arch-
on web, 将使用
arch-web
-
如果 64位系统,则为
arch-64
, 32位为arch-32
-
arch-armv7
,arch-i386
等等
-
-
ios-sim
当构建时指定了--sim
-
debug
: 当开启--debug
时. -
通过 project.flow 文件定义的
Conditional project nodes
在根节点 if 中, 目前可以使用下边节点:
-
files
-
build.fiels
-
build.defines
-
build.flags
条件节点依赖于各种 defines
condition resolution
从 defines 中生成新的 define, 这样不必每次使用过长的条件表达式.
if : {
"mac || windows || linux || android || ios" : {
build: {
defines : ['is_native']
}
},
"is_native && arch-32" : {
...
}
}
conditional statements
条件节点支持如下操作符:
-
!
not -
||
or -
&&
and
但是注意: 使用条件操作符的表达式需要包括在引号内部(单或双引号)
A flow file
下边很多选项不是必须的使用默认值即可
{
project : {
/**
项目的显示名称, 对于 mobile 目标,将显示为菜单标题
@type String
@required 表示为必须提供这个参数
*/
name : 'empty',
/**
版本号, 和 haxelib 版本无关.使用 "major.minor.patch"
@type String
@required
*/
version : '1.0.0',
/**
项目的作者/所属人/管理者, 可以为任意字母和数字的字符串
@type String
*/
author : 'luxeengine',
// {}
app : {
/**
应用的二进制文件名称,不能包括特殊字符(需要符合系统文件名称规范)
@type String
@default "flow_app"
*/
name : 'flow_app',
/**
bundle/package/app的标识符, 不能包括特殊字符和空格. 你应该更改这个属性
@type String
@default "org.snowkit.flow_app"
*/
package : 'org.snowkit.flow_app'
/**
指定输出文件夹名称
@type String
@default "bin"
*/
output : 'bin/'
/**
指定haxe的主类,不需要写 ".hx" 扩展名
@type String
@default "Main"
*/
main : 'Main',
/**
指定源码所在目录, 等同于 haxe 的 `-cp` 参数所指定的目录
@type Array<String>
@default "src"
*/
codepaths: ['src'],
/**
指定 icons 的文件位置. (TODO:文档描述的不明确,只参看了 luxe项目的 luxe.flow 文件)
当值仅为 path 时, 这时假定图标的名称为 "icon" , 相当于 path => icon
当值为 path => name时, 将使用指定的 name 作为图标名称,
path 将相对于 project.flow 的文件所在位置
文件目录示例参考: `flow/src/flow/cmd/icons/default`
@type String
@default 将使用flow内部的图标集,即上边示例
*/
icon: 'path/to/ => icon',
// node, 很明显这个节点用于 html5形式的 app.
web : {
/**
这些名称将传递到模板中去.
libname: 给定库名称
path: 相对于 output 指定的目录, 可以为绝对路径如 http://
@type node of keys {libname: 'path'}
*/
libs : {
jquery: "js/jquery.js",
index: "index.js"
}
},
// node, 用于 mobile 目标
mobile : {
/**
if device fullscreen is used.
@type Bool
@default true
*/
fullsceen: true,
/**
横屏(landscape)竖屏(portrait)
可用值为: "landscape","landscape left","landscape both","portrait","portrait upside down","portrait both"
@type String
@default "landscape"
*/
orientation: "landscape",
//node
ios : {
/**
在 xcode 中指定设备类型
有效值为: "Universal","iPhone","iPad"
@type String
@default "Universal"
*/
devices: "Universal",
/**
指定 ios 的最低版本
@type String
@default "6.0"
*/
deployment_target: "6.0",
/**
xcode 工具包名用于cpp, 不需要更改,除非框架需求, 允许框架开发者定制 cpp 库,
@type String
default "libc++"
*/
cpp: "libc++"
},
//node
android : {
/**
debug/store 编译标记,可用值为: "store","debug"
@type String
@default "debug"
*/
build_type: "debug",
/**
installLocation in android manifest:
http://developer.android.com/guide/topics/manifest/manifest-element.html#install
@type String
@default "preferExternal"
*/
install_location: "preferExternal",
/**
sdk min in android manifest:
http://developer.android.com/guide/topics/manifest/uses-sdk-element.html
@type String
@default "10"
*/
sdk_min: "10",
/**
sdk target in android manifest:
http://developer.android.com/guide/topics/manifest/uses-sdk-element.html
通常设置为可用的最高.
@type String
@default "19"
*/
sdk_target: "19",
/**
android manifest permissions:
http://developer.android.com/reference/android/Manifest.permission.html
@type Array<String>
@default []
*/
permissions: [
'android.permission.READ_EXTERNAL_STORAGE',
'android.permission.INTERNET'
]
}
}
},
build : {
/**
haxe 编译标记, 将直接传递给 haxe.exe
@type Array<String>
@default []
*/
flags : ['-v', '--macro keep(example)'],
/**
自定义 haxe defines, 通过`-D define` 形式传递给 haxe.exe
@type Array<String>
@default []
*/
defines : ['no_sfx', 'no_music'],
/**
key/value 形式的hash列表. 指定 haxelib
key 应该为 haxelib list 中列出的库, version 为 "*" 时表示为当前版本, 或者指定成 "1.0.0" 的形式.
被依赖的库将会优先读取 .flow 文件, 如果不存在则读取 haxelib.json 文件分析内部的依赖
@type {}, i.e. {depend: "version"}
@default {}
*/
dependencies : {
hxnodejs : '*'
},
/**
位于 project/build下的files,将复制文件到 output/target.build/ 下, 其它参考 project/files 的说明
i.e bin/web.build/
web.build目录和web目录的区别是: web.build 是存放haxe源码的,而web目录则为最终生成结果的目录
*/
files:{
}
},
/**
位于 project 下的 files,将复制文件到 output/target/ 例: bin/web/
位于 project/build/下的files 则复制文件到 output/target.build/ 例: bin/web.build/
基本格式为: {filereference: "path/source.ext => dest/path/dest.ext"}, 注意 "=>" 符号
source: 源文件位置, 相对于 project.flow 文件
dest: 目标位置, 相对于目标文件夹
- 将被创建, 包括目录, 可以被覆盖重写(后边描述如何禁止覆盖)
- 部分为可选, 这时将表现为 `name: "source => source"`
@type {}
@default {}
*/
files : {
data : 'data/ => assets/',
// 带有 not_listed 参数
howlerjs : { path:'flow/web/lib/howler.min.js => lib/howler.js', not_listed:true }
/**
如需通过模板生成, 则写成这种形式, 模板使用 [handlebars](http://handlebarsjs.com/)
*/
config : {
/**
@type String
*/
path: 'config.template.json => config.json',
/**
指定的值为 flow文件的根节点(除了if节点),这些节点和自定义节点可以作为模板参数传递
@type Array<String>|String
*/
template:['project']
},
// example
boot : { path:'flow/boot/SnowApp.hx => haxe/SnowApp.hx', template:['project', 'snow'] }
}
},
if : {
...
}
}
misc
flow源码结构
bin/ # 包括各平台的 node.exe
setup/ # haxelib run flow 的快捷方式,
/Flow.hx # run.n 的源码, 获得 args 参数然后传递调用 node flow.js
/flow/ # 目录下所有代码基于 nodejs
/cmd/ # flow <command>,各命令, 这种方式真是简洁
/node_modules/
/project/ # flow.js 加载 project.js 由 project.js 加载这个目录下所有脚本
/dependencies/
/hxcpp.flow # ?主要是移动hxcpp编译之后的库文件到 .build下
/prepare/ #
/conditions.js #
/defines.js #
/depends.js #
/files.js #
/flags.js #
/bake.js #
/prepare.js #
/project.js # 将被初使化加载到 flow.project 属性下
/tools/ # http 服务器用于 web 调试
/utils/
/er.js # 打印一朵字符串拼凑的花,
/flagger.js # 解析命令行参数到
/haxelib.js # 方便从 haxelib 获取一些信息
/process.js # 使用 child_process 运行 cmd,并从 stdout 获得结果
/util.js # 一些 Array,Object 方法
flow.js # 入口文件
config.json # 用于配置flow,可在个人项目中如 project.flow 的 flow 节点中覆盖这个文件的设置
# 例如覆盖 android sdk 的正确路径
project.defaults.json # project.flow 项目的默认配置, 被加载到 flow.project.default
src/
tests/ # 包含一个 flow.json 的配置样例