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 的配置样例