aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <waruqi@gmail.com>2017-08-31 09:08:38 +0800
committerruki <waruqi@gmail.com>2017-08-31 09:08:38 +0800
commit9078c01303c065fbf6e6cefbddcb462adede7bfb (patch)
treec33052b914aeaca00186e6cc83df6f88f4e1c1b4
downloadxmake-docs-9078c01303c065fbf6e6cefbddcb462adede7bfb.tar.gz
xmake-docs-9078c01303c065fbf6e6cefbddcb462adede7bfb.zip
first commit
-rw-r--r--.gitignore35
-rw-r--r--.nojekyll0
-rw-r--r--CNAME1
-rw-r--r--LICENSE.md238
-rw-r--r--README.md602
-rw-r--r--assets/css/cayman.css320
-rw-r--r--assets/css/docute.css4
-rw-r--r--assets/css/normalize.css424
-rw-r--r--assets/css/opensans.css112
-rw-r--r--assets/img/alipay.pngbin0 -> 97219 bytes
-rw-r--r--assets/img/donate.gifbin0 -> 1491 bytes
-rw-r--r--assets/img/patreon.pngbin0 -> 5626 bytes
-rw-r--r--assets/img/paypal.pngbin0 -> 6454 bytes
-rw-r--r--assets/img/weixin.pngbin0 -> 109611 bytes
-rw-r--r--assets/js/docsearch.js2
-rw-r--r--assets/js/docute.js2
-rw-r--r--assets/js/prism-bash.min.js1
-rw-r--r--assets/js/prism-c.min.js1
-rw-r--r--assets/js/prism-lua.min.js1
-rw-r--r--baidu_verify_cuJ4VNoBuE.html1
-rw-r--r--cn/index.html237
-rw-r--r--cn/pages/donation.html119
-rw-r--r--config.js76
-rw-r--r--favicon.icobin0 -> 119943 bytes
-rw-r--r--index.html31
-rw-r--r--landing.html234
-rw-r--r--landing/README.md21
-rw-r--r--landing/_config.yml21
-rw-r--r--landing/_includes/head.cn.html23
-rw-r--r--landing/_includes/head.html23
-rw-r--r--landing/_includes/page-footer.html12
-rw-r--r--landing/_includes/page-header.cn.html18
-rw-r--r--landing/_includes/page-header.html18
-rw-r--r--landing/_layouts/default.cn.html18
-rw-r--r--landing/_layouts/default.html18
-rw-r--r--landing/_layouts/post.html7
-rw-r--r--landing/_posts/donation.md6
-rw-r--r--landing/assets/css/cayman.css320
-rw-r--r--landing/assets/css/normalize.css424
-rw-r--r--landing/assets/css/opensans.css112
-rw-r--r--landing/assets/img/alipay.pngbin0 -> 97219 bytes
-rw-r--r--landing/assets/img/donate.gifbin0 -> 1491 bytes
-rw-r--r--landing/assets/img/patreon.pngbin0 -> 5626 bytes
-rw-r--r--landing/assets/img/paypal.pngbin0 -> 6454 bytes
-rw-r--r--landing/assets/img/weixin.pngbin0 -> 109611 bytes
-rw-r--r--landing/favicon.icobin0 -> 9375 bytes
-rw-r--r--landing/index.cn.md159
-rw-r--r--landing/index.md156
-rw-r--r--landing/pages/donation.cn.md46
-rw-r--r--landing/pages/donation.md48
-rw-r--r--manual.md6818
-rw-r--r--pages/donation.html119
-rw-r--r--plugins.md499
-rw-r--r--zh/README.md645
-rw-r--r--zh/manual.md6835
-rw-r--r--zh/plugins.md525
56 files changed, 19332 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..503e79d4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,35 @@
+*.a
+*.b
+*.o
+*.exe
+*.obj
+*.dll
+*.lib
+*.out
+*.suo
+*~
+*.swp
+*.swo
+*.bak
+*.orig
+*.pdb
+*.idb
+*.ilk
+*.stackdump
+*.manifest
+.ccache
+.demo
+.svn
+.DS_Store
+.xmake
+*.deb
+*.zip
+*.gch
+*.gch.d
+cscope.*
+gmon.out
+other
+tags
+doc
+install.log
+build
diff --git a/.nojekyll b/.nojekyll
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/.nojekyll
diff --git a/CNAME b/CNAME
new file mode 100644
index 00000000..be3e721e
--- /dev/null
+++ b/CNAME
@@ -0,0 +1 @@
+xmake.io
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 00000000..c23b324d
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,238 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2016-2017 TBOOX Open Source Group
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-------------------------------------------------------------------------------
+## SUBCOMPONENTS
+
+The XMake project contains subcomponents with separate copyright
+notices and license terms. Your use of the source code for the these
+subcomponents is subject to the terms and conditions of the following
+licenses.
+
+#### LuaJIT license
+
+===============================================================================
+LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/
+
+Copyright (C) 2005-2014 Mike Pall. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+[ MIT license: http://www.opensource.org/licenses/mit-license.php ]
+
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..eb729ca2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,602 @@
+---
+search: en
+---
+
+<p>
+<div align="center">
+ <a href="http://xmake.io">
+ <img width="200" heigth="200" src="http://tboox.org/static/img/xmake/logo256c.png">
+ </a>
+
+ <h1>xmake</h1>
+
+ <div>
+ <a href="https://travis-ci.org/tboox/xmake">
+ <img src="https://img.shields.io/travis/tboox/xmake/master.svg?style=flat-square" alt="travis-ci" />
+ </a>
+ <a href="https://ci.appveyor.com/project/waruqi/xmake/branch/master">
+ <img src="https://img.shields.io/appveyor/ci/waruqi/xmake/master.svg?style=flat-square" alt="appveyor-ci" />
+ </a>
+ <a href="https://codecov.io/gh/tboox/xmake">
+ <img src="https://img.shields.io/codecov/c/github/tboox/xmake/master.svg?style=flat-square" alt="Coverage" />
+ </a>
+ <a href="https://github.com/tboox/xmake/releases">
+ <img src="https://img.shields.io/github/release/tboox/xmake.svg?style=flat-square" alt="Github All Releases" />
+ </a>
+ <a href="https://aur.archlinux.org/packages/xmake">
+ <img src="https://img.shields.io/aur/votes/xmake.svg?style=flat-square" alt="AUR votes" />
+ </a>
+ </div>
+ <div>
+ <a href="https://github.com/tboox/xmake/blob/master/LICENSE.md">
+ <img src="https://img.shields.io/github/license/tboox/xmake.svg?colorB=f48041&style=flat-square" alt="license" />
+ </a>
+ <a href="https://gitter.im/tboox/tboox?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge">
+ <img src="https://img.shields.io/gitter/room/tboox/tboox.svg?style=flat-square&colorB=96c312" alt="Gitter" />
+ </a>
+ <a href="http://xmake.io/pages/donation.html#donate">
+ <img src="https://img.shields.io/badge/donate-us-orange.svg?style=flat-square" alt="Donate" />
+ </a>
+ </div>
+
+ <p>A cross-platform build utility based on Lua</p>
+</div>
+</p>
+
+## Introduction
+
+xmake is a cross-platform build utility based on lua.
+
+The project focuses on making development and building easier and provides many features (.e.g package, install, plugin, macro, action, option, task ...),
+so that any developer can quickly pick it up and enjoy the productivity boost when developing and building project.
+
+## Installation
+
+#### Master
+
+##### via curl
+
+```bash
+bash <(curl -fsSL https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh)
+```
+
+##### via wget
+
+```bash
+bash <(wget https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh -O -)
+```
+
+##### via powershell
+
+```bash
+Invoke-Expression (Invoke-Webrequest 'https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.ps1' -UseBasicParsing).Content
+```
+
+#### Windows
+
+1. Download xmake windows installer from [Releases](https://github.com/tboox/xmake/releases)
+2. Run xmake-[version].exe
+
+#### MacOS
+
+```bash
+$ brew install xmake
+```
+
+#### Linux
+
+On Archlinux:
+
+```bash
+$ yaourt xmake
+```
+
+On Ubuntu:
+
+```bash
+$ sudo add-apt-repository ppa:tboox/xmake
+$ sudo apt update
+$ sudo apt install xmake
+```
+
+Or add xmake package source manually:
+
+```
+deb http://ppa.launchpad.net/tboox/xmake/ubuntu yakkety main
+deb-src http://ppa.launchpad.net/tboox/xmake/ubuntu yakkety main
+```
+
+Then we run:
+
+```bash
+$ sudo apt update
+$ sudo apt install xmake
+```
+
+Or download deb package to install it:
+
+1. Download xmake `.deb` install package from [Releases](https://github.com/tboox/xmake/releases)
+2. Run `dpkg -i xmake-xxxx.deb`
+
+#### Compilation
+
+```bash
+$ git clone git@github.com:waruqi/xmake.git
+$ cd ./xmake
+$ ./scripts/get.sh __local__
+```
+
+## Quick Start
+
+[![asciicast](https://asciinema.org/a/133693.png)](https://asciinema.org/a/133693)
+
+#### Create Project
+
+```bash
+$ xmake create -l c -P ./hello
+```
+
+And xmake will generate some files for c language project:
+
+```
+hello
+├── src
+│   └── main.c
+└── xmake.lua
+```
+
+It is a simple console program only for printing `hello xmake!`
+
+The content of `xmake.lua` is very simple:
+
+```lua
+target("hello")
+ set_kind("binary")
+ add_files("src/*.c")
+```
+
+Support languages:
+
+* c/c++
+* objc/c++
+* asm
+* swift
+* dlang
+* golang
+* rust
+
+<p class="tip">
+ If you want to known more options, please run: `xmake create --help`
+</p>
+
+#### Build Project
+
+```bash
+$ xmake
+```
+
+#### Run Program
+
+```bash
+$ xmake run hello
+```
+
+#### Debug Program
+
+```bash
+$ xmake run -d hello
+```
+
+It will start the debugger (.e.g lldb, gdb, windbg, vsjitdebugger, ollydbg ..) to load our program.
+
+```bash
+[lldb]$target create "build/hello"
+Current executable set to 'build/hello' (x86_64).
+[lldb]$b main
+Breakpoint 1: where = hello`main, address = 0x0000000100000f50
+[lldb]$r
+Process 7509 launched: '/private/tmp/hello/build/hello' (x86_64)
+Process 7509 stopped
+* thread #1: tid = 0x435a2, 0x0000000100000f50 hello`main, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
+ frame #0: 0x0000000100000f50 hello`main
+hello`main:
+-> 0x100000f50 <+0>: pushq %rbp
+ 0x100000f51 <+1>: movq %rsp, %rbp
+ 0x100000f54 <+4>: leaq 0x2b(%rip), %rdi ; "hello world!"
+ 0x100000f5b <+11>: callq 0x100000f64 ; symbol stub for: puts
+[lldb]$
+```
+
+<p class="tip">
+ You can also use short command option, for exmaple: `xmake r` or `xmake run`
+</p>
+
+## Configuration
+
+Set compilation configuration before building project with command `xmake f|config`.
+
+And if you want to known more options, please run: `xmake f --help`。
+
+<p class="tip">
+ You can use short or long command option, for exmaple: <br>
+ `xmake f` or `xmake config`.<br>
+ `xmake f -p linux` or `xmake config --plat=linux`.
+</p>
+
+#### Target Platforms
+
+##### Current Host
+
+```bash
+$ xmake
+```
+
+<p class="tip">
+ XMake will detect the current host platform automatically and build project.
+</p>
+
+##### Linux
+
+```bash
+$ xmake f -p linux [-a i386|x86_64]
+$ xmake
+```
+
+##### Android
+
+```bash
+$ xmake f -p android --ndk=~/files/android-ndk-r10e/ [-a armv5te|armv6|armv7-a|armv8-a|arm64-v8a]
+$ xmake
+```
+
+If you want to set the other android toolchains, you can use [--toolchains](#-toolchains) option.
+
+For example:
+
+```bash
+$ xmake f -p android --ndk=~/files/android-ndk-r10e/ -a arm64-v8a --toolchains=~/files/android-ndk-r10e/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin
+```
+
+The [--toolchains](#-toolchains) option is used to set `bin` directory of toolchains.
+
+<p class="tip">
+Please attempt to set `--arch=` option if it had failed to check compiler.
+</p>
+
+##### iPhoneOS
+
+```bash
+$ xmake f -p iphoneos [-a armv7|armv7s|arm64|i386|x86_64]
+$ xmake
+```
+
+##### Windows
+
+```bash
+$ xmake f -p windows [-a x86|x64]
+$ xmake
+```
+
+##### Mingw
+
+```bash
+$ xmake f -p mingw --sdk=/usr/local/i386-mingw32-4.3.0/ [-a i386|x86_64]
+$ xmake
+```
+
+##### Apple WatchOS
+
+```bash
+$ xmake f -p watchos [-a i386|armv7k]
+$ xmake
+```
+
+##### Cross Compilation
+
+For linux platform:
+
+```bash
+$ xmake f -p linux --sdk=/usr/local/arm-linux-gcc/ [--toolchains=/sdk/bin] [--cross=arm-linux-]
+$ xmake
+```
+
+Fro other cross platform:
+
+```bash
+$ xmake f -p cross --sdk=/usr/local/arm-xxx-gcc/ [--toolchains=/sdk/bin] [--cross=arm-linux-]
+$ xmake
+```
+
+For custem cross platform (`is_plat("myplat")`):
+
+```bash
+$ xmake f -p myplat --sdk=/usr/local/arm-xxx-gcc/ [--toolchains=/sdk/bin] [--cross=arm-linux-]
+$ xmake
+```
+
+| Configuration Option | Description |
+| ---------------------------- | -------------------------------------------- |
+| [--sdk](#-sdk) | Set the sdk root directory of toolchains |
+| [--toolchains](#-toolchains) | Set the `bin` directory of toolchains |
+| [--cross](#-cross) | Set the prefix of compilation tools |
+| [--as](#-as) | Set `asm` assembler |
+| [--cc](#-cc) | Set `c` compiler |
+| [--cxx](#-cxx) | Set `c++` compiler |
+| [--mm](#-mm) | Set `objc` compiler |
+| [--mxx](#-mxx) | Set `objc++` compiler |
+| [--sc](#-sc) | Set `swift` compiler |
+| [--gc](#-gc) | Set `golang` compiler |
+| [--dc](#-dc) | Set `dlang` compiler |
+| [--rc](#-rc) | Set `rust` compiler |
+| [--ld](#-ld) | Set `c/c++/objc/asm` linker |
+| [--sh](#-sh) | Set `c/c++/objc/asm` shared library linker |
+| [--ar](#-ar) | Set `c/c++/objc/asm` static library archiver |
+| [--sc-ld](#-sc-ld) | Set `swift` linker |
+| [--sc-sh](#-sc-sh) | Set `swift` shared library linker |
+| [--gc-ld](#-gc-ld) | Set `golang` linker |
+| [--gc-ar](#-gc-ar) | Set `golang` static library archiver |
+| [--dc-ld](#-dc-ld) | Set `dlang` linker |
+| [--dc-sh](#-dc-sh) | Set `dlang` shared library linker |
+| [--dc-ar](#-dc-ar) | Set `dlang` static library archiver |
+| [--rc-ld](#-rc-ld) | Set `rust` linker |
+| [--rc-sh](#-rc-sh) | Set `rust` shared library linker |
+| [--rc-ar](#-rc-ar) | Set `rust` static library archiver |
+| [--asflags](#-asflags) | Set `asm` assembler option |
+| [--cflags](#-cflags) | Set `c` compiler option |
+| [--cxflags](#-cxflags) | Set `c/c++` compiler option |
+| [--cxxflags](#-cxxflags) | Set `c++` compiler option |
+| [--mflags](#-mflags) | Set `objc` compiler option |
+| [--mxflags](#-mxflags) | Set `objc/c++` compiler option |
+| [--mxxflags](#-mxxflags) | Set `objc++` compiler option |
+| [--scflags](#-scflags) | Set `swift` compiler option |
+| [--gcflags](#-gcflags) | Set `golang` compiler option |
+| [--dcflags](#-dcflags) | Set `dlang` compiler option |
+| [--rcflags](#-rcflags) | Set `rust` compiler option |
+| [--ldflags](#-ldflags) | Set linker option |
+| [--shflags](#-shflags) | Set shared library linker option |
+| [--arflags](#-arflags) | Set static library archiver option |
+
+<p class="tip">
+if you want to known more options, please run: `xmake f --help`。
+</p>
+
+###### --sdk
+
+- Set the sdk root directory of toolchains
+
+xmake provides a convenient and flexible cross-compiling support.
+In most cases, we need not to configure complex toolchains prefix, for example: `arm-linux-`
+
+As long as this toolchains meet the following directory structure:
+
+```
+/home/toolchains_sdkdir
+ - bin
+ - arm-linux-gcc
+ - arm-linux-ld
+ - ...
+ - lib
+ - libxxx.a
+ - include
+ - xxx.h
+```
+
+Then,we can only configure the sdk directory and build it.
+
+```bash
+$ xmake f -p linux --sdk=/home/toolchains_sdkdir
+$ xmake
+```
+
+xmake will detect the prefix: arm-linux- and add the include and library search directory automatically.
+
+```
+-I/home/toolchains_sdkdir/include -L/home/toolchains_sdkdir/lib
+```
+
+###### --toolchains
+
+- Set the `bin` directory of toolchains
+
+We need set it manually if the toolchains /bin directory is in other places, for example:
+
+```bash
+$ xmake f -p linux --sdk=/home/toolchains_sdkdir --toolchains=/usr/opt/bin
+$ xmake
+```
+
+###### --cross
+
+- Set the prefix of compilation tools
+
+For example, under the same toolchains directory at the same time, there are two different compilers:
+
+```
+/opt/bin
+ - armv7-linux-gcc
+ - aarch64-linux-gcc
+```
+
+If we want to use the `armv7-linux-gcc` compiler, we can run the following command:
+
+```bash
+$ xmake f -p linux --sdk=/usr/toolsdk --toolchains=/opt/bin --cross=armv7-linux-
+```
+
+###### --as
+
+- Set `asm` assembler
+
+```bash
+$ xmake f -p linux --sdk=/user/toolsdk --as=armv7-linux-as
+```
+
+If the 'AS' environment variable exists, it will use the values specified in the current environment variables.
+
+###### --cc
+
+- Set c compiler
+
+```bash
+$ xmake f -p linux --sdk=/user/toolsdk --cc=armv7-linux-clang
+```
+
+If the 'CC' environment variable exists, it will use the values specified in the current environment variables.
+
+###### --cxx
+
+- Set `c++` compiler
+
+```bash
+$ xmake f -p linux --sdk=/user/toolsdk --cxx=armv7-linux-clang++
+```
+
+If the 'CXX' environment variable exists, it will use the values specified in the current environment variables.
+
+###### --ld
+
+- Set `c/c++/objc/asm` linker
+
+```bash
+$ xmake f -p linux --sdk=/user/toolsdk --ld=armv7-linux-clang++
+```
+
+If the 'LD' environment variable exists, it will use the values specified in the current environment variables.
+
+###### --sh
+
+- Set `c/c++/objc/asm` shared library linker
+
+```bash
+$ xmake f -p linux --sdk=/user/toolsdk --sh=armv7-linux-clang++
+```
+
+If the 'SH' environment variable exists, it will use the values specified in the current environment variables.
+
+###### --ar
+
+- Set `c/c++/objc/asm` static library archiver
+
+```bash
+$ xmake f -p linux --sdk=/user/toolsdk --ar=armv7-linux-ar
+```
+
+If the 'AR' environment variable exists, it will use the values specified in the current environment variables.
+
+#### Global Configuration
+
+You can save to the global configuration for simplfying operation.
+
+For example:
+
+```bash
+$ xmake g --ndk=~/files/android-ndk-r10e/
+```
+
+Now, we config and build project for android again.
+
+```bash
+$ xmake f -p android
+$ xmake
+```
+
+<p class="tip">
+ You can use short or long command option, for exmaple: `xmake g` or `xmake global`.<br>
+</p>
+
+#### Clean Configuration
+
+We can clean all cached configuration and re-configure projecct.
+
+```bash
+$ xmake f -c
+$ xmake
+```
+
+or
+
+```bash
+$ xmake f -p iphoneos -c
+$ xmake
+```
+
+## FAQ
+
+#### How to get verbose command-line arguments info?
+
+Get the help info of the main command.
+
+```bash
+$ xmake [-h|--help]
+```
+
+Get the help info of the configuration command.
+
+```bash
+$ xmake f [-h|--help]
+```
+
+Get the help info of the givent action or plugin command.
+
+```bash
+$ xmake [action|plugin] [-h|--help]
+```
+
+For example:
+
+```bash
+$ xmake run --help
+```
+
+#### How to suppress all output info?
+
+```bash
+$ xmake [-q|--quiet]
+```
+
+#### How to do if xmake fails?
+
+Please attempt to clean configuration and rebuild it first.
+
+```bash
+$ xmake f -c
+$ xmake
+```
+
+If it fails again, please add `-v` or `--verbose` options to get more verbose info.
+
+For exmaple:
+
+```hash
+$ xmake -v
+$ xmake --verbose
+```
+
+And add `--backtrace` to get the verbose backtrace info, then you can submit these infos to [issues](https://github.com/tboox/xmake/issues).
+
+```bash
+$ xmake -v --backtrace
+```
+
+## Backers
+
+Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/xmake#backer)]
+
+<a href="https://opencollective.com/xmake#backers" target="_blank"><img src="https://opencollective.com/xmake/backers.svg?width=890"></a>
+
+## Sponsors
+
+Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/xmake#sponsor)]
+
+<a href="https://opencollective.com/xmake/sponsor/0/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/0/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/1/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/1/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/2/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/2/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/3/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/3/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/4/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/4/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/5/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/5/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/6/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/6/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/7/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/7/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/8/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/8/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/9/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/9/avatar.svg"></a>
+
+
diff --git a/assets/css/cayman.css b/assets/css/cayman.css
new file mode 100644
index 00000000..b67d1e8f
--- /dev/null
+++ b/assets/css/cayman.css
@@ -0,0 +1,320 @@
+* {
+ box-sizing: border-box; }
+
+body {
+ padding: 0;
+ margin: 0;
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 16px;
+ line-height: 1.5;
+ color: #606c71; }
+
+a {
+ color: #1e6bb8;
+ text-decoration: none; }
+ a:hover {
+ text-decoration: underline; }
+
+.btn {
+ display: inline-block;
+ margin-bottom: 1rem;
+ color: rgba(255, 255, 255, 0.7);
+ background-color: rgba(255, 255, 255, 0.08);
+ border-color: rgba(255, 255, 255, 0.2);
+ border-style: solid;
+ border-width: 1px;
+ border-radius: 0.3rem;
+ transition: color 0.2s, background-color 0.2s, border-color 0.2s; }
+ .btn:hover {
+ color: rgba(255, 255, 255, 0.8);
+ text-decoration: none;
+ background-color: rgba(255, 255, 255, 0.2);
+ border-color: rgba(255, 255, 255, 0.3); }
+ .btn + .btn {
+ margin-left: 1rem; }
+ @media screen and (min-width: 64em) {
+ .btn {
+ padding: 0.75rem 1rem; } }
+ @media screen and (min-width: 42em) and (max-width: 64em) {
+ .btn {
+ padding: 0.6rem 0.9rem;
+ font-size: 0.9rem; } }
+ @media screen and (max-width: 42em) {
+ .btn {
+ display: block;
+ width: 100%;
+ padding: 0.75rem;
+ font-size: 0.9rem; }
+ .btn + .btn {
+ margin-top: 1rem;
+ margin-left: 0; } }
+
+.page-header {
+ color: #fff;
+ text-align: center;
+ background-color: #159957;
+ background-image: linear-gradient(120deg, #155799, #159957); }
+ @media screen and (min-width: 64em) {
+ .page-header {
+ padding: 5rem 6rem; } }
+ @media screen and (min-width: 42em) and (max-width: 64em) {
+ .page-header {
+ padding: 3rem 4rem; } }
+ @media screen and (max-width: 42em) {
+ .page-header {
+ padding: 2rem 1rem; } }
+
+.project-name {
+ margin-top: 0;
+ margin-bottom: 0.1rem; }
+ @media screen and (min-width: 64em) {
+ .project-name {
+ font-size: 3.25rem; } }
+ @media screen and (min-width: 42em) and (max-width: 64em) {
+ .project-name {
+ font-size: 2.25rem; } }
+ @media screen and (max-width: 42em) {
+ .project-name {
+ font-size: 1.75rem; } }
+
+.project-tagline {
+ margin-bottom: 2rem;
+ font-weight: normal;
+ opacity: 0.7; }
+ @media screen and (min-width: 64em) {
+ .project-tagline {
+ font-size: 1.25rem; } }
+ @media screen and (min-width: 42em) and (max-width: 64em) {
+ .project-tagline {
+ font-size: 1.15rem; } }
+ @media screen and (max-width: 42em) {
+ .project-tagline {
+ font-size: 1rem; } }
+
+.main-content {
+ word-wrap: break-word; }
+ .main-content :first-child {
+ margin-top: 0; }
+ @media screen and (min-width: 64em) {
+ .main-content {
+ max-width: 64rem;
+ padding: 2rem 6rem;
+ margin: 0 auto;
+ font-size: 1.1rem; } }
+ @media screen and (min-width: 42em) and (max-width: 64em) {
+ .main-content {
+ padding: 2rem 4rem;
+ font-size: 1.1rem; } }
+ @media screen and (max-width: 42em) {
+ .main-content {
+ padding: 2rem 1rem;
+ font-size: 1rem; } }
+ .main-content img {
+ max-width: 100%; }
+ .main-content h1,
+ .main-content h2,
+ .main-content h3,
+ .main-content h4,
+ .main-content h5,
+ .main-content h6 {
+ margin-top: 2rem;
+ margin-bottom: 1rem;
+ font-weight: normal;
+ color: #159957; }
+ .main-content p {
+ margin-bottom: 1em; }
+ .main-content code {
+ padding: 2px 4px;
+ font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
+ font-size: 0.9rem;
+ color: #567482;
+ background-color: #f3f6fa;
+ border-radius: 0.3rem; }
+ .main-content pre {
+ padding: 0.8rem;
+ margin-top: 0;
+ margin-bottom: 1rem;
+ font: 1rem Consolas, "Liberation Mono", Menlo, Courier, monospace;
+ color: #567482;
+ word-wrap: normal;
+ background-color: #f3f6fa;
+ border: solid 1px #dce6f0;
+ border-radius: 0.3rem; }
+ .main-content pre > code {
+ padding: 0;
+ margin: 0;
+ font-size: 0.9rem;
+ color: #567482;
+ word-break: normal;
+ white-space: pre;
+ background: transparent;
+ border: 0; }
+ .main-content .highlight {
+ margin-bottom: 1rem; }
+ .main-content .highlight pre {
+ margin-bottom: 0;
+ word-break: normal; }
+ .main-content .highlight pre,
+ .main-content pre {
+ padding: 0.8rem;
+ overflow: auto;
+ font-size: 0.9rem;
+ line-height: 1.45;
+ border-radius: 0.3rem;
+ -webkit-overflow-scrolling: touch; }
+ .main-content pre code,
+ .main-content pre tt {
+ display: inline;
+ max-width: initial;
+ padding: 0;
+ margin: 0;
+ overflow: initial;
+ line-height: inherit;
+ word-wrap: normal;
+ background-color: transparent;
+ border: 0; }
+ .main-content pre code:before, .main-content pre code:after,
+ .main-content pre tt:before,
+ .main-content pre tt:after {
+ content: normal; }
+ .main-content ul,
+ .main-content ol {
+ margin-top: 0; }
+ .main-content blockquote {
+ padding: 0 1rem;
+ margin-left: 0;
+ color: #819198;
+ border-left: 0.3rem solid #dce6f0; }
+ .main-content blockquote > :first-child {
+ margin-top: 0; }
+ .main-content blockquote > :last-child {
+ margin-bottom: 0; }
+ .main-content table {
+ display: block;
+ width: 100%;
+ overflow: auto;
+ word-break: normal;
+ word-break: keep-all;
+ -webkit-overflow-scrolling: touch; }
+ .main-content table th {
+ font-weight: bold; }
+ .main-content table th,
+ .main-content table td {
+ padding: 0.5rem 1rem;
+ border: 1px solid #e9ebec; }
+ .main-content dl {
+ padding: 0; }
+ .main-content dl dt {
+ padding: 0;
+ margin-top: 1rem;
+ font-size: 1rem;
+ font-weight: bold; }
+ .main-content dl dd {
+ padding: 0;
+ margin-bottom: 1rem; }
+ .main-content hr {
+ height: 2px;
+ padding: 0;
+ margin: 1rem 0;
+ background-color: #eff0f1;
+ border: 0; }
+
+.site-footer {
+ padding-top: 2rem;
+ margin-top: 2rem;
+ border-top: solid 1px #eff0f1; }
+ @media screen and (min-width: 64em) {
+ .site-footer {
+ font-size: 1rem; } }
+ @media screen and (min-width: 42em) and (max-width: 64em) {
+ .site-footer {
+ font-size: 1rem; } }
+ @media screen and (max-width: 42em) {
+ .site-footer {
+ font-size: 0.9rem; } }
+
+.site-footer-owner {
+ display: block;
+ text-align:center;
+ font-weight: bold; }
+
+.site-footer-power {
+ display: block;
+ font-size: 0.6rem;
+ text-align:center;}
+
+.site-footer-credits {
+ color: #819198; }
+
+.donate {
+ vertical-align: top;
+ height: 20px;
+ border: 1px solid #d4d4d4;
+ display: inline-block;
+ box-sizing: border-box;
+ line-height: 16px;
+ border-radius: 3px;
+ cursor: pointer;
+ background-image: linear-gradient(to bottom, #fcfcfc 0, #eee 100%);
+ position: relative;
+ width: 72px;
+}
+.donate:hover {
+ border-color: #ccc;
+ background-image: linear-gradient(to bottom, #eee 0, #ddd 100%);
+}
+.donate img {
+ width: 14px;
+ height: 14px;
+ position: absolute;
+ top: 2px;
+ left: 5px;
+}
+.donate a {
+ font: 700 11px/14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ color: #333;
+ text-shadow: 0 1px 0 #fff;
+ position: absolute;
+ top: 2px;
+ left: 24px;
+}
+
+#nav,
+#translations {
+ list-style-type: none;
+ text-align: center;
+ padding: 0;
+ margin: 0;
+}
+#nav li,
+#translations li {
+ display: inline-block;
+ position: relative;
+ line-height: 40px;
+}
+#nav li:last-child .nav-link,
+#translations li:last-child .nav-link {
+ margin-right: 0;
+}
+#translations {
+ margin-bottom: 0em;
+}
+#translations .delimiter {
+ color: #7f8c8d;
+ margin: 0 5px;
+}
+#translations .nav-link {
+ margin: 0;
+}
+.nav-link {
+ color: #7f8c8d;
+ padding-bottom: 3px;
+ margin: 0 1.5em;
+}
+.nav-link:first-child {
+ margin-left: 0;
+}
+.nav-link:hover,
+.nav-link.current {
+ border-bottom: 3px solid #42b983;
+}
diff --git a/assets/css/docute.css b/assets/css/docute.css
new file mode 100644
index 00000000..839c335c
--- /dev/null
+++ b/assets/css/docute.css
@@ -0,0 +1,4 @@
+.announcement{padding-top:10px;padding-bottom:10px;border-bottom:1px solid #e2e2e2;position:relative;font-size:16px;display:flex;align-items:center}.announcement:before{position:absolute;content:"";width:4px;top:0;bottom:0;left:0;background-color:#333}.announcement.announcement-primary,.announcement.announcement-primary a{color:#81b3d6}.announcement.announcement-primary:before{background-color:#81b3d6}.announcement.announcement-danger,.announcement.announcement-danger a{color:#d43f3a}.announcement.announcement-danger:before{background-color:#d43f3a}.announcement.announcement-success,.announcement.announcement-success a{color:#42b983}.announcement.announcement-success:before{background-color:#42b983}.announcement.announcement-warning,.announcement.announcement-warning a{color:#f7d24c}.announcement.announcement-warning:before{background-color:#f7d24c}/*! Hint.css - v2.5.0 - 2017-04-23
+* http://kushagragour.in/lab/hint/
+* Copyright (c) 2017 Kushagra Gour */[class*=hint--]{position:relative;display:inline-block}[class*=hint--]:after,[class*=hint--]:before{position:absolute;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);transform:translateZ(0);visibility:hidden;opacity:0;z-index:1000000;pointer-events:none;-webkit-transition:.3s ease;-moz-transition:.3s ease;transition:.3s ease;-webkit-transition-delay:0ms;-moz-transition-delay:0ms;transition-delay:0ms}[class*=hint--]:hover:after,[class*=hint--]:hover:before{visibility:visible;opacity:1;-webkit-transition-delay:.1s;-moz-transition-delay:.1s;transition-delay:.1s}[class*=hint--]:before{content:"";position:absolute;background:transparent;border:6px solid transparent;z-index:1000001}[class*=hint--]:after{background:#383838;color:#fff;padding:8px 10px;font-size:12px;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;line-height:12px;white-space:nowrap}[class*=hint--][aria-label]:after{content:attr(aria-label)}[class*=hint--][data-hint]:after{content:attr(data-hint)}[aria-label=""]:after,[aria-label=""]:before,[data-hint=""]:after,[data-hint=""]:before{display:none!important}.hint--top-left:before,.hint--top-right:before,.hint--top:before{border-top-color:#383838}.hint--bottom-left:before,.hint--bottom-right:before,.hint--bottom:before{border-bottom-color:#383838}.hint--left:before{border-left-color:#383838}.hint--right:before{border-right-color:#383838}.hint--top:before{margin-bottom:-11px}.hint--top:after,.hint--top:before{bottom:100%;left:50%}.hint--top:before{left:calc(50% - 6px)}.hint--top:after{-webkit-transform:translateX(-50%);-moz-transform:translateX(-50%);transform:translateX(-50%)}.hint--top:hover:before{-webkit-transform:translateY(-8px);-moz-transform:translateY(-8px);transform:translateY(-8px)}.hint--top:hover:after{-webkit-transform:translateX(-50%) translateY(-8px);-moz-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}.hint--bottom:before{margin-top:-11px}.hint--bottom:after,.hint--bottom:before{top:100%;left:50%}.hint--bottom:before{left:calc(50% - 6px)}.hint--bottom:after{-webkit-transform:translateX(-50%);-moz-transform:translateX(-50%);transform:translateX(-50%)}.hint--bottom:hover:before{-webkit-transform:translateY(8px);-moz-transform:translateY(8px);transform:translateY(8px)}.hint--bottom:hover:after{-webkit-transform:translateX(-50%) translateY(8px);-moz-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}.hint--right:before{margin-left:-11px;margin-bottom:-6px}.hint--right:after{margin-bottom:-14px}.hint--right:after,.hint--right:before{left:100%;bottom:50%}.hint--right:hover:after,.hint--right:hover:before{-webkit-transform:translateX(8px);-moz-transform:translateX(8px);transform:translateX(8px)}.hint--left:before{margin-right:-11px;margin-bottom:-6px}.hint--left:after{margin-bottom:-14px}.hint--left:after,.hint--left:before{right:100%;bottom:50%}.hint--left:hover:after,.hint--left:hover:before{-webkit-transform:translateX(-8px);-moz-transform:translateX(-8px);transform:translateX(-8px)}.hint--top-left:before{margin-bottom:-11px}.hint--top-left:after,.hint--top-left:before{bottom:100%;left:50%}.hint--top-left:before{left:calc(50% - 6px)}.hint--top-left:after{-webkit-transform:translateX(-100%);-moz-transform:translateX(-100%);transform:translateX(-100%);margin-left:12px}.hint--top-left:hover:before{-webkit-transform:translateY(-8px);-moz-transform:translateY(-8px);transform:translateY(-8px)}.hint--top-left:hover:after{-webkit-transform:translateX(-100%) translateY(-8px);-moz-transform:translateX(-100%) translateY(-8px);transform:translateX(-100%) translateY(-8px)}.hint--top-right:before{margin-bottom:-11px}.hint--top-right:after,.hint--top-right:before{bottom:100%;left:50%}.hint--top-right:before{left:calc(50% - 6px)}.hint--top-right:after{-webkit-transform:translateX(0);-moz-transform:translateX(0);transform:translateX(0);margin-left:-12px}.hint--top-right:hover:after,.hint--top-right:hover:before{-webkit-transform:translateY(-8px);-moz-transform:translateY(-8px);transform:translateY(-8px)}.hint--bottom-left:before{margin-top:-11px}.hint--bottom-left:after,.hint--bottom-left:before{top:100%;left:50%}.hint--bottom-left:before{left:calc(50% - 6px)}.hint--bottom-left:after{-webkit-transform:translateX(-100%);-moz-transform:translateX(-100%);transform:translateX(-100%);margin-left:12px}.hint--bottom-left:hover:before{-webkit-transform:translateY(8px);-moz-transform:translateY(8px);transform:translateY(8px)}.hint--bottom-left:hover:after{-webkit-transform:translateX(-100%) translateY(8px);-moz-transform:translateX(-100%) translateY(8px);transform:translateX(-100%) translateY(8px)}.hint--bottom-right:before{margin-top:-11px}.hint--bottom-right:after,.hint--bottom-right:before{top:100%;left:50%}.hint--bottom-right:before{left:calc(50% - 6px)}.hint--bottom-right:after{-webkit-transform:translateX(0);-moz-transform:translateX(0);transform:translateX(0);margin-left:-12px}.hint--bottom-right:hover:after,.hint--bottom-right:hover:before{-webkit-transform:translateY(8px);-moz-transform:translateY(8px);transform:translateY(8px)}.hint--large:after,.hint--medium:after,.hint--small:after{white-space:normal;line-height:1.4em;word-wrap:break-word}.hint--small:after{width:80px}.hint--medium:after{width:150px}.hint--large:after{width:300px}[class*=hint--]:after{text-shadow:0 -1px 0 #000;box-shadow:4px 4px 8px rgba(0,0,0,.3)}.hint--error:after{background-color:#b34e4d;text-shadow:0 -1px 0 #592726}.hint--error.hint--top-left:before,.hint--error.hint--top-right:before,.hint--error.hint--top:before{border-top-color:#b34e4d}.hint--error.hint--bottom-left:before,.hint--error.hint--bottom-right:before,.hint--error.hint--bottom:before{border-bottom-color:#b34e4d}.hint--error.hint--left:before{border-left-color:#b34e4d}.hint--error.hint--right:before{border-right-color:#b34e4d}.hint--warning:after{background-color:#c09854;text-shadow:0 -1px 0 #6c5328}.hint--warning.hint--top-left:before,.hint--warning.hint--top-right:before,.hint--warning.hint--top:before{border-top-color:#c09854}.hint--warning.hint--bottom-left:before,.hint--warning.hint--bottom-right:before,.hint--warning.hint--bottom:before{border-bottom-color:#c09854}.hint--warning.hint--left:before{border-left-color:#c09854}.hint--warning.hint--right:before{border-right-color:#c09854}.hint--info:after{background-color:#3986ac;text-shadow:0 -1px 0 #1a3c4d}.hint--info.hint--top-left:before,.hint--info.hint--top-right:before,.hint--info.hint--top:before{border-top-color:#3986ac}.hint--info.hint--bottom-left:before,.hint--info.hint--bottom-right:before,.hint--info.hint--bottom:before{border-bottom-color:#3986ac}.hint--info.hint--left:before{border-left-color:#3986ac}.hint--info.hint--right:before{border-right-color:#3986ac}.hint--success:after{background-color:#458746;text-shadow:0 -1px 0 #1a321a}.hint--success.hint--top-left:before,.hint--success.hint--top-right:before,.hint--success.hint--top:before{border-top-color:#458746}.hint--success.hint--bottom-left:before,.hint--success.hint--bottom-right:before,.hint--success.hint--bottom:before{border-bottom-color:#458746}.hint--success.hint--left:before{border-left-color:#458746}.hint--success.hint--right:before{border-right-color:#458746}.hint--always:after,.hint--always:before{opacity:1;visibility:visible}.hint--always.hint--top:before{-webkit-transform:translateY(-8px);-moz-transform:translateY(-8px);transform:translateY(-8px)}.hint--always.hint--top:after{-webkit-transform:translateX(-50%) translateY(-8px);-moz-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}.hint--always.hint--top-left:before{-webkit-transform:translateY(-8px);-moz-transform:translateY(-8px);transform:translateY(-8px)}.hint--always.hint--top-left:after{-webkit-transform:translateX(-100%) translateY(-8px);-moz-transform:translateX(-100%) translateY(-8px);transform:translateX(-100%) translateY(-8px)}.hint--always.hint--top-right:after,.hint--always.hint--top-right:before{-webkit-transform:translateY(-8px);-moz-transform:translateY(-8px);transform:translateY(-8px)}.hint--always.hint--bottom:before{-webkit-transform:translateY(8px);-moz-transform:translateY(8px);transform:translateY(8px)}.hint--always.hint--bottom:after{-webkit-transform:translateX(-50%) translateY(8px);-moz-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}.hint--always.hint--bottom-left:before{-webkit-transform:translateY(8px);-moz-transform:translateY(8px);transform:translateY(8px)}.hint--always.hint--bottom-left:after{-webkit-transform:translateX(-100%) translateY(8px);-moz-transform:translateX(-100%) translateY(8px);transform:translateX(-100%) translateY(8px)}.hint--always.hint--bottom-right:after,.hint--always.hint--bottom-right:before{-webkit-transform:translateY(8px);-moz-transform:translateY(8px);transform:translateY(8px)}.hint--always.hint--left:after,.hint--always.hint--left:before{-webkit-transform:translateX(-8px);-moz-transform:translateX(-8px);transform:translateX(-8px)}.hint--always.hint--right:after,.hint--always.hint--right:before{-webkit-transform:translateX(8px);-moz-transform:translateX(8px);transform:translateX(8px)}.hint--rounded:after{border-radius:4px}.hint--no-animate:after,.hint--no-animate:before{-webkit-transition-duration:0ms;-moz-transition-duration:0ms;transition-duration:0ms}.hint--bounce:after,.hint--bounce:before{-webkit-transition:opacity .3s ease,visibility .3s ease,-webkit-transform .3s cubic-bezier(.71,1.7,.77,1.24);-moz-transition:opacity .3s ease,visibility .3s ease,-moz-transform .3s cubic-bezier(.71,1.7,.77,1.24);transition:opacity .3s ease,visibility .3s ease,transform .3s cubic-bezier(.71,1.7,.77,1.24)}.markdown-body{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;color:#24292e;font-size:16px;line-height:1.5;word-wrap:break-word}.markdown-body .pl-c{color:#969896}.markdown-body .pl-c1,.markdown-body .pl-s .pl-v{color:#0086b3}.markdown-body .pl-e,.markdown-body .pl-en{color:#795da3}.markdown-body .pl-s .pl-s1,.markdown-body .pl-smi{color:#333}.markdown-body .pl-ent{color:#63a35c}.markdown-body .pl-k{color:#a71d5d}.markdown-body .pl-pds,.markdown-body .pl-s,.markdown-body .pl-s .pl-pse .pl-s1,.markdown-body .pl-sr,.markdown-body .pl-sr .pl-cce,.markdown-body .pl-sr .pl-sra,.markdown-body .pl-sr .pl-sre{color:#183691}.markdown-body .pl-smw,.markdown-body .pl-v{color:#ed6a43}.markdown-body .pl-bu{color:#b52a1d}.markdown-body .pl-c2,.markdown-body .pl-ii{color:#f8f8f8;background-color:#b52a1d}.markdown-body .pl-c2:before{content:"^M"}.markdown-body .pl-sr .pl-cce{font-weight:700;color:#63a35c}.markdown-body .pl-ml{color:#693a17}.markdown-body .pl-mh,.markdown-body .pl-mh .pl-en,.markdown-body .pl-ms{font-weight:700;color:#1d3e81}.markdown-body .pl-mq{color:teal}.markdown-body .pl-mi{font-style:italic;color:#333}.markdown-body .pl-mb{font-weight:700;color:#333}.markdown-body .pl-md{color:#bd2c00;background-color:#ffecec}.markdown-body .pl-mi1{color:#55a532;background-color:#eaffea}.markdown-body .pl-mc{color:#ef9700;background-color:#ffe3b4}.markdown-body .pl-mi2{color:#d8d8d8;background-color:gray}.markdown-body .pl-mdr{font-weight:700;color:#795da3}.markdown-body .pl-mo{color:#1d3e81}.markdown-body .pl-ba{color:#595e62}.markdown-body .pl-sg{color:silver}.markdown-body .pl-corl{text-decoration:underline;color:#183691}.markdown-body .octicon{display:inline-block;vertical-align:text-top;fill:currentColor}.markdown-body a{background-color:transparent;-webkit-text-decoration-skip:objects}.markdown-body a:active,.markdown-body a:hover{outline-width:0}.markdown-body strong{font-weight:inherit;font-weight:bolder}.markdown-body h1{margin:.67em 0}.markdown-body img{border-style:none}.markdown-body svg:not(:root){overflow:hidden}.markdown-body code,.markdown-body kbd,.markdown-body pre{font-family:monospace,monospace;font-size:1em}.markdown-body hr{box-sizing:content-box;overflow:visible}.markdown-body input{font:inherit;margin:0;overflow:visible}.markdown-body [type=checkbox]{box-sizing:border-box;padding:0}.markdown-body *{box-sizing:border-box}.markdown-body input{font-family:inherit;font-size:inherit;line-height:inherit}.markdown-body a{color:#0366d6;text-decoration:none}.markdown-body a:hover{text-decoration:underline}.markdown-body strong{font-weight:600}.markdown-body hr{height:0;margin:15px 0;overflow:hidden;background:transparent;border-bottom:1px solid #dfe2e5}.markdown-body hr:after,.markdown-body hr:before{display:table;content:""}.markdown-body hr:after{clear:both}.markdown-body table{border-spacing:0;border-collapse:collapse}.markdown-body td,.markdown-body th{padding:0}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:0;margin-bottom:0}.markdown-body h1{font-size:32px;font-weight:600}.markdown-body h2{font-size:24px;font-weight:600}.markdown-body h3{font-size:20px;font-weight:600}.markdown-body h4{font-size:16px;font-weight:600}.markdown-body h5{font-size:14px;font-weight:600}.markdown-body h6{font-size:12px;font-weight:600}.markdown-body p{margin-top:0;margin-bottom:10px}.markdown-body blockquote{margin:0}.markdown-body ol,.markdown-body ul{padding-left:0;margin-top:0;margin-bottom:0}.markdown-body ol ol,.markdown-body ul ol{list-style-type:lower-roman}.markdown-body ol ol ol,.markdown-body ol ul ol,.markdown-body ul ol ol,.markdown-body ul ul ol{list-style-type:lower-alpha}.markdown-body dd{margin-left:0}.markdown-body code{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;font-size:12px}.markdown-body pre{margin-top:0;margin-bottom:0;font:12px SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace}.markdown-body .octicon{vertical-align:text-bottom}.markdown-body .pl-0{padding-left:0!important}.markdown-body .pl-1{padding-left:4px!important}.markdown-body .pl-2{padding-left:8px!important}.markdown-body .pl-3{padding-left:16px!important}.markdown-body .pl-4{padding-left:24px!important}.markdown-body .pl-5{padding-left:32px!important}.markdown-body .pl-6{padding-left:40px!important}.markdown-body:after,.markdown-body:before{display:table;content:""}.markdown-body:after{clear:both}.markdown-body>:first-child{margin-top:0!important}.markdown-body>:last-child{margin-bottom:0!important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body .anchor{float:left;padding-right:4px;margin-left:-20px;line-height:1}.markdown-body .anchor:focus{outline:none}.markdown-body blockquote,.markdown-body dl,.markdown-body ol,.markdown-body p,.markdown-body pre,.markdown-body table,.markdown-body ul{margin-top:0;margin-bottom:16px}.markdown-body hr{height:.25em;padding:0;margin:24px 0;background-color:#e1e4e8;border:0}.markdown-body blockquote{padding:0 1em;color:#6a737d;border-left:.25em solid #dfe2e5}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body kbd{font-size:11px;background-color:#fafbfc}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#1b1f23;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h1{font-size:2em}.markdown-body h1,.markdown-body h2{padding-bottom:.3em;border-bottom:1px solid #eaecef}.markdown-body h2{font-size:1.5em}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:.875em}.markdown-body h6{font-size:.85em;color:#6a737d}.markdown-body ol,.markdown-body ul{padding-left:2em}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-top:0;margin-bottom:0}.markdown-body li>p{margin-top:16px}.markdown-body li+li{margin-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:600}.markdown-body dl dd{padding:0 16px;margin-bottom:16px}.markdown-body table{display:block;width:100%;overflow:auto}.markdown-body table th{font-weight:600}.markdown-body table td,.markdown-body table th{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body table tr{background-color:#fff;border-top:1px solid #c6cbd1}.markdown-body table tr:nth-child(2n){background-color:#f6f8fa}.markdown-body img{max-width:100%;box-sizing:content-box;background-color:#fff}.markdown-body code{padding:0;padding-top:.2em;padding-bottom:.2em;margin:0;font-size:85%;background-color:rgba(27,31,35,.05);border-radius:3px}.markdown-body code:after,.markdown-body code:before{letter-spacing:-.2em;content:"\A0"}.markdown-body pre{word-wrap:normal}.markdown-body pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:transparent;border:0}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:3px}.markdown-body pre code{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}.markdown-body pre code:after,.markdown-body pre code:before{content:normal}.markdown-body .full-commit .btn-outline:not(:disabled):hover{color:#005cc5;border-color:#005cc5}.markdown-body kbd{display:inline-block;padding:3px 5px;font:11px SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fcfcfc;border:1px solid #c6cbd1;border-bottom-color:#959da5;border-radius:3px;box-shadow:inset 0 -1px 0 #959da5}.markdown-body :checked+.radio-label{position:relative;z-index:1;border-color:#0366d6}.markdown-body .task-list-item{list-style-type:none}.markdown-body .task-list-item+.task-list-item{margin-top:3px}.markdown-body .task-list-item input{margin:0 .2em .25em -1.6em;vertical-align:middle}.markdown-body hr{border-bottom-color:#eee}#nprogress{pointer-events:none;position:relative;z-index:9999999}#nprogress .bar{background:#42b983;position:fixed;z-index:9999;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;z-index:9999;-webkit-transform:rotate(3deg) translateY(-4px);-ms-transform:rotate(3deg) translateY(-4px);transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:9999;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#42b983;border-left-color:#42b983;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}code[class*=language-],pre[class*=language-]{color:#000;background:none;text-shadow:0 1px #fff;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-]::-moz-selection,code[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-]::selection,code[class*=language-] ::selection,pre[class*=language-]::selection,pre[class*=language-] ::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.token.string{color:#42b983}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#a67f59;background:transparent}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.markdown-body{padding:0 30px}.markdown-body h1{border-bottom:none}.markdown-body h2{margin-top:50px;margin-bottom:20px}.markdown-body h3{margin-top:40px;margin-bottom:20px}.markdown-body .markdown-heading .anchor{float:left;padding-right:5px;margin-left:-20px;cursor:pointer}.markdown-body .markdown-heading .anchor:focus{outline:none}.markdown-body .markdown-heading .anchor svg{width:15px;height:15px;vertical-align:middle;visibility:hidden}.markdown-body .markdown-heading .anchor:hover svg,.markdown-body .markdown-heading:hover .anchor svg{visibility:visible}.markdown-body .markdown-heading:focus{color:#42b983;outline:none}.markdown-body pre{position:relative}.markdown-body pre:after{content:attr(data-lang);position:absolute;top:0;right:0;color:#ccc;text-align:right;font-size:.75em;padding:5px 10px 0;line-height:15px;height:15px}p.danger,p.tip,p.warning{padding:12px 24px 12px 20px;margin:2em 0;border-left:4px solid;position:relative;border-bottom-right-radius:2px;border-top-right-radius:2px}p.danger:before,p.tip:before,p.warning:before{content:"!";position:absolute;top:14px;left:-12px;color:#fff;width:20px;height:20px;border-radius:100%;text-align:center;line-height:20px;font-weight:700;font-family:Dosis,Source Sans Pro,Helvetica Neue,Arial,sans-serif}p.danger.no-bg,p.tip.no-bg,p.warning.no-bg{background-color:#f8f8f8}p.warning{border-left-color:#f7d24c;background-color:#fefbed}p.warning:before{background-color:#f7d24c}p.danger{border-left-color:#f66;background-color:hsla(0,100%,70%,.06)}p.danger:before{background-color:#f66}p.tip{border-left-color:#3c763d;background-color:rgba(241,249,241,.83)}p.tip:before{background-color:#3c763d}@media screen and (max-width:768px){.markdown-body{padding:0 10px}}*{box-sizing:border-box}#app,.page,body,html{height:100%}body{margin:0;font:14px/1.4 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;text-rendering:geometricPrecision}a{color:#34495e;text-decoration:none}.inner-x{padding-left:20px;padding-right:20px}.inner-2x{padding-left:30px;padding-right:30px}.inner-y{padding-top:20px;padding-bottom:20px}@media screen and (max-width:768px){.inner-2x,.inner-x,.inner-y{padding-left:10px;padding-right:10px}}[aria-label]{text-rendering:optimizeSpeed}[jump-to-id],[router-link]{cursor:pointer;color:#4078c0}[jump-to-id]:hover,[router-link]:hover{text-decoration:underline}.link:hover{color:#42b983}.pull-left{float:left}.pull-right{float:right}.docute-button{border:2px solid #333;background-color:#fff;cursor:pointer;outline:none;border-radius:33px;padding:5px 16px;font-size:13px;font-weight:700;transition:background-color .3s ease}.docute-button:hover{color:#fff;background-color:#333}.docute-button.docute-button-mini{padding:3px 14px;font-size:12px}.docute-button.docute-button-primary{border-color:#81b3d6;color:#81b3d6}.docute-button.docute-button-primary:hover{color:#fff;background-color:#81b3d6}.docute-button.docute-button-success{border-color:#42b983;color:#42b983}.docute-button.docute-button-success:hover{color:#fff;background-color:#42b983}.docute-button.docute-button-danger{border-color:#d43f3a;color:#d43f3a}.docute-button.docute-button-danger:hover{color:#fff;background-color:#d43f3a}.docute-button.docute-button-warning{border-color:#f7d24c;color:#f7d24c}.docute-button.docute-button-warning:hover{color:#fff;background-color:#f7d24c}.page{max-width:1280px;margin:0 auto;display:flex}.sidebar{margin:0;width:280px;border-right:1px solid rgba(0,0,0,.07);overflow-y:auto;padding:0 0 70px}.main,.sidebar{background-color:#fff}.main{height:100%;max-width:1000px;width:calc(100% - 280px);margin:0 auto}.content-wrap{height:calc(100% - 40px);overflow:auto;-webkit-overflow-scrolling:touch}.content{padding-top:20px;padding-bottom:20px;margin-top:20px}[class*=is-mobile]{display:none!important}@media screen and (min-width:768px){.no-sidebar .main{border:1px solid rgba(0,0,0,.07);border-top:none;border-bottom:none}}@media screen and (min-width:1280px){.page:not(.no-sidebar){border:1px solid rgba(0,0,0,.07);border-top:none;border-bottom:none}}@media screen and (max-width:768px){.main{width:100%;padding-top:50px}.main .content-wrap{height:100%}.is-desktop{display:none!important}.is-mobile{display:block!important}.is-mobile-flex{display:flex!important}.page{left:0}.sidebar{width:calc(100% - 50px);padding-bottom:10px;top:50px;bottom:0;left:0;position:fixed;border-right:none;z-index:1000;box-shadow:0 0 10px rgba(0,0,0,.2);transform:translateX(-120%);transition:transform .3s cubic-bezier(.4,0,0,1);-webkit-overflow-scrolling:touch}.sidebar.visible{transform:translateX(0)}}.header{height:40px;border-bottom:1px solid rgba(0,0,0,.07);background-color:#fff}.header:empty{display:none}.header .header-container{display:flex;justify-content:space-between;align-items:center;height:100%;padding:0 30px}.header .header-container,.no-sidebar .header{max-width:1000px;margin:0 auto}.header-right{display:flex;align-items:center}@media screen and (max-width:768px){.header{padding:0 10px}}.header-nav{display:flex;align-items:center}.header-nav.is-mobile .nav-list{margin-top:10px;height:auto;line-height:auto}.header-nav.is-mobile .nav-list .nav-item{float:none}.header-nav.is-mobile .nav-list .nav-item>a,.header-nav.is-mobile .nav-list .nav-item>div{border-bottom:none;height:auto;line-height:30px}.header-nav.is-mobile .nav-list .nav-item>a.router-link-active,.header-nav.is-mobile .nav-list .nav-item>div.router-link-active{color:#42b983}.header-nav.is-mobile .nav-list .dropdown-list{background-color:transparent}.header-nav.is-mobile .nav-list .nav-item-dropdown .dropdown-list{position:static;display:block;transform:none;border:none;padding:0}.nav-list{list-style:none;padding-left:0;margin:0;line-height:40px;height:40px}.nav-list .sep{height:1px;background-color:#f0f0f0;display:block;margin:8px 0}.nav-list .label{display:block;margin-top:5px;font-weight:700;font-size:14px}.nav-list .nav-item{float:left;margin-right:20px}.nav-list .nav-item>a,.nav-list .nav-item>div{color:#666;height:40px;border-bottom:3px solid transparent;display:block}.nav-list .nav-item>a.router-link-active,.nav-list .nav-item>div.router-link-active{border-bottom-color:#42b983;color:#333}.nav-list .nav-item>a:hover,.nav-list .nav-item>div:hover{color:#333}.nav-list .nav-item>a:hover:not(.router-link-active),.nav-list .nav-item>div:hover:not(.router-link-active){border-bottom-color:#e2e2e2}.nav-list .nav-item .arrow{display:inline-block;vertical-align:middle;margin-top:-1px;margin-left:6px;width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid #ccc}.nav-list .nav-item-dropdown{position:relative}.nav-list .nav-item-dropdown .dropdown-list{position:absolute;z-index:9999;top:100%;left:50%;transform:translateX(-50%);display:none;background-color:#fff;margin:0;list-style-type:none;border:1px solid #e2e2e2;border-radius:3px;white-space:nowrap;padding:10px 0}.nav-list .nav-item-dropdown .dropdown-list .dropdown-item{font-size:13px;line-height:28px}.nav-list .nav-item-dropdown .dropdown-list .dropdown-item .router-link-active,.nav-list .nav-item-dropdown .dropdown-list .dropdown-item .router-link:hover{color:#42b983}.nav-list .nav-item-dropdown:hover .dropdown-list{display:block}.svg-icon{align-items:center;justify-content:center}.header-icons,.svg-icon{display:flex}.header-icons .header-icon{display:flex;align-items:center;justify-content:center;text-align:center;color:#666}.header-icons .header-icon:not(:first-child){margin-left:20px}.header-icons .header-icon:hover,.header-icons .header-icon:hover svg{color:#333}.header-icons svg{width:22px;height:22px;color:#666}.mobile-header{box-shadow:0 0 2px rgba(0,0,0,.25);padding:0 10px;display:flex;justify-content:space-between;align-items:center;position:fixed;top:0;height:50px;left:0;right:0;z-index:9900;background-color:#fff}.mobile-header .site-title{margin:0;font-weight:300;font-size:20px;display:flex;align-items:center;-webkit-user-select:none;-moz-user-select:none;user-select:none}.mobile-header .header-left{cursor:pointer;user-select:none}.mobile-header .header-left .svg-icon{margin-right:10px;color:#999;width:24px}.sidebar-headings{list-style:none;margin:0;margin-top:10px;padding-left:0}.sidebar-headings .sidebar-heading{line-height:1.4}.sidebar-headings .sidebar-heading:not(.visible){display:none}.sidebar-headings .sidebar-heading[data-level="2"]{font-weight:700}.sidebar-headings .sidebar-heading[data-level="2"] .sidebar-heading-anchor{color:#333}.sidebar-headings .sidebar-heading[data-level="4"]{font-size:13px}.sidebar-headings .sidebar-heading[data-level="4"] .sidebar-heading-anchor{padding-left:35px}.sidebar-headings .sidebar-heading[data-level="5"]{font-size:13px}.sidebar-headings .sidebar-heading[data-level="5"] .sidebar-heading-anchor{padding-left:50px}.sidebar-headings .sidebar-heading[data-level="6"]{font-size:12px}.sidebar-headings .sidebar-heading[data-level="6"] .sidebar-heading-anchor{padding-left:66px}.sidebar-headings .sidebar-heading .sidebar-heading-anchor{color:#666;padding:7px 20px;display:block}.sidebar-headings .sidebar-heading .sidebar-heading-anchor.active,.sidebar-headings .sidebar-heading .sidebar-heading-anchor:hover{color:#42b983}@media screen and (max-width:768px){.sidebar-headings{border-top:1px solid #e2e2e2;padding-top:10px}.sidebar-heading-anchor{padding:7px 10px!important}}.search-form{position:relative;border-bottom:1px solid rgba(0,0,0,.07);height:40px}.search-form.focus .svg-icon{color:#333}.search-form .svg-icon{cursor:pointer;top:0;height:40px;width:40px;position:absolute;right:0;color:rgba(0,0,0,.22)}.search-form .svg-icon svg{width:14px;height:14px}.search-form .svg-icon.close:hover{color:#f66}.search-form .svg-icon.do-search:hover{color:#42b983}.search-box{height:100%;border:none;width:100%;outline:none;font-size:14px;padding-right:45px}.search-result .empty-search-result{padding-bottom:10px;color:#8a8a8a}.search-result .result-item{cursor:pointer;padding-top:20px;padding-bottom:20px;border-bottom:1px solid rgba(0,0,0,.07)}.search-result .result-item:last-child{margin-bottom:20px}.search-result .result-item:hover{background-color:#f9f9f9}.search-result .result-item.active{border-left:3px solid #42b983}.search-result .result-item .result-title{color:#42b983}.search-result .result-item .result-content{margin-top:5px;color:#666}.search-result .empty-search-result{padding-top:10px;color:#666}.sidebar-toggle{position:fixed;bottom:0;width:260px;height:50px;z-index:7000;background-color:hsla(0,0%,99%,.83);display:flex;align-items:center;user-select:none}.sidebar-toggle .toggle-trigger{color:#666;cursor:pointer}.sidebar-toggle .toggle-trigger:hover{color:#333}.sidebar-toggle .toggle-trigger svg{width:22px}.no-sidebar .sidebar-toggle{background-color:transparent;width:auto}@media screen and (max-width:768px){.sidebar-toggle{display:none}}._13JmIB1emdpmGGUjth0wc2_0 ul{list-style:none;margin:0;margin-top:10px;padding-left:0;font-weight:700}._13JmIB1emdpmGGUjth0wc2_0 ul ul{margin-top:0;font-weight:400}._13JmIB1emdpmGGUjth0wc2_0 ul ul a{color:#666}._13JmIB1emdpmGGUjth0wc2_0 ul a{padding:7px 20px;display:block;color:#333}._13JmIB1emdpmGGUjth0wc2_0 ul a:hover{color:#42b98d;text-decoration:none}.not-found[data-v-ebc5a04e]{height:100%;background-color:#f0f0f0;display:flex;align-items:center;justify-content:center;text-align:center}.message{font-size:30px;text-shadow:0 1px #fff}.message a{color:#42b983}
+/*# sourceMappingURL=docute.css.map*/ \ No newline at end of file
diff --git a/assets/css/normalize.css b/assets/css/normalize.css
new file mode 100644
index 00000000..30366a6e
--- /dev/null
+++ b/assets/css/normalize.css
@@ -0,0 +1,424 @@
+/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
+
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS text size adjust after orientation change, without disabling
+ * user zoom.
+ */
+
+html {
+ font-family: sans-serif; /* 1 */
+ -ms-text-size-adjust: 100%; /* 2 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+ * Remove default margin.
+ */
+
+body {
+ margin: 0;
+}
+
+/* HTML5 display definitions
+ ========================================================================== */
+
+/**
+ * Correct `block` display not defined for any HTML5 element in IE 8/9.
+ * Correct `block` display not defined for `details` or `summary` in IE 10/11
+ * and Firefox.
+ * Correct `block` display not defined for `main` in IE 11.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+ */
+
+audio,
+canvas,
+progress,
+video {
+ display: inline-block; /* 1 */
+ vertical-align: baseline; /* 2 */
+}
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+/**
+ * Address `[hidden]` styling not present in IE 8/9/10.
+ * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
+ */
+
+[hidden],
+template {
+ display: none;
+}
+
+/* Links
+ ========================================================================== */
+
+/**
+ * Remove the gray background color from active links in IE 10.
+ */
+
+a {
+ background-color: transparent;
+}
+
+/**
+ * Improve readability when focused and also mouse hovered in all browsers.
+ */
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+ */
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+ */
+
+b,
+strong {
+ font-weight: bold;
+}
+
+/**
+ * Address styling not present in Safari and Chrome.
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari, and Chrome.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Remove border when inside `a` element in IE 8/9/10.
+ */
+
+img {
+ border: 0;
+}
+
+/**
+ * Correct overflow not hidden in IE 9/10/11.
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * Address margin not present in IE 8/9 and Safari.
+ */
+
+figure {
+ margin: 1em 40px;
+}
+
+/**
+ * Address differences between Firefox and other browsers.
+ */
+
+hr {
+ box-sizing: content-box;
+ height: 0;
+}
+
+/**
+ * Contain overflow in all browsers.
+ */
+
+pre {
+ overflow: auto;
+}
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
+ */
+
+/**
+ * 1. Correct color not being inherited.
+ * Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit; /* 1 */
+ font: inherit; /* 2 */
+ margin: 0; /* 3 */
+}
+
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10/11.
+ */
+
+button {
+ overflow: visible;
+}
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+ * Correct `select` style inheritance in Firefox.
+ */
+
+button,
+select {
+ text-transform: none;
+}
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button; /* 2 */
+ cursor: pointer; /* 3 */
+}
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+
+/**
+ * Remove inner padding and border in Firefox 4+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+
+input {
+ line-height: normal;
+}
+
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
+ * (include `-moz` to future-proof).
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */ /* 2 */
+ box-sizing: content-box;
+}
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct `color` not being inherited in IE 8/9/10/11.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+
+legend {
+ border: 0; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Remove default vertical scrollbar in IE 8/9/10/11.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+
+optgroup {
+ font-weight: bold;
+}
+
+/* Tables
+ ========================================================================== */
+
+/**
+ * Remove most spacing between table cells.
+ */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+td,
+th {
+ padding: 0;
+}
diff --git a/assets/css/opensans.css b/assets/css/opensans.css
new file mode 100644
index 00000000..ebac7ce8
--- /dev/null
+++ b/assets/css/opensans.css
@@ -0,0 +1,112 @@
+/* cyrillic-ext */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/K88pR3goAWT7BTt32Z01m4X0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
+ unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
+}
+/* cyrillic */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/RjgO7rYTmqiVp7vzi-Q5UYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
+ unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/LWCjsQkB6EMdfHrEVqA1KYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
+ unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/xozscpT2726on7jbcb_pAoX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
+ unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/59ZRklaO5bWGqF5A9baEEYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
+ unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/u-WUoqrET9fUeobQW7jkRYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
+ unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3ZBw1xU1rKptJj_0jans920.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
+}
+/* cyrillic-ext */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzA7aC6SjiAOpAWOKfJDfVRY.woff2) format('woff2');
+ unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
+}
+/* cyrillic */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzBdwxCXfZpKo5kWAx_74bHs.woff2) format('woff2');
+ unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzJ6vnaPZw6nYDxM4SVEMFKg.woff2) format('woff2');
+ unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzPy1_HTwRwgtl1cPga3Fy3Y.woff2) format('woff2');
+ unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzPgrLsWo7Jk1KvZser0olKY.woff2) format('woff2');
+ unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzIjoYw3YTyktCCer_ilOlhE.woff2) format('woff2');
+ unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzBampu5_7CjHW5spxoeN3Vs.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
+}
diff --git a/assets/img/alipay.png b/assets/img/alipay.png
new file mode 100644
index 00000000..bc1088d0
--- /dev/null
+++ b/assets/img/alipay.png
Binary files differ
diff --git a/assets/img/donate.gif b/assets/img/donate.gif
new file mode 100644
index 00000000..d6df5107
--- /dev/null
+++ b/assets/img/donate.gif
Binary files differ
diff --git a/assets/img/patreon.png b/assets/img/patreon.png
new file mode 100644
index 00000000..aa0e4aee
--- /dev/null
+++ b/assets/img/patreon.png
Binary files differ
diff --git a/assets/img/paypal.png b/assets/img/paypal.png
new file mode 100644
index 00000000..780c84f6
--- /dev/null
+++ b/assets/img/paypal.png
Binary files differ
diff --git a/assets/img/weixin.png b/assets/img/weixin.png
new file mode 100644
index 00000000..1b1880b9
--- /dev/null
+++ b/assets/img/weixin.png
Binary files differ
diff --git a/assets/js/docsearch.js b/assets/js/docsearch.js
new file mode 100644
index 00000000..60592c31
--- /dev/null
+++ b/assets/js/docsearch.js
@@ -0,0 +1,2 @@
+(function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.docsearch=e():t.docsearch=e()})(this,function(){return function(t){function e(o){if(r[o])return r[o].exports;var n=r[o]={i:o,l:!1,exports:{}};return t[o].call(n.exports,n,n.exports,e),n.l=!0,n.exports}var r={};return e.m=t,e.c=r,e.i=function(t){return t},e.d=function(t,r,o){e.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:o})},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="/",e(e.s=37)}([function(t,e){var r=Object.prototype.hasOwnProperty,o=Object.prototype.toString;t.exports=function(t,e,n){if("[object Function]"!==o.call(e))throw new TypeError("iterator must be a function");var s=t.length;if(s===+s)for(var i=0;i<s;i++)e.call(n,t[i],i,t);else for(var a in t)r.call(t,a)&&e.call(n,t[a],a,t)}},function(t,e){t.exports=function(t){return JSON.parse(JSON.stringify(t))}},function(t,e,r){"use strict";function o(t,e){var o=r(0),n=this;"function"==typeof Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):n.stack=(new Error).stack||"Cannot get a stacktrace, browser is too old",this.name="AlgoliaSearchError",this.message=t||"Unknown error",e&&o(e,function(t,e){n[e]=t})}function n(t,e){function r(){var r=Array.prototype.slice.call(arguments,0);"string"!=typeof r[0]&&r.unshift(e),o.apply(this,r),this.name="AlgoliaSearch"+t+"Error"}return s(r,o),r}var s=r(8);s(o,Error),t.exports={AlgoliaSearchError:o,UnparsableJSON:n("UnparsableJSON","Could not parse the incoming response as JSON, see err.more for details"),RequestTimeout:n("RequestTimeout","Request timedout before getting a response"),Network:n("Network","Network issue, see err.more for details"),JSONPScriptFail:n("JSONPScriptFail","<script> was loaded but did not call our provided callback"),JSONPScriptError:n("JSONPScriptError","<script> unable to load due to an `error` event on it"),Unknown:n("Unknown","Unknown error occured")}},function(t,e,r){function o(){return"undefined"!=typeof document&&"WebkitAppearance"in document.documentElement.style||window.console&&(console.firebug||console.exception&&console.table)||navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31}function n(){var t=arguments,r=this.useColors;if(t[0]=(r?"%c":"")+this.namespace+(r?" %c":" ")+t[0]+(r?"%c ":" ")+"+"+e.humanize(this.diff),!r)return t;var o="color: "+this.color;t=[t[0],o,"color: inherit"].concat(Array.prototype.slice.call(t,1));var n=0,s=0;return t[0].replace(/%[a-z%]/g,function(t){"%%"!==t&&(n++,"%c"===t&&(s=n))}),t.splice(s,0,o),t}function s(){return"object"==typeof console&&console.log&&Function.prototype.apply.call(console.log,console,arguments)}function i(t){try{null==t?e.storage.removeItem("debug"):e.storage.debug=t}catch(t){}}function a(){try{return e.storage.debug}catch(t){}if("env"in r.i({env:r.i({NODE_ENV:"production"})}))return r.i({NODE_ENV:"production"}).DEBUG}e=t.exports=r(26),e.log=s,e.formatArgs=n,e.save=i,e.load=a,e.useColors=o,e.storage="undefined"!=typeof chrome&&void 0!==chrome.storage?chrome.storage.local:function(){try{return window.localStorage}catch(t){}}(),e.colors=["lightseagreen","forestgreen","goldenrod","dodgerblue","darkorchid","crimson"],e.formatters.j=function(t){try{return JSON.stringify(t)}catch(t){return"[UnexpectedJSONParseError]: "+t.message}},e.enable(a())},function(t,e,r){var o=r(0);t.exports=function(t,e){var r=[];return o(t,function(o,n){r.push(e(o,n,t))}),r}},function(t,e){var r={}.toString;t.exports=Array.isArray||function(t){return"[object Array]"==r.call(t)}},function(t,e){var r;r=function(){return this}();try{r=r||Function("return this")()||(0,eval)("this")}catch(t){"object"==typeof window&&(r=window)}t.exports=r},function(t,e,r){function o(t,e){return function(r,o,s){if("function"==typeof r&&"object"==typeof o||"object"==typeof s)throw new n.AlgoliaSearchError("index.search usage is index.search(query, params, cb)");0===arguments.length||"function"==typeof r?(s=r,r=""):1!==arguments.length&&"function"!=typeof o||(s=o,o=void 0),"object"==typeof r&&null!==r?(o=r,r=void 0):void 0!==r&&null!==r||(r="");var i="";void 0!==r&&(i+=t+"="+encodeURIComponent(r));var a;return void 0!==o&&(o.additionalUA&&(a=o.additionalUA,delete o.additionalUA),i=this.as._getSearchParams(o,i)),this._search(i,e,s,a)}}t.exports=o;var n=r(2)},function(t,e){"function"==typeof Object.create?t.exports=function(t,e){t.super_=e,t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}})}:t.exports=function(t,e){t.super_=e;var r=function(){};r.prototype=e.prototype,t.prototype=new r,t.prototype.constructor=t}},function(t,e,r){var o=r(12),n=r(33);t.exports=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.apiKey,r=t.indexName,s=t.url;return function(t){var i=t.store,a=t.registerComponent,c=s||i.state.config.url;if(!c)return console.error("docsearch requires a `url` option");if(/^http:\/\/localhost/.test(c))return console.error("`url` option cannot be localhost");"/"===c.slice(-1)&&(c=c.replace(/\/$/,""));var u=new RegExp("^"+c+"(/#)?");a("sidebar:start",n),i.registerModule("pluginSearch",{actions:{search:function(t,n){var s=(t.commit,t.dispatch),i=(t.rootState,t.getters);if(s("updateSearchKeyword",n),!n)return void s("stopSearching",null);s("startSearching");var a=i.currentTags;o("BH4D9OD16A",e).search([{indexName:r,query:n,params:{filters:a.length>0?"("+a.map(function(t){return t=/^.+:.+$/.test(t)?t:"tags:"+t,t=t.replace(/\\:/g,":")}).join(" OR ")+")":""}}]).then(function(t){var e=t.results[0];s("stopSearching",e.hits.map(function(t){var e=t.url.replace(u,""),r=Object.keys(t.hierarchy).sort();return r.length>3&&r.shift(),r=r.filter(function(e){return Boolean(t.hierarchy[e])}).map(function(e){return t.hierarchy[e]}).join(" > "),{title:r,path:e,id:t.anchor,content:t.content}}))})}}})}}},function(t,e,r){function o(t,e,o){var s=r(3)("algoliasearch"),i=r(1),a=r(5),u=r(4),l="Usage: algoliasearch(applicationID, apiKey, opts)";if(!0!==o._allowEmptyCredentials&&!t)throw new c.AlgoliaSearchError("Please provide an application ID. "+l);if(!0!==o._allowEmptyCredentials&&!e)throw new c.AlgoliaSearchError("Please provide an API key. "+l);this.applicationID=t,this.apiKey=e,this.hosts={read:[],write:[]},o=o||{};var p=o.protocol||"https:";if(this._timeouts=o.timeouts||{connect:1e3,read:2e3,write:3e4},o.timeout&&(this._timeouts.connect=this._timeouts.read=this._timeouts.write=o.timeout),/:$/.test(p)||(p+=":"),"http:"!==o.protocol&&"https:"!==o.protocol)throw new c.AlgoliaSearchError("protocol must be `http:` or `https:` (was `"+o.protocol+"`)");if(this._checkAppIdData(),o.hosts)a(o.hosts)?(this.hosts.read=i(o.hosts),this.hosts.write=i(o.hosts)):(this.hosts.read=i(o.hosts.read),this.hosts.write=i(o.hosts.write));else{var f=u(this._shuffleResult,function(e){return t+"-"+e+".algolianet.com"});this.hosts.read=[this.applicationID+"-dsn.algolia.net"].concat(f),this.hosts.write=[this.applicationID+".algolia.net"].concat(f)}this.hosts.read=u(this.hosts.read,n(p)),this.hosts.write=u(this.hosts.write,n(p)),this.extraHeaders=[],this.cache=o._cache||{},this._ua=o._ua,this._useCache=!(void 0!==o._useCache&&!o._cache)||o._useCache,this._useFallback=void 0===o.useFallback||o.useFallback,this._setTimeout=o._setTimeout,s("init done, %j",this)}function n(t){return function(e){return t+"//"+e.toLowerCase()}}function s(t){if(void 0===Array.prototype.toJSON)return JSON.stringify(t);var e=Array.prototype.toJSON;delete Array.prototype.toJSON;var r=JSON.stringify(t);return Array.prototype.toJSON=e,r}function i(t){for(var e,r,o=t.length;0!==o;)r=Math.floor(Math.random()*o),o-=1,e=t[o],t[o]=t[r],t[r]=e;return t}function a(t){var e={};for(var r in t)if(Object.prototype.hasOwnProperty.call(t,r)){var o;o="x-algolia-api-key"===r||"x-algolia-application-id"===r?"**hidden for security purposes**":t[r],e[r]=o}return e}t.exports=o;var c=r(2),u=r(19),l=r(11),p=r(23),f=r.i({NODE_ENV:"production"}).RESET_APP_DATA_TIMER&&parseInt(r.i({NODE_ENV:"production"}).RESET_APP_DATA_TIMER,10)||12e4;o.prototype.initIndex=function(t){return new l(this,t)},o.prototype.setExtraHeader=function(t,e){this.extraHeaders.push({name:t.toLowerCase(),value:e})},o.prototype.addAlgoliaAgent=function(t){-1===this._ua.indexOf(";"+t)&&(this._ua+=";"+t)},o.prototype._jsonRequest=function(t){function e(r,u){function g(t){var e=t&&t.body&&t.body.message&&t.body.status||t.statusCode||t&&t.body&&200;i("received response: statusCode: %s, computed statusCode: %d, headers: %j",t.statusCode,e,t.headers);var r=2===Math.floor(e/100),s=new Date;if(m.push({currentHost:S,headers:a(n),content:o||null,contentLength:void 0!==o?o.length:null,method:u.method,timeouts:u.timeouts,url:u.url,startTime:x,endTime:s,duration:s-x,statusCode:e}),r)return f._useCache&&p&&(p[w]=t.responseText),t.body;if(4!==Math.floor(e/100))return h+=1,b();i("unrecoverable error");var l=new c.AlgoliaSearchError(t.body&&t.body.message,{debugData:m,statusCode:e});return f._promise.reject(l)}function v(e){i("error: %s, stack: %s",e.message,e.stack);var r=new Date;return m.push({currentHost:S,headers:a(n),content:o||null,contentLength:void 0!==o?o.length:null,method:u.method,timeouts:u.timeouts,url:u.url,startTime:x,endTime:r,duration:r-x}),e instanceof c.AlgoliaSearchError||(e=new c.Unknown(e&&e.message,e)),h+=1,e instanceof c.Unknown||e instanceof c.UnparsableJSON||h>=f.hosts[t.hostType].length&&(d||!y)?(e.debugData=m,f._promise.reject(e)):e instanceof c.RequestTimeout?_():b()}function b(){return i("retrying request"),f._incrementHostIndex(t.hostType),e(r,u)}function _(){return i("retrying request with higher timeout"),f._incrementHostIndex(t.hostType),f._incrementTimeoutMultipler(),u.timeouts=f._getTimeoutsForRequest(t.hostType),e(r,u)}f._checkAppIdData();var w,x=new Date;if(f._useCache&&(w=t.url),f._useCache&&o&&(w+="_body_"+u.body),f._useCache&&p&&void 0!==p[w])return i("serving response from cache"),f._promise.resolve(JSON.parse(p[w]));if(h>=f.hosts[t.hostType].length)return!y||d?(i("could not get any response"),f._promise.reject(new c.AlgoliaSearchError("Cannot connect to the AlgoliaSearch API. Send an email to support@algolia.com to report and resolve the issue. Application id was: "+f.applicationID,{debugData:m}))):(i("switching to fallback"),h=0,u.method=t.fallback.method,u.url=t.fallback.url,u.jsonBody=t.fallback.body,u.jsonBody&&(u.body=s(u.jsonBody)),n=f._computeRequestHeaders(l),u.timeouts=f._getTimeoutsForRequest(t.hostType),f._setHostIndexByType(0,t.hostType),d=!0,e(f._request.fallback,u));var S=f._getHostByType(t.hostType),j=S+u.url,O={body:u.body,jsonBody:u.jsonBody,method:u.method,headers:n,timeouts:u.timeouts,debug:i};return i("method: %s, url: %s, headers: %j, timeouts: %d",O.method,j,O.headers,O.timeouts),r===f._request.fallback&&i("using fallback"),r.call(f,j,O).then(g,v)}this._checkAppIdData();var o,n,i=r(3)("algoliasearch:"+t.url),l=t.additionalUA||"",p=t.cache,f=this,h=0,d=!1,y=f._useFallback&&f._request.fallback&&t.fallback;this.apiKey.length>500&&void 0!==t.body&&(void 0!==t.body.params||void 0!==t.body.requests)?(t.body.apiKey=this.apiKey,n=this._computeRequestHeaders(l,!1)):n=this._computeRequestHeaders(l),void 0!==t.body&&(o=s(t.body)),i("request start");var m=[],g=e(f._request,{url:t.url,method:t.method,body:o,jsonBody:t.body,timeouts:f._getTimeoutsForRequest(t.hostType)});if(!t.callback)return g;g.then(function(e){u(function(){t.callback(null,e)},f._setTimeout||setTimeout)},function(e){u(function(){t.callback(e)},f._setTimeout||setTimeout)})},o.prototype._getSearchParams=function(t,e){if(void 0===t||null===t)return e;for(var r in t)null!==r&&void 0!==t[r]&&t.hasOwnProperty(r)&&(e+=""===e?"":"&",e+=r+"="+encodeURIComponent("[object Array]"===Object.prototype.toString.call(t[r])?s(t[r]):t[r]));return e},o.prototype._computeRequestHeaders=function(t,e){var o=r(0),n=t?this._ua+";"+t:this._ua,s={"x-algolia-agent":n,"x-algolia-application-id":this.applicationID};return!1!==e&&(s["x-algolia-api-key"]=this.apiKey),this.userToken&&(s["x-algolia-usertoken"]=this.userToken),this.securityTags&&(s["x-algolia-tagfilters"]=this.securityTags),this.extraHeaders&&o(this.extraHeaders,function(t){s[t.name]=t.value}),s},o.prototype.search=function(t,e,o){var n=r(5),s=r(4);if(!n(t))throw new Error("Usage: client.search(arrayOfQueries[, callback])");"function"==typeof e?(o=e,e={}):void 0===e&&(e={});var i=this,a={requests:s(t,function(t){var e="";return void 0!==t.query&&(e+="query="+encodeURIComponent(t.query)),{indexName:t.indexName,params:i._getSearchParams(t.params,e)}})},c=s(a.requests,function(t,e){return e+"="+encodeURIComponent("/1/indexes/"+encodeURIComponent(t.indexName)+"?"+t.params)}).join("&"),u="/1/indexes/*/queries";return void 0!==e.strategy&&(u+="?strategy="+e.strategy),this._jsonRequest({cache:this.cache,method:"POST",url:u,body:a,hostType:"read",fallback:{method:"GET",url:"/1/indexes/*",body:{params:c}},callback:o})},o.prototype.setSecurityTags=function(t){if("[object Array]"===Object.prototype.toString.call(t)){for(var e=[],r=0;r<t.length;++r)if("[object Array]"===Object.prototype.toString.call(t[r])){for(var o=[],n=0;n<t[r].length;++n)o.push(t[r][n]);e.push("("+o.join(",")+")")}else e.push(t[r]);t=e.join(",")}this.securityTags=t},o.prototype.setUserToken=function(t){this.userToken=t},o.prototype.clearCache=function(){this.cache={}},o.prototype.setRequestTimeout=function(t){t&&(this._timeouts.connect=this._timeouts.read=this._timeouts.write=t)},o.prototype.setTimeouts=function(t){this._timeouts=t},o.prototype.getTimeouts=function(){return this._timeouts},o.prototype._getAppIdData=function(){var t=p.get(this.applicationID);return null!==t&&this._cacheAppIdData(t),t},o.prototype._setAppIdData=function(t){return t.lastChange=(new Date).getTime(),this._cacheAppIdData(t),p.set(this.applicationID,t)},o.prototype._checkAppIdData=function(){var t=this._getAppIdData(),e=(new Date).getTime();return null===t||e-t.lastChange>f?this._resetInitialAppIdData(t):t},o.prototype._resetInitialAppIdData=function(t){var e=t||{};return e.hostIndexes={read:0,write:0},e.timeoutMultiplier=1,e.shuffleResult=e.shuffleResult||i([1,2,3]),this._setAppIdData(e)},o.prototype._cacheAppIdData=function(t){this._hostIndexes=t.hostIndexes,this._timeoutMultiplier=t.timeoutMultiplier,this._shuffleResult=t.shuffleResult},o.prototype._partialAppIdDataUpdate=function(t){var e=r(0),o=this._getAppIdData();return e(t,function(t,e){o[e]=t}),this._setAppIdData(o)},o.prototype._getHostByType=function(t){return this.hosts[t][this._getHostIndexByType(t)]},o.prototype._getTimeoutMultiplier=function(){return this._timeoutMultiplier},o.prototype._getHostIndexByType=function(t){return this._hostIndexes[t]},o.prototype._setHostIndexByType=function(t,e){var o=r(1),n=o(this._hostIndexes);return n[e]=t,this._partialAppIdDataUpdate({hostIndexes:n}),t},o.prototype._incrementHostIndex=function(t){return this._setHostIndexByType((this._getHostIndexByType(t)+1)%this.hosts[t].length,t)},o.prototype._incrementTimeoutMultipler=function(){var t=Math.max(this._timeoutMultiplier+1,4);return this._partialAppIdDataUpdate({timeoutMultiplier:t})},o.prototype._getTimeoutsForRequest=function(t){return{connect:this._timeouts.connect*this._timeoutMultiplier,complete:this._timeouts[t]*this._timeoutMultiplier}}},function(t,e,r){function o(t,e){this.indexName=e,this.as=t,this.typeAheadArgs=null,this.typeAheadValueOption=null,this.cache={}}var n=r(7),s=r(17),i=r(18);t.exports=o,o.prototype.clearCache=function(){this.cache={}},o.prototype.search=n("query"),o.prototype.similarSearch=n("similarQuery"),o.prototype.browse=function(t,e,o){var n,s,i=r(20),a=this;0===arguments.length||1===arguments.length&&"function"==typeof arguments[0]?(n=0,o=arguments[0],t=void 0):"number"==typeof arguments[0]?(n=arguments[0],"number"==typeof arguments[1]?s=arguments[1]:"function"==typeof arguments[1]&&(o=arguments[1],s=void 0),t=void 0,e=void 0):"object"==typeof arguments[0]?("function"==typeof arguments[1]&&(o=arguments[1]),e=arguments[0],t=void 0):"string"==typeof arguments[0]&&"function"==typeof arguments[1]&&(o=arguments[1],e=void 0),e=i({},e||{},{page:n,hitsPerPage:s,query:t});var c=this.as._getSearchParams(e,"");return this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(a.indexName)+"/browse",body:{params:c},hostType:"read",callback:o})},o.prototype.browseFrom=function(t,e){return this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/browse",body:{cursor:t},hostType:"read",callback:e})},o.prototype.searchForFacetValues=function(t,e){var o=r(1),n=r(21);if(void 0===t.facetName||void 0===t.facetQuery)throw new Error("Usage: index.searchForFacetValues({facetName, facetQuery, ...params}[, callback])");var s=t.facetName,i=n(o(t),function(t){return"facetName"===t}),a=this.as._getSearchParams(i,"");return this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/facets/"+encodeURIComponent(s)+"/query",hostType:"read",body:{params:a},callback:e})},o.prototype.searchFacet=s(function(t,e){return this.searchForFacetValues(t,e)},i("index.searchFacet(params[, callback])","index.searchForFacetValues(params[, callback])")),o.prototype._search=function(t,e,r,o){return this.as._jsonRequest({cache:this.cache,method:"POST",url:e||"/1/indexes/"+encodeURIComponent(this.indexName)+"/query",body:{params:t},hostType:"read",fallback:{method:"GET",url:"/1/indexes/"+encodeURIComponent(this.indexName),body:{params:t}},callback:r,additionalUA:o})},o.prototype.getObject=function(t,e,r){var o=this;1!==arguments.length&&"function"!=typeof e||(r=e,e=void 0);var n="";if(void 0!==e){n="?attributes=";for(var s=0;s<e.length;++s)0!==s&&(n+=","),n+=e[s]}return this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(o.indexName)+"/"+encodeURIComponent(t)+n,hostType:"read",callback:r})},o.prototype.getObjects=function(t,e,o){var n=r(5),s=r(4);if(!n(t))throw new Error("Usage: index.getObjects(arrayOfObjectIDs[, callback])");var i=this;1!==arguments.length&&"function"!=typeof e||(o=e,e=void 0);var a={requests:s(t,function(t){var r={indexName:i.indexName,objectID:t};return e&&(r.attributesToRetrieve=e.join(",")),r})};return this.as._jsonRequest({method:"POST",url:"/1/indexes/*/objects",hostType:"read",body:a,callback:o})},o.prototype.as=null,o.prototype.indexName=null,o.prototype.typeAheadArgs=null,o.prototype.typeAheadValueOption=null},function(t,e,r){"use strict";var o=r(10),n=r(13);t.exports=n(o,"(lite) ")},function(t,e,r){"use strict";var o=r(28),n=o.Promise||r(27).Promise;t.exports=function(t,e){function s(t,e,o){var n=r(1),a=r(14);return o=n(o||{}),void 0===o.protocol&&(o.protocol=a()),o._ua=o._ua||s.ua,new i(t,e,o)}function i(){t.apply(this,arguments)}var a=r(8),c=r(2),u=r(15),l=r(16),p=r(22);e=e||"",s.version=r(24),s.ua="Algolia for vanilla JavaScript "+e+s.version,s.initPlaces=p(s),o.__algolia={debug:r(3),algoliasearch:s};var f={hasXMLHttpRequest:"XMLHttpRequest"in o,hasXDomainRequest:"XDomainRequest"in o};return f.hasXMLHttpRequest&&(f.cors="withCredentials"in new XMLHttpRequest),a(i,t),i.prototype._request=function(t,e){return new n(function(r,o){function n(){if(!d){clearTimeout(h);var t;try{t={body:JSON.parse(m.responseText),responseText:m.responseText,statusCode:m.status,headers:m.getAllResponseHeaders&&m.getAllResponseHeaders()||{}}}catch(e){t=new c.UnparsableJSON({more:m.responseText})}t instanceof c.UnparsableJSON?o(t):r(t)}}function s(t){d||(clearTimeout(h),o(new c.Network({more:t})))}function i(){d=!0,m.abort(),o(new c.RequestTimeout)}function a(){g=!0,clearTimeout(h),h=setTimeout(i,e.timeouts.complete)}function l(){g||a()}function p(){!g&&m.readyState>1&&a()}if(!f.cors&&!f.hasXDomainRequest)return void o(new c.Network("CORS not supported"));t=u(t,e.headers);var h,d,y=e.body,m=f.cors?new XMLHttpRequest:new XDomainRequest,g=!1;h=setTimeout(i,e.timeouts.connect),m.onprogress=l,"onreadystatechange"in m&&(m.onreadystatechange=p),m.onload=n,m.onerror=s,m instanceof XMLHttpRequest?m.open(e.method,t,!0):m.open(e.method,t),f.cors&&(y&&("POST"===e.method?m.setRequestHeader("content-type","application/x-www-form-urlencoded"):m.setRequestHeader("content-type","application/json")),m.setRequestHeader("accept","application/json")),m.send(y)})},i.prototype._request.fallback=function(t,e){return t=u(t,e.headers),new n(function(r,o){l(t,e,function(t,e){if(t)return void o(t);r(e)})})},i.prototype._promise={reject:function(t){return n.reject(t)},resolve:function(t){return n.resolve(t)},delay:function(t){return new n(function(e){setTimeout(e,t)})}},s}},function(t,e,r){"use strict";function o(){var t=window.document.location.protocol;return"http:"!==t&&"https:"!==t&&(t="http:"),t}t.exports=o},function(t,e,r){"use strict";function o(t,e){return/\?/.test(t)?t+="&":t+="?",t+n(e)}t.exports=o;var n=r(32)},function(t,e,r){"use strict";function o(t,e,r){function o(){e.debug("JSONP: success"),m||f||(m=!0,p||(e.debug("JSONP: Fail. Script loaded but did not call the callback"),a(),r(new n.JSONPScriptFail)))}function i(){"loaded"!==this.readyState&&"complete"!==this.readyState||o()}function a(){clearTimeout(g),d.onload=null,d.onreadystatechange=null,d.onerror=null,h.removeChild(d)}function c(){try{delete window[y],delete window[y+"_loaded"]}catch(t){window[y]=window[y+"_loaded"]=void 0}}function u(){e.debug("JSONP: Script timeout"),f=!0,a(),r(new n.RequestTimeout)}function l(){e.debug("JSONP: Script error"),m||f||(a(),r(new n.JSONPScriptError))}if("GET"!==e.method)return void r(new Error("Method "+e.method+" "+t+" is not supported by JSONP."));e.debug("JSONP: start");var p=!1,f=!1;s+=1;var h=document.getElementsByTagName("head")[0],d=document.createElement("script"),y="algoliaJSONP_"+s,m=!1;window[y]=function(t){if(c(),f)return void e.debug("JSONP: Late answer, ignoring");p=!0,a(),r(null,{body:t})},t+="&callback="+y,e.jsonBody&&e.jsonBody.params&&(t+="&"+e.jsonBody.params);var g=setTimeout(u,e.timeouts.complete);d.onreadystatechange=i,d.onload=o,d.onerror=l,d.async=!0,d.defer=!0,d.src=t,h.appendChild(d)}t.exports=o;var n=r(2),s=0},function(t,e){t.exports=function(t,e){function r(){return o||(console.log(e),o=!0),t.apply(this,arguments)}var o=!1;return r}},function(t,e){t.exports=function(t,e){return"algoliasearch: `"+t+"` was replaced by `"+e+"`. Please see https://github.com/algolia/algoliasearch-client-js/wiki/Deprecated#"+t.toLowerCase().replace(".","").replace("()","")}},function(t,e){t.exports=function(t,e){e(t,0)}},function(t,e,r){var o=r(0);t.exports=function t(e){var r=Array.prototype.slice.call(arguments);return o(r,function(r){for(var o in r)r.hasOwnProperty(o)&&("object"==typeof e[o]&&"object"==typeof r[o]?e[o]=t({},e[o],r[o]):void 0!==r[o]&&(e[o]=r[o]))}),e}},function(t,e,r){t.exports=function(t,e){var o=r(30),n=r(0),s={};return n(o(t),function(r){!0!==e(r)&&(s[r]=t[r])}),s}},function(t,e,r){function o(t){return function(e,o,s){var i=r(1);s=s&&i(s)||{},s.hosts=s.hosts||["places-dsn.algolia.net","places-1.algolianet.com","places-2.algolianet.com","places-3.algolianet.com"],0!==arguments.length&&"object"!=typeof e&&void 0!==e||(e="",o="",s._allowEmptyCredentials=!0);var a=t(e,o,s),c=a.initIndex("places");return c.search=n("query","/1/places/query"),c}}t.exports=o;var n=r(7)},function(t,e,r){(function(e){function o(t,e){return c("localStorage failed with",e),i(),a=l,a.get(t)}function n(t,e){return 1===arguments.length?a.get(t):a.set(t,e)}function s(){try{return"localStorage"in e&&null!==e.localStorage&&(e.localStorage[u]||e.localStorage.setItem(u,JSON.stringify({})),!0)}catch(t){return!1}}function i(){try{e.localStorage.removeItem(u)}catch(t){}}var a,c=r(3)("algoliasearch:src/hostIndexState.js"),u="algoliasearch-client-js",l={state:{},set:function(t,e){return this.state[t]=e,this.state[t]},get:function(t){return this.state[t]||null}},p={set:function(t,r){l.set(t,r);try{var n=JSON.parse(e.localStorage[u]);return n[t]=r,e.localStorage[u]=JSON.stringify(n),n[t]}catch(e){return o(t,e)}},get:function(t){try{return JSON.parse(e.localStorage[u])[t]||null}catch(e){return o(t,e)}}};a=s()?p:l,t.exports={get:n,set:n,supportsLocalStorage:s}}).call(e,r(6))},function(t,e,r){"use strict";t.exports="3.22.1"},function(t,e,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default={computed:{showLogo:function(){return Boolean(this.$store.state.searchResult)}}}},function(t,e,r){function o(){return e.colors[l++%e.colors.length]}function n(t){function r(){}function n(){var t=n,r=+new Date,s=r-(u||r);t.diff=s,t.prev=u,t.curr=r,u=r,null==t.useColors&&(t.useColors=e.useColors()),null==t.color&&t.useColors&&(t.color=o());for(var i=new Array(arguments.length),a=0;a<i.length;a++)i[a]=arguments[a];i[0]=e.coerce(i[0]),"string"!=typeof i[0]&&(i=["%o"].concat(i));var c=0;i[0]=i[0].replace(/%([a-z%])/g,function(r,o){if("%%"===r)return r;c++;var n=e.formatters[o];if("function"==typeof n){var s=i[c];r=n.call(t,s),i.splice(c,1),c--}return r}),i=e.formatArgs.apply(t,i),(n.log||e.log||console.log.bind(console)).apply(t,i)}r.enabled=!1,n.enabled=!0;var s=e.enabled(t)?n:r;return s.namespace=t,s}function s(t){e.save(t);for(var r=(t||"").split(/[\s,]+/),o=r.length,n=0;n<o;n++)r[n]&&(t=r[n].replace(/[\\^$+?.()|[\]{}]/g,"\\$&").replace(/\*/g,".*?"),"-"===t[0]?e.skips.push(new RegExp("^"+t.substr(1)+"$")):e.names.push(new RegExp("^"+t+"$")))}function i(){e.enable("")}function a(t){var r,o;for(r=0,o=e.skips.length;r<o;r++)if(e.skips[r].test(t))return!1;for(r=0,o=e.names.length;r<o;r++)if(e.names[r].test(t))return!0;return!1}function c(t){return t instanceof Error?t.stack||t.message:t}e=t.exports=n.debug=n,e.coerce=c,e.disable=i,e.enable=s,e.enabled=a,e.humanize=r(29),e.names=[],e.skips=[],e.formatters={};var u,l=0},function(t,e,r){(function(e){(function(e,r){t.exports=r()})(0,function(){"use strict";function t(t){return"function"==typeof t||"object"==typeof t&&null!==t}function o(t){return"function"==typeof t}function n(t){L=t}function s(t){V=t}function i(){return void 0!==B?function(){B(c)}:a()}function a(){var t=setTimeout;return function(){return t(c,1)}}function c(){for(var t=0;t<F;t+=2){(0,Q[t])(Q[t+1]),Q[t]=void 0,Q[t+1]=void 0}F=0}function u(t,e){var r=arguments,o=this,n=new this.constructor(p);void 0===n[Z]&&N(n);var s=o._state;return s?function(){var t=r[s-1];V(function(){return A(s,n,t,o._result)})}():S(o,n,t,e),n}function l(t){var e=this;if(t&&"object"==typeof t&&t.constructor===e)return t;var r=new e(p);return b(r,t),r}function p(){}function f(){return new TypeError("You cannot resolve a promise with itself")}function h(){return new TypeError("A promises callback cannot return that same promise.")}function d(t){try{return t.then}catch(t){return ot.error=t,ot}}function y(t,e,r,o){try{t.call(e,r,o)}catch(t){return t}}function m(t,e,r){V(function(t){var o=!1,n=y(r,e,function(r){o||(o=!0,e!==r?b(t,r):w(t,r))},function(e){o||(o=!0,x(t,e))},"Settle: "+(t._label||" unknown promise"));!o&&n&&(o=!0,x(t,n))},t)}function g(t,e){e._state===et?w(t,e._result):e._state===rt?x(t,e._result):S(e,void 0,function(e){return b(t,e)},function(e){return x(t,e)})}function v(t,e,r){e.constructor===t.constructor&&r===u&&e.constructor.resolve===l?g(t,e):r===ot?(x(t,ot.error),ot.error=null):void 0===r?w(t,e):o(r)?m(t,e,r):w(t,e)}function b(e,r){e===r?x(e,f()):t(r)?v(e,r,d(r)):w(e,r)}function _(t){t._onerror&&t._onerror(t._result),j(t)}function w(t,e){t._state===tt&&(t._result=e,t._state=et,0!==t._subscribers.length&&V(j,t))}function x(t,e){t._state===tt&&(t._state=rt,t._result=e,V(_,t))}function S(t,e,r,o){var n=t._subscribers,s=n.length;t._onerror=null,n[s]=e,n[s+et]=r,n[s+rt]=o,0===s&&t._state&&V(j,t)}function j(t){var e=t._subscribers,r=t._state;if(0!==e.length){for(var o=void 0,n=void 0,s=t._result,i=0;i<e.length;i+=3)o=e[i],n=e[i+r],o?A(r,o,n,s):n(s);t._subscribers.length=0}}function O(){this.error=null}function T(t,e){try{return t(e)}catch(t){return nt.error=t,nt}}function A(t,e,r,n){var s=o(r),i=void 0,a=void 0,c=void 0,u=void 0;if(s){if(i=T(r,n),i===nt?(u=!0,a=i.error,i.error=null):c=!0,e===i)return void x(e,h())}else i=n,c=!0;e._state!==tt||(s&&c?b(e,i):u?x(e,a):t===et?w(e,i):t===rt&&x(e,i))}function k(t,e){try{e(function(e){b(t,e)},function(e){x(t,e)})}catch(e){x(t,e)}}function I(){return st++}function N(t){t[Z]=st++,t._state=void 0,t._result=void 0,t._subscribers=[]}function R(t,e){this._instanceConstructor=t,this.promise=new t(p),this.promise[Z]||N(this.promise),H(e)?(this._input=e,this.length=e.length,this._remaining=e.length,this._result=new Array(this.length),0===this.length?w(this.promise,this._result):(this.length=this.length||0,this._enumerate(),0===this._remaining&&w(this.promise,this._result))):x(this.promise,E())}function E(){return new Error("Array Methods must be provided an Array")}function C(t){return new R(this,t).promise}function q(t){var e=this;return new e(H(t)?function(r,o){for(var n=t.length,s=0;s<n;s++)e.resolve(t[s]).then(r,o)}:function(t,e){return e(new TypeError("You must pass an array to race."))})}function P(t){var e=this,r=new e(p);return x(r,t),r}function D(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function U(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function M(t){this[Z]=I(),this._result=this._state=void 0,this._subscribers=[],p!==t&&("function"!=typeof t&&D(),this instanceof M?k(this,t):U())}function J(){var t=void 0;if(void 0!==e)t=e;else if("undefined"!=typeof self)t=self;else try{t=Function("return this")()}catch(t){throw new Error("polyfill failed because global object is unavailable in this environment")}var r=t.Promise;if(r){var o=null;try{o=Object.prototype.toString.call(r.resolve())}catch(t){}if("[object Promise]"===o&&!r.cast)return}t.Promise=M}var $=void 0;$=Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)};var H=$,F=0,B=void 0,L=void 0,V=function(t,e){Q[F]=t,Q[F+1]=e,2===(F+=2)&&(L?L(c):W())},X="undefined"!=typeof window?window:void 0,K=X||{},G=K.MutationObserver||K.WebKitMutationObserver,Y="undefined"==typeof self&&!0&&"[object process]"==={}.toString.call(r.i({env:r.i({NODE_ENV:"production"})})),z="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,Q=new Array(1e3),W=void 0;W=Y?function(){return function(){return r.i({env:r.i({NODE_ENV:"production"})}).nextTick(c)}}():G?function(){var t=0,e=new G(c),r=document.createTextNode("");return e.observe(r,{characterData:!0}),function(){r.data=t=++t%2}}():z?function(){var t=new MessageChannel;return t.port1.onmessage=c,function(){return t.port2.postMessage(0)}}():void 0===X?function(){try{var t=r(36);return B=t.runOnLoop||t.runOnContext,i()}catch(t){return a()}}():a();var Z=Math.random().toString(36).substring(16),tt=void 0,et=1,rt=2,ot=new O,nt=new O,st=0;return R.prototype._enumerate=function(){for(var t=this.length,e=this._input,r=0;this._state===tt&&r<t;r++)this._eachEntry(e[r],r)},R.prototype._eachEntry=function(t,e){var r=this._instanceConstructor,o=r.resolve;if(o===l){var n=d(t);if(n===u&&t._state!==tt)this._settledAt(t._state,e,t._result);else if("function"!=typeof n)this._remaining--,this._result[e]=t;else if(r===M){var s=new r(p);v(s,t,n),this._willSettleAt(s,e)}else this._willSettleAt(new r(function(e){return e(t)}),e)}else this._willSettleAt(o(t),e)},R.prototype._settledAt=function(t,e,r){var o=this.promise;o._state===tt&&(this._remaining--,t===rt?x(o,r):this._result[e]=r),0===this._remaining&&w(o,this._result)},R.prototype._willSettleAt=function(t,e){var r=this;S(t,void 0,function(t){return r._settledAt(et,e,t)},function(t){return r._settledAt(rt,e,t)})},M.all=C,M.race=q,M.resolve=l,M.reject=P,M._setScheduler=n,M._setAsap=s,M._asap=V,M.prototype={constructor:M,then:u,catch:function(t){return this.then(null,t)}},M.polyfill=J,M.Promise=M,M})}).call(e,r(6))},function(t,e,r){(function(e){var r;r="undefined"!=typeof window?window:void 0!==e?e:"undefined"!=typeof self?self:{},t.exports=r}).call(e,r(6))},function(t,e){function r(t){if(t=String(t),!(t.length>1e4)){var e=/^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(t);if(e){var r=parseFloat(e[1]);switch((e[2]||"ms").toLowerCase()){case"years":case"year":case"yrs":case"yr":case"y":return r*l;case"days":case"day":case"d":return r*u;case"hours":case"hour":case"hrs":case"hr":case"h":return r*c;case"minutes":case"minute":case"mins":case"min":case"m":return r*a;case"seconds":case"second":case"secs":case"sec":case"s":return r*i;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return r;default:return}}}}function o(t){return t>=u?Math.round(t/u)+"d":t>=c?Math.round(t/c)+"h":t>=a?Math.round(t/a)+"m":t>=i?Math.round(t/i)+"s":t+"ms"}function n(t){return s(t,u,"day")||s(t,c,"hour")||s(t,a,"minute")||s(t,i,"second")||t+" ms"}function s(t,e,r){if(!(t<e))return t<1.5*e?Math.floor(t/e)+" "+r:Math.ceil(t/e)+" "+r+"s"}var i=1e3,a=60*i,c=60*a,u=24*c,l=365.25*u;t.exports=function(t,e){e=e||{};var s=typeof t;if("string"===s&&t.length>0)return r(t);if("number"===s&&!1===isNaN(t))return e.long?n(t):o(t);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(t))}},function(t,e,r){"use strict";var o=Object.prototype.hasOwnProperty,n=Object.prototype.toString,s=Array.prototype.slice,i=r(31),a=Object.prototype.propertyIsEnumerable,c=!a.call({toString:null},"toString"),u=a.call(function(){},"prototype"),l=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],p=function(t){var e=t.constructor;return e&&e.prototype===t},f={$console:!0,$external:!0,$frame:!0,$frameElement:!0,$frames:!0,$innerHeight:!0,$innerWidth:!0,$outerHeight:!0,$outerWidth:!0,$pageXOffset:!0,$pageYOffset:!0,$parent:!0,$scrollLeft:!0,$scrollTop:!0,$scrollX:!0,$scrollY:!0,$self:!0,$webkitIndexedDB:!0,$webkitStorageInfo:!0,$window:!0},h=function(){if("undefined"==typeof window)return!1;for(var t in window)try{if(!f["$"+t]&&o.call(window,t)&&null!==window[t]&&"object"==typeof window[t])try{p(window[t])}catch(t){return!0}}catch(t){return!0}return!1}(),d=function(t){if("undefined"==typeof window||!h)return p(t);try{return p(t)}catch(t){return!1}},y=function(t){var e=null!==t&&"object"==typeof t,r="[object Function]"===n.call(t),s=i(t),a=e&&"[object String]"===n.call(t),p=[];if(!e&&!r&&!s)throw new TypeError("Object.keys called on a non-object");var f=u&&r;if(a&&t.length>0&&!o.call(t,0))for(var h=0;h<t.length;++h)p.push(String(h));if(s&&t.length>0)for(var y=0;y<t.length;++y)p.push(String(y));else for(var m in t)f&&"prototype"===m||!o.call(t,m)||p.push(String(m));if(c)for(var g=d(t),v=0;v<l.length;++v)g&&"constructor"===l[v]||!o.call(t,l[v])||p.push(l[v]);return p};y.shim=function(){if(Object.keys){if(!function(){return 2===(Object.keys(arguments)||"").length}(1,2)){var t=Object.keys;Object.keys=function(e){return t(i(e)?s.call(e):e)}}}else Object.keys=y;return Object.keys||y},t.exports=y},function(t,e,r){"use strict";var o=Object.prototype.toString;t.exports=function(t){var e=o.call(t),r="[object Arguments]"===e;return r||(r="[object Array]"!==e&&null!==t&&"object"==typeof t&&"number"==typeof t.length&&t.length>=0&&"[object Function]"===o.call(t.callee)),r}},function(t,e,r){"use strict";function o(t,e){if(t.map)return t.map(e);for(var r=[],o=0;o<t.length;o++)r.push(e(t[o],o));return r}var n=function(t){switch(typeof t){case"string":return t;case"boolean":return t?"true":"false";case"number":return isFinite(t)?t:"";default:return""}};t.exports=function(t,e,r,a){return e=e||"&",r=r||"=",null===t&&(t=void 0),"object"==typeof t?o(i(t),function(i){var a=encodeURIComponent(n(i))+r;return s(t[i])?o(t[i],function(t){return a+encodeURIComponent(n(t))}).join(e):a+encodeURIComponent(n(t[i]))}).join(e):a?encodeURIComponent(n(a))+r+encodeURIComponent(n(t)):""};var s=Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)},i=Object.keys||function(t){var e=[];for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&e.push(r);return e}},function(t,e,r){var o=r(34)(r(25),r(35),null,null,null);o.options.__file="/Users/egoist/dev/docute/src/plugins/docsearch/Logo.vue",o.esModule&&Object.keys(o.esModule).some(function(t){return"default"!==t&&"__"!==t.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),o.options.functional&&console.error("[vue-loader] Logo.vue: functional components are not supported with templates, they should use render functions."),t.exports=o.exports},function(t,e){t.exports=function(t,e,r,o,n){var s,i=t=t||{},a=typeof t.default;"object"!==a&&"function"!==a||(s=t,i=t.default);var c="function"==typeof i?i.options:i;e&&(c.render=e.render,c.staticRenderFns=e.staticRenderFns),o&&(c._scopeId=o);var u;if(n?(u=function(t){t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,t||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),r&&r.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(n)},c._ssrRegister=u):r&&(u=r),u){var l=c.functional,p=l?c.render:c.beforeCreate;l?c.render=function(t,e){return u.call(e),p(t,e)}:c.beforeCreate=p?[].concat(p,u):[u]}return{esModule:s,exports:i,options:c}}},function(t,e,r){t.exports={render:function(){var t=this,e=t.$createElement,r=t._self._c||e;return t.showLogo?r("div",{staticClass:"dosearch-logo inner-x"},[t._m(0)]):t._e()},staticRenderFns:[function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("a",{attrs:{href:"https://www.algolia.com/docsearch",target:"_blank"}},[r("img",{attrs:{src:"https://www.algolia.com/static_assets/images/press/downloads/search-by-algolia.svg",alt:"algolia",width:"100"}})])}]},t.exports.render._withStripped=!0},function(t,e){},function(t,e,r){t.exports=r(9)}])});
+//# sourceMappingURL=docsearch.js.map \ No newline at end of file
diff --git a/assets/js/docute.js b/assets/js/docute.js
new file mode 100644
index 00000000..8068ac85
--- /dev/null
+++ b/assets/js/docute.js
@@ -0,0 +1,2 @@
+(function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.docute=e():t.docute=e()})(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var n={};return e.m=t,e.c=n,e.i=function(t){return t},e.d=function(t,n,r){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:r})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="/",e(e.s=132)}([function(t,e){t.exports=function(t,e,n,r,o){var i,a=t=t||{},s=typeof t.default;"object"!==s&&"function"!==s||(i=t,a=t.default);var u="function"==typeof a?a.options:a;e&&(u.render=e.render,u.staticRenderFns=e.staticRenderFns),r&&(u._scopeId=r);var c;if(o?(c=function(t){t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,t||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),n&&n.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(o)},u._ssrRegister=c):n&&(c=n),c){var l=u.functional,f=l?u.render:u.beforeCreate;l?u.render=function(t,e){return c.call(e),f(t,e)}:u.beforeCreate=f?[].concat(f,c):[c]}return{esModule:i,exports:a,options:u}}},function(t,e,n){"use strict";function r(t){C&&(t._devtoolHook=C,C.emit("vuex:init",t),C.on("vuex:travel-to-state",function(e){t.replaceState(e)}),t.subscribe(function(t,e){C.emit("vuex:mutation",t,e)}))}function o(t,e){Object.keys(t).forEach(function(n){return e(t[n],n)})}function i(t){return null!==t&&"object"==typeof t}function a(t){return t&&"function"==typeof t.then}function s(t,e){if(!t)throw new Error("[vuex] "+e)}function u(t,e){if(t.update(e),e.modules)for(var n in e.modules){if(!t.getChild(n))return void console.warn("[vuex] trying to add a new module '"+n+"' on hot reloading, manual reload is needed");u(t.getChild(n),e.modules[n])}}function c(t,e){t._actions=Object.create(null),t._mutations=Object.create(null),t._wrappedGetters=Object.create(null),t._modulesNamespaceMap=Object.create(null);var n=t.state;f(t,n,[],t._modules.root,!0),l(t,n,e)}function l(t,e,n){var r=t._vm;t.getters={};var i=t._wrappedGetters,a={};o(i,function(e,n){a[n]=function(){return e(t)},Object.defineProperty(t.getters,n,{get:function(){return t._vm[n]},enumerable:!0})});var s=j.config.silent;j.config.silent=!0,t._vm=new j({data:{$$state:e},computed:a}),j.config.silent=s,t.strict&&g(t),r&&(n&&t._withCommit(function(){r._data.$$state=null}),j.nextTick(function(){return r.$destroy()}))}function f(t,e,n,r,o){var i=!n.length,a=t._modules.getNamespace(n);if(r.namespaced&&(t._modulesNamespaceMap[a]=r),!i&&!o){var s=y(e,n.slice(0,-1)),u=n[n.length-1];t._withCommit(function(){j.set(s,u,r.state)})}var c=r.context=p(t,a,n);r.forEachMutation(function(e,n){h(t,a+n,e,c)}),r.forEachAction(function(e,n){v(t,a+n,e,c)}),r.forEachGetter(function(e,n){m(t,a+n,e,c)}),r.forEachChild(function(r,i){f(t,e,n.concat(i),r,o)})}function p(t,e,n){var r=""===e,o={dispatch:r?t.dispatch:function(n,r,o){var i=b(n,r,o),a=i.payload,s=i.options,u=i.type;return s&&s.root||(u=e+u,t._actions[u])?t.dispatch(u,a):void console.error("[vuex] unknown local action type: "+i.type+", global type: "+u)},commit:r?t.commit:function(n,r,o){var i=b(n,r,o),a=i.payload,s=i.options,u=i.type;if(!(s&&s.root||(u=e+u,t._mutations[u])))return void console.error("[vuex] unknown local mutation type: "+i.type+", global type: "+u);t.commit(u,a,s)}};return Object.defineProperties(o,{getters:{get:r?function(){return t.getters}:function(){return d(t,e)}},state:{get:function(){return y(t.state,n)}}}),o}function d(t,e){var n={},r=e.length;return Object.keys(t.getters).forEach(function(o){if(o.slice(0,r)===e){var i=o.slice(r);Object.defineProperty(n,i,{get:function(){return t.getters[o]},enumerable:!0})}}),n}function h(t,e,n,r){(t._mutations[e]||(t._mutations[e]=[])).push(function(t){n(r.state,t)})}function v(t,e,n,r){(t._actions[e]||(t._actions[e]=[])).push(function(e,o){var i=n({dispatch:r.dispatch,commit:r.commit,getters:r.getters,state:r.state,rootGetters:t.getters,rootState:t.state},e,o);return a(i)||(i=Promise.resolve(i)),t._devtoolHook?i.catch(function(e){throw t._devtoolHook.emit("vuex:error",e),e}):i})}function m(t,e,n,r){if(t._wrappedGetters[e])return void console.error("[vuex] duplicate getter key: "+e);t._wrappedGetters[e]=function(t){return n(r.state,r.getters,t.state,t.getters)}}function g(t){t._vm.$watch(function(){return this._data.$$state},function(){s(t._committing,"Do not mutate vuex store state outside mutation handlers.")},{deep:!0,sync:!0})}function y(t,e){return e.length?e.reduce(function(t,e){return t[e]},t):t}function b(t,e,n){return i(t)&&t.type&&(n=e,e=t,t=t.type),s("string"==typeof t,"Expects string as the type, but found "+typeof t+"."),{type:t,payload:e,options:n}}function _(t){if(j)return void console.error("[vuex] already installed. Vue.use(Vuex) should be called only once.");j=t,$(j)}function w(t){return Array.isArray(t)?t.map(function(t){return{key:t,val:t}}):Object.keys(t).map(function(e){return{key:e,val:t[e]}})}function x(t){return function(e,n){return"string"!=typeof e?(n=e,e=""):"/"!==e.charAt(e.length-1)&&(e+="/"),t(e,n)}}function k(t,e,n){var r=t._modulesNamespaceMap[n];return r||console.error("[vuex] module namespace not found in "+e+"(): "+n),r}n.d(e,"a",function(){return P}),n.d(e,"d",function(){return L}),n.d(e,"b",function(){return N}),n.d(e,"c",function(){return I});var $=function(t){function e(){var t=this.$options;t.store?this.$store=t.store:t.parent&&t.parent.$store&&(this.$store=t.parent.$store)}if(Number(t.version.split(".")[0])>=2){var n=t.config._lifecycleHooks.indexOf("init")>-1;t.mixin(n?{init:e}:{beforeCreate:e})}else{var r=t.prototype._init;t.prototype._init=function(t){void 0===t&&(t={}),t.init=t.init?[e].concat(t.init):e,r.call(this,t)}}},C="undefined"!=typeof window&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,O=function(t,e){this.runtime=e,this._children=Object.create(null),this._rawModule=t;var n=t.state;this.state=("function"==typeof n?n():n)||{}},S={namespaced:{}};S.namespaced.get=function(){return!!this._rawModule.namespaced},O.prototype.addChild=function(t,e){this._children[t]=e},O.prototype.removeChild=function(t){delete this._children[t]},O.prototype.getChild=function(t){return this._children[t]},O.prototype.update=function(t){this._rawModule.namespaced=t.namespaced,t.actions&&(this._rawModule.actions=t.actions),t.mutations&&(this._rawModule.mutations=t.mutations),t.getters&&(this._rawModule.getters=t.getters)},O.prototype.forEachChild=function(t){o(this._children,t)},O.prototype.forEachGetter=function(t){this._rawModule.getters&&o(this._rawModule.getters,t)},O.prototype.forEachAction=function(t){this._rawModule.actions&&o(this._rawModule.actions,t)},O.prototype.forEachMutation=function(t){this._rawModule.mutations&&o(this._rawModule.mutations,t)},Object.defineProperties(O.prototype,S);var A=function(t){var e=this;this.root=new O(t,!1),t.modules&&o(t.modules,function(t,n){e.register([n],t,!1)})};A.prototype.get=function(t){return t.reduce(function(t,e){return t.getChild(e)},this.root)},A.prototype.getNamespace=function(t){var e=this.root;return t.reduce(function(t,n){return e=e.getChild(n),t+(e.namespaced?n+"/":"")},"")},A.prototype.update=function(t){u(this.root,t)},A.prototype.register=function(t,e,n){var r=this;void 0===n&&(n=!0);var i=this.get(t.slice(0,-1)),a=new O(e,n);i.addChild(t[t.length-1],a),e.modules&&o(e.modules,function(e,o){r.register(t.concat(o),e,n)})},A.prototype.unregister=function(t){var e=this.get(t.slice(0,-1)),n=t[t.length-1];e.getChild(n).runtime&&e.removeChild(n)};var j,E=function(t){var e=this;void 0===t&&(t={}),s(j,"must call Vue.use(Vuex) before creating a store instance."),s("undefined"!=typeof Promise,"vuex requires a Promise polyfill in this browser.");var n=t.state;void 0===n&&(n={});var o=t.plugins;void 0===o&&(o=[]);var i=t.strict;void 0===i&&(i=!1),this._committing=!1,this._actions=Object.create(null),this._mutations=Object.create(null),this._wrappedGetters=Object.create(null),this._modules=new A(t),this._modulesNamespaceMap=Object.create(null),this._subscribers=[],this._watcherVM=new j;var a=this,u=this,c=u.dispatch,p=u.commit;this.dispatch=function(t,e){return c.call(a,t,e)},this.commit=function(t,e,n){return p.call(a,t,e,n)},this.strict=i,f(this,n,[],this._modules.root),l(this,n),o.concat(r).forEach(function(t){return t(e)})},T={state:{}};T.state.get=function(){return this._vm._data.$$state},T.state.set=function(t){s(!1,"Use store.replaceState() to explicit replace store state.")},E.prototype.commit=function(t,e,n){var r=this,o=b(t,e,n),i=o.type,a=o.payload,s=o.options,u={type:i,payload:a},c=this._mutations[i];if(!c)return void console.error("[vuex] unknown mutation type: "+i);this._withCommit(function(){c.forEach(function(t){t(a)})}),this._subscribers.forEach(function(t){return t(u,r.state)}),s&&s.silent&&console.warn("[vuex] mutation type: "+i+". Silent option has been removed. Use the filter functionality in the vue-devtools")},E.prototype.dispatch=function(t,e){var n=b(t,e),r=n.type,o=n.payload,i=this._actions[r];return i?i.length>1?Promise.all(i.map(function(t){return t(o)})):i[0](o):void console.error("[vuex] unknown action type: "+r)},E.prototype.subscribe=function(t){var e=this._subscribers;return e.indexOf(t)<0&&e.push(t),function(){var n=e.indexOf(t);n>-1&&e.splice(n,1)}},E.prototype.watch=function(t,e,n){var r=this;return s("function"==typeof t,"store.watch only accepts a function."),this._watcherVM.$watch(function(){return t(r.state,r.getters)},e,n)},E.prototype.replaceState=function(t){var e=this;this._withCommit(function(){e._vm._data.$$state=t})},E.prototype.registerModule=function(t,e){"string"==typeof t&&(t=[t]),s(Array.isArray(t),"module path must be a string or an Array."),this._modules.register(t,e),f(this,this.state,t,this._modules.get(t)),l(this,this.state)},E.prototype.unregisterModule=function(t){var e=this;"string"==typeof t&&(t=[t]),s(Array.isArray(t),"module path must be a string or an Array."),this._modules.unregister(t),this._withCommit(function(){var n=y(e.state,t.slice(0,-1));j.delete(n,t[t.length-1])}),c(this)},E.prototype.hotUpdate=function(t){this._modules.update(t),c(this,!0)},E.prototype._withCommit=function(t){var e=this._committing;this._committing=!0,t(),this._committing=e},Object.defineProperties(E.prototype,T),"undefined"!=typeof window&&window.Vue&&_(window.Vue);var P=x(function(t,e){var n={};return w(e).forEach(function(e){var r=e.key,o=e.val;n[r]=function(){var e=this.$store.state,n=this.$store.getters;if(t){var r=k(this.$store,"mapState",t);if(!r)return;e=r.context.state,n=r.context.getters}return"function"==typeof o?o.call(this,e,n):e[o]},n[r].vuex=!0}),n}),L=x(function(t,e){var n={};return w(e).forEach(function(e){var r=e.key,o=e.val;o=t+o,n[r]=function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];if(!t||k(this.$store,"mapMutations",t))return this.$store.commit.apply(this.$store,[o].concat(e))}}),n}),N=x(function(t,e){var n={};return w(e).forEach(function(e){var r=e.key,o=e.val;o=t+o,n[r]=function(){if(!t||k(this.$store,"mapGetters",t))return o in this.$store.getters?this.$store.getters[o]:void console.error("[vuex] unknown getter: "+o)},n[r].vuex=!0}),n}),I=x(function(t,e){var n={};return w(e).forEach(function(e){var r=e.key,o=e.val;o=t+o,n[r]=function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];if(!t||k(this.$store,"mapActions",t))return this.$store.dispatch.apply(this.$store,[o].concat(e))}}),n}),M={Store:E,install:_,version:"2.3.0",mapState:P,mapMutations:L,mapGetters:N,mapActions:I};e.e=M},function(t,e){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e,n){"use strict";var r=n(102);n.n(r);e.a=n.i(r.makeComponent)({github:n(87),twitter:n(91),edit:n(86),menu:n(89),link:n(20),search:n(90),close:n(85),info:n(88)})},function(t,e,n){"use strict";n.d(e,"a",function(){return o}),n.d(e,"c",function(){return i}),n.d(e,"b",function(){return a});var r="undefined"!=typeof document,o=r&&document.querySelector.bind(document),i=r&&document.querySelectorAll.bind(document),a=r&&Math.max(document.documentElement.clientWidth,window.innerWidth||0)<=768},function(t,e,n){"use strict";function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}n.d(e,"a",function(){return s});var o=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),i=function(){function t(){r(this,t),this.components={}}return o(t,[{key:"add",value:function(t,e){this.components[t]||(this.components[t]=[]),this.components[t].push(e)}},{key:"count",value:function(t){return this.components[t]?this.components[t].length:0}}]),t}(),a=new i,s=function(){a.add.apply(a,arguments)};e.b=a},function(t,e,n){"use strict";var r=n(52),o=n.n(r);e.a=o()()},function(t,e,n){t.exports=n(92)},function(t,e,n){"use strict";var r=n(5);e.a={props:{place:{validator:function(t){return["content:start","content:end","sidebar:start","sidebar:end","nav:start","nav:end","icons:start","icons:end"].indexOf(t)>-1}}},data:function(){return{components:r.b.components[this.place],className:"custom-components-"+this.place.replace(":","-")}},render:function(){var t=arguments[0];if(this.components&&0!==this.components.length)return t("div",{class:"custom-components "+this.className},[this.components.map(function(e){return t(e,null,[])})])}}},function(t,e,n){"use strict";function r(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e<t.length;e++)n[e]=t[e];return n}return Array.from(t)}function o(t,e){var n=Math.min.apply(Math,r(t.map(function(t){return t[e]})));return t.filter(function(t){return t[e]===n})}function i(t,e){var n=Math.max.apply(Math,r(t.map(function(t){return t[e]})));return t.filter(function(t){return t[e]===n})}function a(t,e){return"[object "+e+"]"===Object.prototype.toString.call(t)}function s(t){return!(/^https?:\/\//.test(t)&&!new RegExp("^"+location.origin).test(t))&&"include"}e.d=o,e.c=i,e.b=a,e.a=s},function(t,e,n){"use strict";function r(t){this.tokens=[],this.tokens.links={},this.options=t||p.defaults,this.rules=v.normal,this.options.gfm&&(this.options.tables?this.rules=v.tables:this.rules=v.gfm)}function o(t,e){if(this.options=e||p.defaults,this.links=t,this.rules=m.normal,this.renderer=this.options.renderer||new i,this.renderer.options=this.options,!this.links)throw new Error("Tokens array requires a `links` property.");this.options.gfm?this.options.breaks?this.rules=m.breaks:this.rules=m.gfm:this.options.pedantic&&(this.rules=m.pedantic)}function i(t){this.options=t||{}}function a(t){this.tokens=[],this.token=null,this.options=t||p.defaults,this.options.renderer=this.options.renderer||new i,this.renderer=this.options.renderer,this.renderer.options=this.options}function s(t,e){return t.replace(e?/&/g:/&(?!#?\w+;)/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function u(t){return t.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g,function(t,e){return e=e.toLowerCase(),"colon"===e?":":"#"===e.charAt(0)?"x"===e.charAt(1)?String.fromCharCode(parseInt(e.substring(2),16)):String.fromCharCode(+e.substring(1)):""})}function c(t,e){return t=t.source,e=e||"",function n(r,o){return r?(o=o.source||o,o=o.replace(/(^|[^\[])\^/g,"$1"),t=t.replace(r,o),n):new RegExp(t,e)}}function l(){}function f(t){for(var e,n,r=1;r<arguments.length;r++){e=arguments[r];for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])}return t}function p(t,e,n){if(n||"function"==typeof e){n||(n=e,e=null),e=f({},p.defaults,e||{});var o,i,u=e.highlight,c=0;try{o=r.lex(t,e)}catch(t){return n(t)}i=o.length;var l=function(t){if(t)return e.highlight=u,n(t);var r;try{r=a.parse(o,e)}catch(e){t=e}return e.highlight=u,t?n(t):n(null,r)};if(!u||u.length<3)return l();if(delete e.highlight,!i)return l();for(;c<o.length;c++)(function(t){"code"!==t.type?--i||l():u(t.text,t.lang,function(e,n){return e?l(e):null==n||n===t.text?--i||l():(t.text=n,t.escaped=!0,void(--i||l()))})})(o[c])}else try{return e&&(e=f({},p.defaults,e)),a.parse(r.lex(t,e),e)}catch(t){if(t.message+="\nPlease report this to https://github.com/chjj/marked.",(e||p.defaults).silent)return"<p>An error occured:</p><pre>"+s(t.message+"",!0)+"</pre>";throw t}}var d=n(16),h=function(){function t(t,e){var n=[],r=!0,o=!1,i=void 0;try{for(var a,s=t[Symbol.iterator]();!(r=(a=s.next()).done)&&(n.push(a.value),!e||n.length!==e);r=!0);}catch(t){o=!0,i=t}finally{try{!r&&s.return&&s.return()}finally{if(o)throw i}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),v={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:l,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:l,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:l,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};v.checkbox=/^\[([ x])\] +/,v.bullet=/(?:[*+-]|\d+\.)/,v.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/,v.item=c(v.item,"gm")(/bull/g,v.bullet)(),v.list=c(v.list)(/bull/g,v.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+v.def.source+")")(),v.blockquote=c(v.blockquote)("def",v.def)(),v._tag="(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b",v.html=c(v.html)("comment",/<!--[\s\S]*?-->/)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,v._tag)(),v.paragraph=c(v.paragraph)("hr",v.hr)("heading",v.heading)("lheading",v.lheading)("blockquote",v.blockquote)("tag","<"+v._tag)("def",v.def)(),v.normal=f({},v),v.gfm=f({},v.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/}),v.gfm.paragraph=c(v.paragraph)("(?!","(?!"+v.gfm.fences.source.replace("\\1","\\2")+"|"+v.list.source.replace("\\1","\\3")+"|")(),v.tables=f({},v.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/}),r.rules=v,r.lex=function(t,e){return new r(e).lex(t)},r.prototype.lex=function(t){return t=t.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n"),this.token(t,!0)},r.prototype.token=function(t,e,n){for(var r,o,i,a,s,u,c,l,f,p,t=t.replace(/^ +$/gm,"");t;)if((i=this.rules.newline.exec(t))&&(t=t.substring(i[0].length),i[0].length>1&&this.tokens.push({type:"space"})),i=this.rules.code.exec(t))t=t.substring(i[0].length),i=i[0].replace(/^ {4}/gm,""),this.tokens.push({type:"code",text:this.options.pedantic?i:i.replace(/\n+$/,"")});else if(i=this.rules.fences.exec(t)){t=t.substring(i[0].length);var d=i[2]?/^([^{]*){?([^}]+)?}?/.exec(i[2]):[,i[2]],m=h(d,3),g=m[1],y=m[2];this.tokens.push({type:"code",lang:g,line:y,text:i[3]||""})}else if(i=this.rules.heading.exec(t))t=t.substring(i[0].length),this.tokens.push({type:"heading",depth:i[1].length,text:i[2]});else if(e&&(i=this.rules.nptable.exec(t))){for(t=t.substring(i[0].length),u={type:"table",header:i[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:i[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:i[3].replace(/\n$/,"").split("\n")},l=0;l<u.align.length;l++)/^ *-+: *$/.test(u.align[l])?u.align[l]="right":/^ *:-+: *$/.test(u.align[l])?u.align[l]="center":/^ *:-+ *$/.test(u.align[l])?u.align[l]="left":u.align[l]=null;for(l=0;l<u.cells.length;l++)u.cells[l]=u.cells[l].split(/ *\| */);this.tokens.push(u)}else if(i=this.rules.lheading.exec(t))t=t.substring(i[0].length),this.tokens.push({type:"heading",depth:"="===i[2]?1:2,text:i[1]});else if(i=this.rules.hr.exec(t))t=t.substring(i[0].length),this.tokens.push({type:"hr"});else if(i=this.rules.blockquote.exec(t))t=t.substring(i[0].length),this.tokens.push({type:"blockquote_start"}),i=i[0].replace(/^ *> ?/gm,""),this.token(i,e,!0),this.tokens.push({type:"blockquote_end"});else if(i=this.rules.list.exec(t)){for(t=t.substring(i[0].length),a=i[2],this.tokens.push({type:"list_start",ordered:a.length>1}),i=i[0].match(this.rules.item),r=!1,f=i.length,l=0;l<f;l++)u=i[l],c=u.length,u=u.replace(/^ *([*+-]|\d+\.) +/,""),this.options.gfm&&(p=v.checkbox.exec(u),p?(p="x"===p[1],u=u.replace(v.checkbox,"")):p=void 0),~u.indexOf("\n ")&&(c-=u.length,u=this.options.pedantic?u.replace(/^ {1,4}/gm,""):u.replace(new RegExp("^ {1,"+c+"}","gm"),"")),this.options.smartLists&&l!==f-1&&(s=v.bullet.exec(i[l+1])[0],a===s||a.length>1&&s.length>1||(t=i.slice(l+1).join("\n")+t,l=f-1)),o=r||/\n\n(?!\s*$)/.test(u),l!==f-1&&(r="\n"===u.charAt(u.length-1),o||(o=r)),this.tokens.push({checked:p,type:o?"loose_item_start":"list_item_start"}),this.token(u,!1,n),this.tokens.push({type:"list_item_end"});this.tokens.push({type:"list_end"})}else if(i=this.rules.html.exec(t))t=t.substring(i[0].length),this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:!this.options.sanitizer&&("pre"===i[1]||"script"===i[1]||"style"===i[1]),text:i[0]});else if(!n&&e&&(i=this.rules.def.exec(t)))t=t.substring(i[0].length),this.tokens.links[i[1].toLowerCase()]={href:i[2],title:i[3]};else if(e&&(i=this.rules.table.exec(t))){for(t=t.substring(i[0].length),u={type:"table",header:i[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:i[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:i[3].replace(/(?: *\| *)?\n$/,"").split("\n")},l=0;l<u.align.length;l++)/^ *-+: *$/.test(u.align[l])?u.align[l]="right":/^ *:-+: *$/.test(u.align[l])?u.align[l]="center":/^ *:-+ *$/.test(u.align[l])?u.align[l]="left":u.align[l]=null;for(l=0;l<u.cells.length;l++)u.cells[l]=u.cells[l].replace(/^ *\| *| *\| *$/g,"").split(/ *\| */);this.tokens.push(u)}else if(e&&(i=this.rules.paragraph.exec(t)))t=t.substring(i[0].length),this.tokens.push({type:"paragraph",text:"\n"===i[1].charAt(i[1].length-1)?i[1].slice(0,-1):i[1]});else if(i=this.rules.text.exec(t))t=t.substring(i[0].length),this.tokens.push({type:"text",text:i[0]});else if(t)throw new Error("Infinite loop on byte: "+t.charCodeAt(0));return this.tokens};var m={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:l,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:l,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/};m._inside=/(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/,m._href=/\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/,m.link=c(m.link)("inside",m._inside)("href",m._href)(),m.reflink=c(m.reflink)("inside",m._inside)(),m.normal=f({},m),m.pedantic=f({},m.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/}),m.gfm=f({},m.normal,{escape:c(m.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:c(m.text)("]|","~]|")("|","|https?://|")()}),m.breaks=f({},m.gfm,{br:c(m.br)("{2,}","*")(),text:c(m.gfm.text)("{2,}","*")()}),o.rules=m,o.output=function(t,e,n){return new o(e,n).output(t)},o.prototype.output=function(t){for(var e,n,r,o,i="";t;)if(o=this.rules.escape.exec(t))t=t.substring(o[0].length),i+=o[1];else if(o=this.rules.autolink.exec(t))t=t.substring(o[0].length),"@"===o[2]?(n=":"===o[1].charAt(6)?this.mangle(o[1].substring(7)):this.mangle(o[1]),r=this.mangle("mailto:")+n):(n=s(o[1]),r=n),i+=this.renderer.link(r,null,n);else if(this.inLink||!(o=this.rules.url.exec(t))){if(o=this.rules.tag.exec(t))!this.inLink&&/^<a /i.test(o[0])?this.inLink=!0:this.inLink&&/^<\/a>/i.test(o[0])&&(this.inLink=!1),t=t.substring(o[0].length),i+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(o[0]):s(o[0]):o[0];else if(o=this.rules.link.exec(t))t=t.substring(o[0].length),this.inLink=!0,i+=this.outputLink(o,{href:o[2],title:o[3]}),this.inLink=!1;else if((o=this.rules.reflink.exec(t))||(o=this.rules.nolink.exec(t))){if(t=t.substring(o[0].length),e=(o[2]||o[1]).replace(/\s+/g," "),!(e=this.links[e.toLowerCase()])||!e.href){i+=o[0].charAt(0),t=o[0].substring(1)+t;continue}this.inLink=!0,i+=this.outputLink(o,e),this.inLink=!1}else if(o=this.rules.strong.exec(t))t=t.substring(o[0].length),i+=this.renderer.strong(this.output(o[2]||o[1]));else if(o=this.rules.em.exec(t))t=t.substring(o[0].length),i+=this.renderer.em(this.output(o[2]||o[1]));else if(o=this.rules.code.exec(t))t=t.substring(o[0].length),i+=this.renderer.codespan(s(o[2],!0));else if(o=this.rules.br.exec(t))t=t.substring(o[0].length),i+=this.renderer.br();else if(o=this.rules.del.exec(t))t=t.substring(o[0].length),i+=this.renderer.del(this.output(o[1]));else if(o=this.rules.text.exec(t))t=t.substring(o[0].length),i+=this.renderer.text(this.smartypants(o[0]));else if(t)throw new Error("Infinite loop on byte: "+t.charCodeAt(0))}else t=t.substring(o[0].length),n=s(o[1]),r=n,i+=this.renderer.link(r,null,n);return i},o.prototype.outputLink=function(t,e){var n=s(e.href),r=e.title?s(e.title):null;return"!"!==t[0].charAt(0)?this.renderer.link(n,r,this.output(t[1])):this.renderer.image(n,r,s(t[1]))},o.prototype.smartypants=function(t){return this.options.smartypants?t.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014\/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014\/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…"):t},o.prototype.mangle=function(t){if(!this.options.mangle)return t;for(var e,n="",r=t.length,o=0;o<r;o++)e=t.charCodeAt(o),Math.random()>.5&&(e="x"+e.toString(16)),n+="&#"+e+";";return n},i.prototype.code=function(t,e,n,r){if(this.options.highlight){var o=this.options.highlight(t,e,r);null!=o&&o!==t&&(n=!0,t=o)}var i="";return r&&(i+=' data-line="'+r+'"'),e?"<pre"+i+' data-lang="'+e+'"><code class="'+this.options.langPrefix+s(e,!0)+'">'+(n?t:s(t,!0))+"\n</code></pre>\n":"<pre"+i+"><code>"+(n?t:s(t,!0))+"\n</code></pre>"},i.prototype.blockquote=function(t){return"<blockquote>\n"+t+"</blockquote>\n"},i.prototype.html=function(t){return t},i.prototype.heading=function(t,e,n){return"<h"+e+' id="'+this.options.headerPrefix+n.toLowerCase().replace(/[^\w]+/g,"-")+'">'+t+"</h"+e+">\n"},i.prototype.hr=function(){return this.options.xhtml?"<hr/>\n":"<hr>\n"},i.prototype.list=function(t,e,n){var r=e?"ol":"ul";return"<"+r+(n?' class="task-list"':"")+">\n"+t+"</"+r+">\n"},i.prototype.listitem=function(t,e){return void 0===e?"<li>"+t+"</li>\n":'<li class="task-list-item"><input type="checkbox" disabled class="task-list-item-checkbox"'+(e?" checked":"")+"> "+t+"</li>\n"},i.prototype.paragraph=function(t){return"<p>"+t+"</p>\n"},i.prototype.table=function(t,e){return"<table>\n<thead>\n"+t+"</thead>\n<tbody>\n"+e+"</tbody>\n</table>\n"},i.prototype.tablerow=function(t){return"<tr>\n"+t+"</tr>\n"},i.prototype.tablecell=function(t,e){var n=e.header?"th":"td";return(e.align?"<"+n+' style="text-align:'+e.align+'">':"<"+n+">")+t+"</"+n+">\n"},i.prototype.strong=function(t){return"<strong>"+t+"</strong>"},i.prototype.em=function(t){return"<em>"+t+"</em>"},i.prototype.codespan=function(t){return"<code>"+t+"</code>"},i.prototype.br=function(){return this.options.xhtml?"<br/>":"<br>"},i.prototype.del=function(t){return"<del>"+t+"</del>"},i.prototype.link=function(t,e,r){if(this.options.sanitize){try{var o=decodeURIComponent(u(t)).replace(/[^\w:]/g,"").toLowerCase()}catch(t){return""}if(0===o.indexOf("javascript:")||0===o.indexOf("vbscript:"))return""}var i,a,s="jump-to-id"===t,c=t&&"#"===t.charAt(0),l=t&&"/"===t.charAt(0),f="hash"===this.options.context.routerMode?"#"+this.options.context.path:this.options.context.path;s?(i=n.i(d.a)(r),t=f+"?id="+i,a="jump-to-id"):c?(i=t.slice(1),t=f+"?id="+i,a="jump-to-id"):l&&(t=t.replace("#","?id="),i=t,a="router-link");var p='<a href="'+t+'"';return e&&(p+=' title="'+e+'"'),a&&(p+=" "+a+'="'+i+'"'),this.options.targetBlank&&!a&&(p+=' target="_blank"'),p+=">"+r+"</a>"},i.prototype.image=function(t,e,n){var r='<img src="'+t+'" alt="'+n+'"';return e&&(r+=' title="'+e+'"'),r+=this.options.xhtml?"/>":">"},i.prototype.text=function(t){return t},a.parse=function(t,e,n){return new a(e,n).parse(t)},a.prototype.parse=function(t){this.inline=new o(t.links,this.options,this.renderer),this.tokens=t.reverse();for(var e="";this.next();)e+=this.tok();return e},a.prototype.next=function(){return this.token=this.tokens.pop()},a.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},a.prototype.parseText=function(){for(var t=this.token.text;"text"===this.peek().type;)t+="\n"+this.next().text;return this.inline.output(t)},a.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text);case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped,this.token.line);case"table":var t,e,n,r,o="",i="";for(n="",t=0;t<this.token.header.length;t++)({header:!0,align:this.token.align[t]}),n+=this.renderer.tablecell(this.inline.output(this.token.header[t]),{header:!0,align:this.token.align[t]});for(o+=this.renderer.tablerow(n),t=0;t<this.token.cells.length;t++){for(e=this.token.cells[t],n="",r=0;r<e.length;r++)n+=this.renderer.tablecell(this.inline.output(e[r]),{header:!1,align:this.token.align[r]});i+=this.renderer.tablerow(n)}return this.renderer.table(o,i);case"blockquote_start":for(var i="";"blockquote_end"!==this.next().type;)i+=this.tok();return this.renderer.blockquote(i);case"list_start":for(var i="",a=!1,s=this.token.ordered;"list_end"!==this.next().type;)void 0!==this.token.checked&&(a=!0),i+=this.tok();return this.renderer.list(i,s,a);case"list_item_start":for(var i="",u=this.token.checked;"list_item_end"!==this.next().type;)i+="text"===this.token.type?this.parseText():this.tok();return this.renderer.listitem(i,u);case"loose_item_start":for(var i="";"list_item_end"!==this.next().type;)i+=this.tok();return this.renderer.listitem(i,u);case"html":var c=this.token.pre||this.options.pedantic?this.token.text:this.inline.output(this.token.text);return this.renderer.html(c);case"paragraph":return this.renderer.paragraph(this.inline.output(this.token.text));case"text":return this.renderer.paragraph(this.parseText())}},l.exec=l,p.options=p.setOptions=function(t){return f(p.defaults,t),p},p.defaults={gfm:!0,tables:!0,breaks:!1,pedantic:!1,sanitize:!1,sanitizer:null,mangle:!0,smartLists:!1,silent:!1,highlight:null,langPrefix:"lang-",smartypants:!1,headerPrefix:"",renderer:new i,xhtml:!1,targetBlank:!0,context:{}},p.Parser=a,p.parser=a.parse,p.Renderer=i,p.Lexer=r,p.lexer=r.lex,p.InlineLexer=o,p.inlineLexer=o.output,p.parse=p,e.a=p},function(t,e,n){var r,o;(function(i,a){r=a,void 0!==(o="function"==typeof r?r.call(e,n,e,t):r)&&(t.exports=o)})(0,function(){function t(t,e,n){return t<e?e:t>n?n:t}function e(t){return 100*(-1+t)}function n(t,n,r){var o;return o="translate3d"===c.positionUsing?{transform:"translate3d("+e(t)+"%,0,0)"}:"translate"===c.positionUsing?{transform:"translate("+e(t)+"%,0)"}:{"margin-left":e(t)+"%"},o.transition="all "+n+"ms "+r,o}function r(t,e){return("string"==typeof t?t:a(t)).indexOf(" "+e+" ")>=0}function o(t,e){var n=a(t),o=n+e;r(n,e)||(t.className=o.substring(1))}function i(t,e){var n,o=a(t);r(t,e)&&(n=o.replace(" "+e+" "," "),t.className=n.substring(1,n.length-1))}function a(t){return(" "+(t.className||"")+" ").replace(/\s+/gi," ")}function s(t){t&&t.parentNode&&t.parentNode.removeChild(t)}var u={};u.version="0.2.0";var c=u.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'};u.configure=function(t){var e,n;for(e in t)void 0!==(n=t[e])&&t.hasOwnProperty(e)&&(c[e]=n);return this},u.status=null,u.set=function(e){var r=u.isStarted();e=t(e,c.minimum,1),u.status=1===e?null:e;var o=u.render(!r),i=o.querySelector(c.barSelector),a=c.speed,s=c.easing;return o.offsetWidth,l(function(t){""===c.positionUsing&&(c.positionUsing=u.getPositioningCSS()),f(i,n(e,a,s)),1===e?(f(o,{transition:"none",opacity:1}),o.offsetWidth,setTimeout(function(){f(o,{transition:"all "+a+"ms linear",opacity:0}),setTimeout(function(){u.remove(),t()},a)},a)):setTimeout(t,a)}),this},u.isStarted=function(){return"number"==typeof u.status},u.start=function(){u.status||u.set(0);var t=function(){setTimeout(function(){u.status&&(u.trickle(),t())},c.trickleSpeed)};return c.trickle&&t(),this},u.done=function(t){return t||u.status?u.inc(.3+.5*Math.random()).set(1):this},u.inc=function(e){var n=u.status;return n?("number"!=typeof e&&(e=(1-n)*t(Math.random()*n,.1,.95)),n=t(n+e,0,.994),u.set(n)):u.start()},u.trickle=function(){return u.inc(Math.random()*c.trickleRate)},function(){var t=0,e=0;u.promise=function(n){return n&&"resolved"!==n.state()?(0===e&&u.start(),t++,e++,n.always(function(){e--,0===e?(t=0,u.done()):u.set((t-e)/t)}),this):this}}(),u.render=function(t){if(u.isRendered())return document.getElementById("nprogress");o(document.documentElement,"nprogress-busy");var n=document.createElement("div");n.id="nprogress",n.innerHTML=c.template;var r,i=n.querySelector(c.barSelector),a=t?"-100":e(u.status||0),l=document.querySelector(c.parent);return f(i,{transition:"all 0 linear",transform:"translate3d("+a+"%,0,0)"}),c.showSpinner||(r=n.querySelector(c.spinnerSelector))&&s(r),l!=document.body&&o(l,"nprogress-custom-parent"),l.appendChild(n),n},u.remove=function(){i(document.documentElement,"nprogress-busy"),i(document.querySelector(c.parent),"nprogress-custom-parent");var t=document.getElementById("nprogress");t&&s(t)},u.isRendered=function(){return!!document.getElementById("nprogress")},u.getPositioningCSS=function(){var t=document.body.style,e="WebkitTransform"in t?"Webkit":"MozTransform"in t?"Moz":"msTransform"in t?"ms":"OTransform"in t?"O":"";return e+"Perspective"in t?"translate3d":e+"Transform"in t?"translate":"margin"};var l=function(){function t(){var n=e.shift();n&&n(t)}var e=[];return function(n){e.push(n),1==e.length&&t()}}(),f=function(){function t(t){return t.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(t,e){return e.toUpperCase()})}function e(t){var e=document.body.style;if(t in e)return t;for(var n,r=o.length,i=t.charAt(0).toUpperCase()+t.slice(1);r--;)if((n=o[r]+i)in e)return n;return t}function n(n){return n=t(n),i[n]||(i[n]=e(n))}function r(t,e,r){e=n(e),t.style[e]=r}var o=["Webkit","O","Moz","ms"],i={};return function(t,e){var n,o,i=arguments;if(2==i.length)for(n in e)void 0!==(o=e[n])&&e.hasOwnProperty(n)&&r(t,n,o);else r(t,i[1],i[2])}}();return u})},function(t,e,n){"use strict";(function(t){function n(t){return void 0===t||null===t}function r(t){return void 0!==t&&null!==t}function o(t){return!0===t}function i(t){return!1===t}function a(t){return"string"==typeof t||"number"==typeof t}function s(t){return null!==t&&"object"==typeof t}function u(t){return"[object Object]"===Po.call(t)}function c(t){return"[object RegExp]"===Po.call(t)}function l(t){return null==t?"":"object"==typeof t?JSON.stringify(t,null,2):String(t)}function f(t){var e=parseFloat(t);return isNaN(e)?t:e}function p(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o<r.length;o++)n[r[o]]=!0;return e?function(t){return n[t.toLowerCase()]}:function(t){return n[t]}}function d(t,e){if(t.length){var n=t.indexOf(e);if(n>-1)return t.splice(n,1)}}function h(t,e){return No.call(t,e)}function v(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}function m(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n}function g(t,e){e=e||0;for(var n=t.length-e,r=new Array(n);n--;)r[n]=t[n+e];return r}function y(t,e){for(var n in e)t[n]=e[n];return t}function b(t){for(var e={},n=0;n<t.length;n++)t[n]&&y(e,t[n]);return e}function _(){}function w(t,e){var n=s(t),r=s(e);if(!n||!r)return!n&&!r&&String(t)===String(e);try{return JSON.stringify(t)===JSON.stringify(e)}catch(n){return t===e}}function x(t,e){for(var n=0;n<t.length;n++)if(w(t[n],e))return n;return-1}function k(t){var e=!1;return function(){e||(e=!0,t.apply(this,arguments))}}function $(t){var e=(t+"").charCodeAt(0);return 36===e||95===e}function C(t,e,n,r){Object.defineProperty(t,e,{value:n,enumerable:!!r,writable:!0,configurable:!0})}function O(t){if(!Vo.test(t)){var e=t.split(".");return function(t){for(var n=0;n<e.length;n++){if(!t)return;t=t[e[n]]}return t}}}function S(t,e,n){if(Bo.errorHandler)Bo.errorHandler.call(null,t,e,n);else{if(!Ko||"undefined"==typeof console)throw t;console.error(t)}}function A(t){return"function"==typeof t&&/native code/.test(t.toString())}function j(t){fi.target&&pi.push(fi.target),fi.target=t}function E(){fi.target=pi.pop()}function T(t,e){t.__proto__=e}function P(t,e,n){for(var r=0,o=n.length;r<o;r++){var i=n[r];C(t,i,e[i])}}function L(t,e){if(s(t)){var n;return h(t,"__ob__")&&t.__ob__ instanceof gi?n=t.__ob__:mi.shouldConvert&&!ai()&&(Array.isArray(t)||u(t))&&Object.isExtensible(t)&&!t._isVue&&(n=new gi(t)),e&&n&&n.vmCount++,n}}function N(t,e,n,r){var o=new fi,i=Object.getOwnPropertyDescriptor(t,e);if(!i||!1!==i.configurable){var a=i&&i.get,s=i&&i.set,u=L(n);Object.defineProperty(t,e,{enumerable:!0,configurable:!0,get:function(){var e=a?a.call(t):n;return fi.target&&(o.depend(),u&&u.dep.depend(),Array.isArray(e)&&R(e)),e},set:function(e){var r=a?a.call(t):n;e===r||e!==e&&r!==r||(s?s.call(t,e):n=e,u=L(e),o.notify())}})}}function I(t,e,n){if(Array.isArray(t)&&"number"==typeof e)return t.length=Math.max(t.length,e),t.splice(e,1,n),n;if(h(t,e))return t[e]=n,n;var r=t.__ob__;return t._isVue||r&&r.vmCount?n:r?(N(r.value,e,n),r.dep.notify(),n):(t[e]=n,n)}function M(t,e){if(Array.isArray(t)&&"number"==typeof e)return void t.splice(e,1);var n=t.__ob__;t._isVue||n&&n.vmCount||h(t,e)&&(delete t[e],n&&n.dep.notify())}function R(t){for(var e=void 0,n=0,r=t.length;n<r;n++)e=t[n],e&&e.__ob__&&e.__ob__.dep.depend(),Array.isArray(e)&&R(e)}function D(t,e){if(!e)return t;for(var n,r,o,i=Object.keys(e),a=0;a<i.length;a++)n=i[a],r=t[n],o=e[n],h(t,n)?u(r)&&u(o)&&D(r,o):I(t,n,o);return t}function q(t,e){return e?t?t.concat(e):Array.isArray(e)?e:[e]:t}function F(t,e){var n=Object.create(t||null);return e?y(n,e):n}function U(t){var e=t.props;if(e){var n,r,o,i={};if(Array.isArray(e))for(n=e.length;n--;)"string"==typeof(r=e[n])&&(o=Io(r),i[o]={type:null});else if(u(e))for(var a in e)r=e[a],o=Io(a),i[o]=u(r)?r:{type:r};t.props=i}}function H(t){var e=t.directives;if(e)for(var n in e){var r=e[n];"function"==typeof r&&(e[n]={bind:r,update:r})}}function B(t,e,n){function r(r){var o=yi[r]||bi;u[r]=o(t[r],e[r],n,r)}"function"==typeof e&&(e=e.options),U(e),H(e);var o=e.extends;if(o&&(t=B(t,o,n)),e.mixins)for(var i=0,a=e.mixins.length;i<a;i++)t=B(t,e.mixins[i],n);var s,u={};for(s in t)r(s);for(s in e)h(t,s)||r(s);return u}function z(t,e,n,r){if("string"==typeof n){var o=t[e];if(h(o,n))return o[n];var i=Io(n);if(h(o,i))return o[i];var a=Mo(i);if(h(o,a))return o[a];return o[n]||o[i]||o[a]}}function V(t,e,n,r){var o=e[t],i=!h(n,t),a=n[t];if(K(Boolean,o.type)&&(i&&!h(o,"default")?a=!1:K(String,o.type)||""!==a&&a!==Ro(t)||(a=!0)),void 0===a){a=W(r,o,t);var s=mi.shouldConvert;mi.shouldConvert=!0,L(a),mi.shouldConvert=s}return a}function W(t,e,n){if(h(e,"default")){var r=e.default;return t&&t.$options.propsData&&void 0===t.$options.propsData[n]&&void 0!==t._props[n]?t._props[n]:"function"==typeof r&&"Function"!==G(e.type)?r.call(t):r}}function G(t){var e=t&&t.toString().match(/^\s*function (\w+)/);return e?e[1]:""}function K(t,e){if(!Array.isArray(e))return G(e)===G(t);for(var n=0,r=e.length;n<r;n++)if(G(e[n])===G(t))return!0;return!1}function J(t){return new _i(void 0,void 0,void 0,String(t))}function Z(t){var e=new _i(t.tag,t.data,t.children,t.text,t.elm,t.context,t.componentOptions);return e.ns=t.ns,e.isStatic=t.isStatic,e.key=t.key,e.isComment=t.isComment,e.isCloned=!0,e}function Y(t){for(var e=t.length,n=new Array(e),r=0;r<e;r++)n[r]=Z(t[r]);return n}function X(t){function e(){var t=arguments,n=e.fns;if(!Array.isArray(n))return n.apply(null,arguments);for(var r=0;r<n.length;r++)n[r].apply(null,t)}return e.fns=t,e}function Q(t,e,r,o,i){var a,s,u,c;for(a in t)s=t[a],u=e[a],c=$i(a),n(s)||(n(u)?(n(s.fns)&&(s=t[a]=X(s)),r(c.name,s,c.once,c.capture,c.passive)):s!==u&&(u.fns=s,t[a]=u));for(a in e)n(t[a])&&(c=$i(a),o(c.name,e[a],c.capture))}function tt(t,e,i){function a(){i.apply(this,arguments),d(s.fns,a)}var s,u=t[e];n(u)?s=X([a]):r(u.fns)&&o(u.merged)?(s=u,s.fns.push(a)):s=X([u,a]),s.merged=!0,t[e]=s}function et(t,e,o){var i=e.options.props;if(!n(i)){var a={},s=t.attrs,u=t.props;if(r(s)||r(u))for(var c in i){var l=Ro(c);nt(a,u,c,l,!0)||nt(a,s,c,l,!1)}return a}}function nt(t,e,n,o,i){if(r(e)){if(h(e,n))return t[n]=e[n],i||delete e[n],!0;if(h(e,o))return t[n]=e[o],i||delete e[o],!0}return!1}function rt(t){for(var e=0;e<t.length;e++)if(Array.isArray(t[e]))return Array.prototype.concat.apply([],t);return t}function ot(t){return a(t)?[J(t)]:Array.isArray(t)?at(t):void 0}function it(t){return r(t)&&r(t.text)&&i(t.isComment)}function at(t,e){var i,s,u,c=[];for(i=0;i<t.length;i++)s=t[i],n(s)||"boolean"==typeof s||(u=c[c.length-1],Array.isArray(s)?c.push.apply(c,at(s,(e||"")+"_"+i)):a(s)?it(u)?u.text+=String(s):""!==s&&c.push(J(s)):it(s)&&it(u)?c[c.length-1]=J(u.text+s.text):(o(t._isVList)&&r(s.tag)&&n(s.key)&&r(e)&&(s.key="__vlist"+e+"_"+i+"__"),c.push(s)));return c}function st(t,e){return s(t)?e.extend(t):t}function ut(t,e,i){if(o(t.error)&&r(t.errorComp))return t.errorComp;if(r(t.resolved))return t.resolved;if(o(t.loading)&&r(t.loadingComp))return t.loadingComp;if(!r(t.contexts)){var a=t.contexts=[i],u=!0,c=function(){for(var t=0,e=a.length;t<e;t++)a[t].$forceUpdate()},l=k(function(n){t.resolved=st(n,e),u||c()}),f=k(function(e){r(t.errorComp)&&(t.error=!0,c())}),p=t(l,f);return s(p)&&("function"==typeof p.then?n(t.resolved)&&p.then(l,f):r(p.component)&&"function"==typeof p.component.then&&(p.component.then(l,f),r(p.error)&&(t.errorComp=st(p.error,e)),r(p.loading)&&(t.loadingComp=st(p.loading,e),0===p.delay?t.loading=!0:setTimeout(function(){n(t.resolved)&&n(t.error)&&(t.loading=!0,c())},p.delay||200)),r(p.timeout)&&setTimeout(function(){n(t.resolved)&&f(null)},p.timeout))),u=!1,t.loading?t.loadingComp:t.resolved}t.contexts.push(i)}function ct(t){if(Array.isArray(t))for(var e=0;e<t.length;e++){var n=t[e];if(r(n)&&r(n.componentOptions))return n}}function lt(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t.$options._parentListeners;e&&dt(t,e)}function ft(t,e,n){n?xi.$once(t,e):xi.$on(t,e)}function pt(t,e){xi.$off(t,e)}function dt(t,e,n){xi=t,Q(e,n||{},ft,pt,t)}function ht(t,e){var n={};if(!t)return n;for(var r=[],o=0,i=t.length;o<i;o++){var a=t[o];if(a.context!==e&&a.functionalContext!==e||!a.data||null==a.data.slot)r.push(a);else{var s=a.data.slot,u=n[s]||(n[s]=[]);"template"===a.tag?u.push.apply(u,a.children):u.push(a)}}return r.every(vt)||(n.default=r),n}function vt(t){return t.isComment||" "===t.text}function mt(t,e){e=e||{};for(var n=0;n<t.length;n++)Array.isArray(t[n])?mt(t[n],e):e[t[n].key]=t[n].fn;return e}function gt(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(t)}t.$parent=n,t.$root=n?n.$root:t,t.$children=[],t.$refs={},t._watcher=null,t._inactive=null,t._directInactive=!1,t._isMounted=!1,t._isDestroyed=!1,t._isBeingDestroyed=!1}function yt(t,e,n){t.$el=e,t.$options.render||(t.$options.render=ki),kt(t,"beforeMount");var r;return r=function(){t._update(t._render(),n)},t._watcher=new Li(t,r,_),n=!1,null==t.$vnode&&(t._isMounted=!0,kt(t,"mounted")),t}function bt(t,e,n,r,o){var i=!!(o||t.$options._renderChildren||r.data.scopedSlots||t.$scopedSlots!==zo);if(t.$options._parentVnode=r,t.$vnode=r,t._vnode&&(t._vnode.parent=r),t.$options._renderChildren=o,e&&t.$options.props){mi.shouldConvert=!1;for(var a=t._props,s=t.$options._propKeys||[],u=0;u<s.length;u++){var c=s[u];a[c]=V(c,t.$options.props,e,t)}mi.shouldConvert=!0,t.$options.propsData=e}if(n){var l=t.$options._parentListeners;t.$options._parentListeners=n,dt(t,n,l)}i&&(t.$slots=ht(o,r.context),t.$forceUpdate())}function _t(t){for(;t&&(t=t.$parent);)if(t._inactive)return!0;return!1}function wt(t,e){if(e){if(t._directInactive=!1,_t(t))return}else if(t._directInactive)return;if(t._inactive||null===t._inactive){t._inactive=!1;for(var n=0;n<t.$children.length;n++)wt(t.$children[n]);kt(t,"activated")}}function xt(t,e){if(!(e&&(t._directInactive=!0,_t(t))||t._inactive)){t._inactive=!0;for(var n=0;n<t.$children.length;n++)xt(t.$children[n]);kt(t,"deactivated")}}function kt(t,e){var n=t.$options[e];if(n)for(var r=0,o=n.length;r<o;r++)try{n[r].call(t)}catch(n){S(n,t,e+" hook")}t._hasHookEvent&&t.$emit("hook:"+e)}function $t(){Ti=Oi.length=Si.length=0,Ai={},ji=Ei=!1}function Ct(){Ei=!0;var t,e;for(Oi.sort(function(t,e){return t.id-e.id}),Ti=0;Ti<Oi.length;Ti++)t=Oi[Ti],e=t.id,Ai[e]=null,t.run();var n=Si.slice(),r=Oi.slice();$t(),At(n),Ot(r),si&&Bo.devtools&&si.emit("flush")}function Ot(t){for(var e=t.length;e--;){var n=t[e],r=n.vm;r._watcher===n&&r._isMounted&&kt(r,"updated")}}function St(t){t._inactive=!1,Si.push(t)}function At(t){for(var e=0;e<t.length;e++)t[e]._inactive=!0,wt(t[e],!0)}function jt(t){var e=t.id;if(null==Ai[e]){if(Ai[e]=!0,Ei){for(var n=Oi.length-1;n>Ti&&Oi[n].id>t.id;)n--;Oi.splice(n+1,0,t)}else Oi.push(t);ji||(ji=!0,ci(Ct))}}function Et(t){Ni.clear(),Tt(t,Ni)}function Tt(t,e){var n,r,o=Array.isArray(t);if((o||s(t))&&Object.isExtensible(t)){if(t.__ob__){var i=t.__ob__.dep.id;if(e.has(i))return;e.add(i)}if(o)for(n=t.length;n--;)Tt(t[n],e);else for(r=Object.keys(t),n=r.length;n--;)Tt(t[r[n]],e)}}function Pt(t,e,n){Ii.get=function(){return this[e][n]},Ii.set=function(t){this[e][n]=t},Object.defineProperty(t,n,Ii)}function Lt(t){t._watchers=[];var e=t.$options;e.props&&Nt(t,e.props),e.methods&&Ft(t,e.methods),e.data?It(t):L(t._data={},!0),e.computed&&Rt(t,e.computed),e.watch&&Ut(t,e.watch)}function Nt(t,e){var n=t.$options.propsData||{},r=t._props={},o=t.$options._propKeys=[],i=!t.$parent;mi.shouldConvert=i;for(var a in e)(function(i){o.push(i);var a=V(i,e,n,t);N(r,i,a),i in t||Pt(t,"_props",i)})(a);mi.shouldConvert=!0}function It(t){var e=t.$options.data;e=t._data="function"==typeof e?Mt(e,t):e||{},u(e)||(e={});for(var n=Object.keys(e),r=t.$options.props,o=n.length;o--;)r&&h(r,n[o])||$(n[o])||Pt(t,"_data",n[o]);L(e,!0)}function Mt(t,e){try{return t.call(e)}catch(t){return S(t,e,"data()"),{}}}function Rt(t,e){var n=t._computedWatchers=Object.create(null);for(var r in e){var o=e[r],i="function"==typeof o?o:o.get;n[r]=new Li(t,i,_,Mi),r in t||Dt(t,r,o)}}function Dt(t,e,n){"function"==typeof n?(Ii.get=qt(e),Ii.set=_):(Ii.get=n.get?!1!==n.cache?qt(e):n.get:_,Ii.set=n.set?n.set:_),Object.defineProperty(t,e,Ii)}function qt(t){return function(){var e=this._computedWatchers&&this._computedWatchers[t];if(e)return e.dirty&&e.evaluate(),fi.target&&e.depend(),e.value}}function Ft(t,e){t.$options.props;for(var n in e)t[n]=null==e[n]?_:m(e[n],t)}function Ut(t,e){for(var n in e){var r=e[n];if(Array.isArray(r))for(var o=0;o<r.length;o++)Ht(t,n,r[o]);else Ht(t,n,r)}}function Ht(t,e,n){var r;u(n)&&(r=n,n=n.handler),"string"==typeof n&&(n=t[n]),t.$watch(e,n,r)}function Bt(t){var e=t.$options.provide;e&&(t._provided="function"==typeof e?e.call(t):e)}function zt(t){var e=Vt(t.$options.inject,t);e&&Object.keys(e).forEach(function(n){N(t,n,e[n])})}function Vt(t,e){if(t){for(var n=Array.isArray(t),r=Object.create(null),o=n?t:ui?Reflect.ownKeys(t):Object.keys(t),i=0;i<o.length;i++)for(var a=o[i],s=n?a:t[a],u=e;u;){if(u._provided&&s in u._provided){r[a]=u._provided[s];break}u=u.$parent}return r}}function Wt(t,e,n,o,i){var a={},s=t.options.props;if(r(s))for(var u in s)a[u]=V(u,s,e||{});else r(n.attrs)&&Gt(a,n.attrs),r(n.props)&&Gt(a,n.props);var c=Object.create(o),l=function(t,e,n,r){return Qt(c,t,e,n,r,!0)},f=t.options.render.call(null,l,{data:n,props:a,children:i,parent:o,listeners:n.on||{},injections:Vt(t.options.inject,o),slots:function(){return ht(i,o)}});return f instanceof _i&&(f.functionalContext=o,f.functionalOptions=t.options,n.slot&&((f.data||(f.data={})).slot=n.slot)),f}function Gt(t,e){for(var n in e)t[Io(n)]=e[n]}function Kt(t,e,i,a,u){if(!n(t)){var c=i.$options._base;if(s(t)&&(t=c.extend(t)),"function"==typeof t&&(!n(t.cid)||void 0!==(t=ut(t,c,i)))){de(t),e=e||{},r(e.model)&&Xt(t.options,e);var l=et(e,t,u);if(o(t.options.functional))return Wt(t,l,e,i,a);var f=e.on;e.on=e.nativeOn,o(t.options.abstract)&&(e={}),Zt(e);var p=t.options.name||u;return new _i("vue-component-"+t.cid+(p?"-"+p:""),e,void 0,void 0,void 0,i,{Ctor:t,propsData:l,listeners:f,tag:u,children:a})}}}function Jt(t,e,n,o){var i=t.componentOptions,a={_isComponent:!0,parent:e,propsData:i.propsData,_componentTag:i.tag,_parentVnode:t,_parentListeners:i.listeners,_renderChildren:i.children,_parentElm:n||null,_refElm:o||null},s=t.data.inlineTemplate;return r(s)&&(a.render=s.render,a.staticRenderFns=s.staticRenderFns),new i.Ctor(a)}function Zt(t){t.hook||(t.hook={});for(var e=0;e<Di.length;e++){var n=Di[e],r=t.hook[n],o=Ri[n];t.hook[n]=r?Yt(o,r):o}}function Yt(t,e){return function(n,r,o,i){t(n,r,o,i),e(n,r,o,i)}}function Xt(t,e){var n=t.model&&t.model.prop||"value",o=t.model&&t.model.event||"input";(e.props||(e.props={}))[n]=e.model.value;var i=e.on||(e.on={});r(i[o])?i[o]=[e.model.callback].concat(i[o]):i[o]=e.model.callback}function Qt(t,e,n,r,i,s){return(Array.isArray(n)||a(n))&&(i=r,r=n,n=void 0),o(s)&&(i=Fi),te(t,e,n,r,i)}function te(t,e,n,o,i){if(r(n)&&r(n.__ob__))return ki();if(!e)return ki();Array.isArray(o)&&"function"==typeof o[0]&&(n=n||{},n.scopedSlots={default:o[0]},o.length=0),i===Fi?o=ot(o):i===qi&&(o=rt(o));var a,s;if("string"==typeof e){var u;s=Bo.getTagNamespace(e),a=Bo.isReservedTag(e)?new _i(Bo.parsePlatformTagName(e),n,o,void 0,void 0,t):r(u=z(t.$options,"components",e))?Kt(u,n,t,o,e):new _i(e,n,o,void 0,void 0,t)}else a=Kt(e,n,t,o);return r(a)?(s&&ee(a,s),a):ki()}function ee(t,e){if(t.ns=e,"foreignObject"!==t.tag&&r(t.children))for(var o=0,i=t.children.length;o<i;o++){var a=t.children[o];r(a.tag)&&n(a.ns)&&ee(a,e)}}function ne(t,e){var n,o,i,a,u;if(Array.isArray(t)||"string"==typeof t)for(n=new Array(t.length),o=0,i=t.length;o<i;o++)n[o]=e(t[o],o);else if("number"==typeof t)for(n=new Array(t),o=0;o<t;o++)n[o]=e(o+1,o);else if(s(t))for(a=Object.keys(t),n=new Array(a.length),o=0,i=a.length;o<i;o++)u=a[o],n[o]=e(t[u],u,o);return r(n)&&(n._isVList=!0),n}function re(t,e,n,r){var o=this.$scopedSlots[t];if(o)return n=n||{},r&&y(n,r),o(n)||e;var i=this.$slots[t];return i||e}function oe(t){return z(this.$options,"filters",t,!0)||qo}function ie(t,e,n){var r=Bo.keyCodes[e]||n;return Array.isArray(r)?-1===r.indexOf(t):r!==t}function ae(t,e,n,r){if(n)if(s(n)){Array.isArray(n)&&(n=b(n));var o;for(var i in n){if("class"===i||"style"===i)o=t;else{var a=t.attrs&&t.attrs.type;o=r||Bo.mustUseProp(e,a,i)?t.domProps||(t.domProps={}):t.attrs||(t.attrs={})}i in o||(o[i]=n[i])}}else;return t}function se(t,e){var n=this._staticTrees[t];return n&&!e?Array.isArray(n)?Y(n):Z(n):(n=this._staticTrees[t]=this.$options.staticRenderFns[t].call(this._renderProxy),ce(n,"__static__"+t,!1),n)}function ue(t,e,n){return ce(t,"__once__"+e+(n?"_"+n:""),!0),t}function ce(t,e,n){if(Array.isArray(t))for(var r=0;r<t.length;r++)t[r]&&"string"!=typeof t[r]&&le(t[r],e+"_"+r,n);else le(t,e,n)}function le(t,e,n){t.isStatic=!0,t.key=e,t.isOnce=n}function fe(t){t._vnode=null,t._staticTrees=null;var e=t.$vnode=t.$options._parentVnode,n=e&&e.context;t.$slots=ht(t.$options._renderChildren,n),t.$scopedSlots=zo,t._c=function(e,n,r,o){return Qt(t,e,n,r,o,!1)},t.$createElement=function(e,n,r,o){return Qt(t,e,n,r,o,!0)}}function pe(t,e){var n=t.$options=Object.create(t.constructor.options);n.parent=e.parent,n.propsData=e.propsData,n._parentVnode=e._parentVnode,n._parentListeners=e._parentListeners,n._renderChildren=e._renderChildren,n._componentTag=e._componentTag,n._parentElm=e._parentElm,n._refElm=e._refElm,e.render&&(n.render=e.render,n.staticRenderFns=e.staticRenderFns)}function de(t){var e=t.options;if(t.super){var n=de(t.super);if(n!==t.superOptions){t.superOptions=n;var r=he(t);r&&y(t.extendOptions,r),e=t.options=B(n,t.extendOptions),e.name&&(e.components[e.name]=t)}}return e}function he(t){var e,n=t.options,r=t.extendOptions,o=t.sealedOptions;for(var i in n)n[i]!==o[i]&&(e||(e={}),e[i]=ve(n[i],r[i],o[i]));return e}function ve(t,e,n){if(Array.isArray(t)){var r=[];n=Array.isArray(n)?n:[n],e=Array.isArray(e)?e:[e];for(var o=0;o<t.length;o++)(e.indexOf(t[o])>=0||n.indexOf(t[o])<0)&&r.push(t[o]);return r}return t}function me(t){this._init(t)}function ge(t){t.use=function(t){if(t.installed)return this;var e=g(arguments,1);return e.unshift(this),"function"==typeof t.install?t.install.apply(t,e):"function"==typeof t&&t.apply(null,e),t.installed=!0,this}}function ye(t){t.mixin=function(t){return this.options=B(this.options,t),this}}function be(t){t.cid=0;var e=1;t.extend=function(t){t=t||{};var n=this,r=n.cid,o=t._Ctor||(t._Ctor={});if(o[r])return o[r];var i=t.name||n.options.name,a=function(t){this._init(t)};return a.prototype=Object.create(n.prototype),a.prototype.constructor=a,a.cid=e++,a.options=B(n.options,t),a.super=n,a.options.props&&_e(a),a.options.computed&&we(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,Uo.forEach(function(t){a[t]=n[t]}),i&&(a.options.components[i]=a),a.superOptions=n.options,a.extendOptions=t,a.sealedOptions=y({},a.options),o[r]=a,a}}function _e(t){var e=t.options.props;for(var n in e)Pt(t.prototype,"_props",n)}function we(t){var e=t.options.computed;for(var n in e)Dt(t.prototype,n,e[n])}function xe(t){Uo.forEach(function(e){t[e]=function(t,n){return n?("component"===e&&u(n)&&(n.name=n.name||t,n=this.options._base.extend(n)),"directive"===e&&"function"==typeof n&&(n={bind:n,update:n}),this.options[e+"s"][t]=n,n):this.options[e+"s"][t]}})}function ke(t){return t&&(t.Ctor.options.name||t.tag)}function $e(t,e){return"string"==typeof t?t.split(",").indexOf(e)>-1:!!c(t)&&t.test(e)}function Ce(t,e,n){for(var r in t){var o=t[r];if(o){var i=ke(o.componentOptions);i&&!n(i)&&(o!==e&&Oe(o),t[r]=null)}}}function Oe(t){t&&t.componentInstance.$destroy()}function Se(t){for(var e=t.data,n=t,o=t;r(o.componentInstance);)o=o.componentInstance._vnode,o.data&&(e=Ae(o.data,e));for(;r(n=n.parent);)n.data&&(e=Ae(e,n.data));return je(e)}function Ae(t,e){return{staticClass:Ee(t.staticClass,e.staticClass),class:r(t.class)?[t.class,e.class]:e.class}}function je(t){var e=t.class,n=t.staticClass;return r(n)||r(e)?Ee(n,Te(e)):""}function Ee(t,e){return t?e?t+" "+e:t:e||""}function Te(t){if(n(t))return"";if("string"==typeof t)return t;var e="";if(Array.isArray(t)){for(var o,i=0,a=t.length;i<a;i++)r(t[i])&&r(o=Te(t[i]))&&""!==o&&(e+=o+" ");return e.slice(0,-1)}if(s(t)){for(var u in t)t[u]&&(e+=u+" ");return e.slice(0,-1)}return e}function Pe(t){return fa(t)?"svg":"math"===t?"math":void 0}function Le(t){if(!Ko)return!0;if(da(t))return!1;if(t=t.toLowerCase(),null!=ha[t])return ha[t];var e=document.createElement(t);return t.indexOf("-")>-1?ha[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:ha[t]=/HTMLUnknownElement/.test(e.toString())}function Ne(t){if("string"==typeof t){var e=document.querySelector(t);return e||document.createElement("div")}return t}function Ie(t,e){var n=document.createElement(t);return"select"!==t?n:(e.data&&e.data.attrs&&void 0!==e.data.attrs.multiple&&n.setAttribute("multiple","multiple"),n)}function Me(t,e){return document.createElementNS(ca[t],e)}function Re(t){return document.createTextNode(t)}function De(t){return document.createComment(t)}function qe(t,e,n){t.insertBefore(e,n)}function Fe(t,e){t.removeChild(e)}function Ue(t,e){t.appendChild(e)}function He(t){return t.parentNode}function Be(t){return t.nextSibling}function ze(t){return t.tagName}function Ve(t,e){t.textContent=e}function We(t,e,n){t.setAttribute(e,n)}function Ge(t,e){var n=t.data.ref;if(n){var r=t.context,o=t.componentInstance||t.elm,i=r.$refs;e?Array.isArray(i[n])?d(i[n],o):i[n]===o&&(i[n]=void 0):t.data.refInFor?Array.isArray(i[n])&&i[n].indexOf(o)<0?i[n].push(o):i[n]=[o]:i[n]=o}}function Ke(t,e){return t.key===e.key&&t.tag===e.tag&&t.isComment===e.isComment&&r(t.data)===r(e.data)&&Je(t,e)}function Je(t,e){if("input"!==t.tag)return!0;var n;return(r(n=t.data)&&r(n=n.attrs)&&n.type)===(r(n=e.data)&&r(n=n.attrs)&&n.type)}function Ze(t,e,n){var o,i,a={};for(o=e;o<=n;++o)i=t[o].key,r(i)&&(a[i]=o);return a}function Ye(t,e){(t.data.directives||e.data.directives)&&Xe(t,e)}function Xe(t,e){var n,r,o,i=t===ga,a=e===ga,s=Qe(t.data.directives,t.context),u=Qe(e.data.directives,e.context),c=[],l=[];for(n in u)r=s[n],o=u[n],r?(o.oldValue=r.value,en(o,"update",e,t),o.def&&o.def.componentUpdated&&l.push(o)):(en(o,"bind",e,t),o.def&&o.def.inserted&&c.push(o));if(c.length){var f=function(){for(var n=0;n<c.length;n++)en(c[n],"inserted",e,t)};i?tt(e.data.hook||(e.data.hook={}),"insert",f):f()}if(l.length&&tt(e.data.hook||(e.data.hook={}),"postpatch",function(){for(var n=0;n<l.length;n++)en(l[n],"componentUpdated",e,t)}),!i)for(n in s)u[n]||en(s[n],"unbind",t,t,a)}function Qe(t,e){var n=Object.create(null);if(!t)return n;var r,o;for(r=0;r<t.length;r++)o=t[r],o.modifiers||(o.modifiers=_a),n[tn(o)]=o,o.def=z(e.$options,"directives",o.name,!0);return n}function tn(t){return t.rawName||t.name+"."+Object.keys(t.modifiers||{}).join(".")}function en(t,e,n,r,o){var i=t.def&&t.def[e];if(i)try{i(n.elm,t,n,r,o)}catch(r){S(r,n.context,"directive "+t.name+" "+e+" hook")}}function nn(t,e){if(!n(t.data.attrs)||!n(e.data.attrs)){var o,i,a=e.elm,s=t.data.attrs||{},u=e.data.attrs||{};r(u.__ob__)&&(u=e.data.attrs=y({},u));for(o in u)i=u[o],s[o]!==i&&rn(a,o,i);Yo&&u.value!==s.value&&rn(a,"value",u.value);for(o in s)n(u[o])&&(aa(o)?a.removeAttributeNS(ia,sa(o)):ra(o)||a.removeAttribute(o))}}function rn(t,e,n){oa(e)?ua(n)?t.removeAttribute(e):t.setAttribute(e,e):ra(e)?t.setAttribute(e,ua(n)||"false"===n?"false":"true"):aa(e)?ua(n)?t.removeAttributeNS(ia,sa(e)):t.setAttributeNS(ia,e,n):ua(n)?t.removeAttribute(e):t.setAttribute(e,n)}function on(t,e){var o=e.elm,i=e.data,a=t.data;if(!(n(i.staticClass)&&n(i.class)&&(n(a)||n(a.staticClass)&&n(a.class)))){var s=Se(e),u=o._transitionClasses;r(u)&&(s=Ee(s,Te(u))),s!==o._prevClass&&(o.setAttribute("class",s),o._prevClass=s)}}function an(t){function e(){(a||(a=[])).push(t.slice(h,o).trim()),h=o+1}var n,r,o,i,a,s=!1,u=!1,c=!1,l=!1,f=0,p=0,d=0,h=0;for(o=0;o<t.length;o++)if(r=n,n=t.charCodeAt(o),s)39===n&&92!==r&&(s=!1);else if(u)34===n&&92!==r&&(u=!1);else if(c)96===n&&92!==r&&(c=!1);else if(l)47===n&&92!==r&&(l=!1);else if(124!==n||124===t.charCodeAt(o+1)||124===t.charCodeAt(o-1)||f||p||d){switch(n){case 34:u=!0;break;case 39:s=!0;break;case 96:c=!0;break;case 40:d++;break;case 41:d--;break;case 91:p++;break;case 93:p--;break;case 123:f++;break;case 125:f--}if(47===n){for(var v=o-1,m=void 0;v>=0&&" "===(m=t.charAt(v));v--);m&&$a.test(m)||(l=!0)}}else void 0===i?(h=o+1,i=t.slice(0,o).trim()):e();if(void 0===i?i=t.slice(0,o).trim():0!==h&&e(),a)for(o=0;o<a.length;o++)i=sn(i,a[o]);return i}function sn(t,e){var n=e.indexOf("(");return n<0?'_f("'+e+'")('+t+")":'_f("'+e.slice(0,n)+'")('+t+","+e.slice(n+1)}function un(t){console.error("[Vue compiler]: "+t)}function cn(t,e){return t?t.map(function(t){return t[e]}).filter(function(t){return t}):[]}function ln(t,e,n){(t.props||(t.props=[])).push({name:e,value:n})}function fn(t,e,n){(t.attrs||(t.attrs=[])).push({name:e,value:n})}function pn(t,e,n,r,o,i){(t.directives||(t.directives=[])).push({name:e,rawName:n,value:r,arg:o,modifiers:i})}function dn(t,e,n,r,o,i){r&&r.capture&&(delete r.capture,e="!"+e),r&&r.once&&(delete r.once,e="~"+e),r&&r.passive&&(delete r.passive,e="&"+e);var a;r&&r.native?(delete r.native,a=t.nativeEvents||(t.nativeEvents={})):a=t.events||(t.events={});var s={value:n,modifiers:r},u=a[e];Array.isArray(u)?o?u.unshift(s):u.push(s):a[e]=u?o?[s,u]:[u,s]:s}function hn(t,e,n){var r=vn(t,":"+e)||vn(t,"v-bind:"+e);if(null!=r)return an(r);if(!1!==n){var o=vn(t,e);if(null!=o)return JSON.stringify(o)}}function vn(t,e){var n;if(null!=(n=t.attrsMap[e]))for(var r=t.attrsList,o=0,i=r.length;o<i;o++)if(r[o].name===e){r.splice(o,1);break}return n}function mn(t,e,n){var r=n||{},o=r.number,i=r.trim,a="$$v";i&&(a="(typeof $$v === 'string'? $$v.trim(): $$v)"),o&&(a="_n("+a+")");var s=gn(e,a);t.model={value:"("+e+")",expression:'"'+e+'"',callback:"function ($$v) {"+s+"}"}}function gn(t,e){var n=yn(t);return null===n.idx?t+"="+e:"var $$exp = "+n.exp+", $$idx = "+n.idx+";if (!Array.isArray($$exp)){"+t+"="+e+"}else{$$exp.splice($$idx, 1, "+e+")}"}function yn(t){if(Wi=t,Vi=Wi.length,Ki=Ji=Zi=0,t.indexOf("[")<0||t.lastIndexOf("]")<Vi-1)return{exp:t,idx:null};for(;!_n();)Gi=bn(),wn(Gi)?kn(Gi):91===Gi&&xn(Gi);return{exp:t.substring(0,Ji),idx:t.substring(Ji+1,Zi)}}function bn(){return Wi.charCodeAt(++Ki)}function _n(){return Ki>=Vi}function wn(t){return 34===t||39===t}function xn(t){var e=1;for(Ji=Ki;!_n();)if(t=bn(),wn(t))kn(t);else if(91===t&&e++,93===t&&e--,0===e){Zi=Ki;break}}function kn(t){for(var e=t;!_n()&&(t=bn())!==e;);}function $n(t,e,n){Yi=n;var r=e.value,o=e.modifiers,i=t.tag,a=t.attrsMap.type;if("select"===i)Sn(t,r,o);else if("input"===i&&"checkbox"===a)Cn(t,r,o);else if("input"===i&&"radio"===a)On(t,r,o);else if("input"===i||"textarea"===i)An(t,r,o);else if(!Bo.isReservedTag(i))return mn(t,r,o),!1;return!0}function Cn(t,e,n){var r=n&&n.number,o=hn(t,"value")||"null",i=hn(t,"true-value")||"true",a=hn(t,"false-value")||"false";ln(t,"checked","Array.isArray("+e+")?_i("+e+","+o+")>-1"+("true"===i?":("+e+")":":_q("+e+","+i+")")),dn(t,Oa,"var $$a="+e+",$$el=$event.target,$$c=$$el.checked?("+i+"):("+a+");if(Array.isArray($$a)){var $$v="+(r?"_n("+o+")":o)+",$$i=_i($$a,$$v);if($$c){$$i<0&&("+e+"=$$a.concat($$v))}else{$$i>-1&&("+e+"=$$a.slice(0,$$i).concat($$a.slice($$i+1)))}}else{"+gn(e,"$$c")+"}",null,!0)}function On(t,e,n){var r=n&&n.number,o=hn(t,"value")||"null";o=r?"_n("+o+")":o,ln(t,"checked","_q("+e+","+o+")"),dn(t,Oa,gn(e,o),null,!0)}function Sn(t,e,n){var r=n&&n.number,o='Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = "_value" in o ? o._value : o.value;return '+(r?"_n(val)":"val")+"})",i="var $$selectedVal = "+o+";";i=i+" "+gn(e,"$event.target.multiple ? $$selectedVal : $$selectedVal[0]"),dn(t,"change",i,null,!0)}function An(t,e,n){var r=t.attrsMap.type,o=n||{},i=o.lazy,a=o.number,s=o.trim,u=!i&&"range"!==r,c=i?"change":"range"===r?Ca:"input",l="$event.target.value";s&&(l="$event.target.value.trim()"),a&&(l="_n("+l+")");var f=gn(e,l);u&&(f="if($event.target.composing)return;"+f),ln(t,"value","("+e+")"),dn(t,c,f,null,!0),(s||a||"number"===r)&&dn(t,"blur","$forceUpdate()")}function jn(t){var e;r(t[Ca])&&(e=Zo?"change":"input",t[e]=[].concat(t[Ca],t[e]||[]),delete t[Ca]),r(t[Oa])&&(e=ei?"click":"change",t[e]=[].concat(t[Oa],t[e]||[]),delete t[Oa])}function En(t,e,n,r,o){if(n){var i=e,a=Xi;e=function(n){null!==(1===arguments.length?i(n):i.apply(null,arguments))&&Tn(t,e,r,a)}}Xi.addEventListener(t,e,ni?{capture:r,passive:o}:r)}function Tn(t,e,n,r){(r||Xi).removeEventListener(t,e,n)}function Pn(t,e){if(!n(t.data.on)||!n(e.data.on)){var r=e.data.on||{},o=t.data.on||{};Xi=e.elm,jn(r),Q(r,o,En,Tn,e.context)}}function Ln(t,e){if(!n(t.data.domProps)||!n(e.data.domProps)){var o,i,a=e.elm,s=t.data.domProps||{},u=e.data.domProps||{};r(u.__ob__)&&(u=e.data.domProps=y({},u));for(o in s)n(u[o])&&(a[o]="");for(o in u)if(i=u[o],"textContent"!==o&&"innerHTML"!==o||(e.children&&(e.children.length=0),i!==s[o]))if("value"===o){a._value=i;var c=n(i)?"":String(i);Nn(a,e,c)&&(a.value=c)}else a[o]=i}}function Nn(t,e,n){return!t.composing&&("option"===e.tag||In(t,n)||Mn(t,n))}function In(t,e){return document.activeElement!==t&&t.value!==e}function Mn(t,e){var n=t.value,o=t._vModifiers;return r(o)&&o.number||"number"===t.type?f(n)!==f(e):r(o)&&o.trim?n.trim()!==e.trim():n!==e}function Rn(t){var e=Dn(t.style);return t.staticStyle?y(t.staticStyle,e):e}function Dn(t){return Array.isArray(t)?b(t):"string"==typeof t?ja(t):t}function qn(t,e){var n,r={};if(e)for(var o=t;o.componentInstance;)o=o.componentInstance._vnode,o.data&&(n=Rn(o.data))&&y(r,n);(n=Rn(t.data))&&y(r,n);for(var i=t;i=i.parent;)i.data&&(n=Rn(i.data))&&y(r,n);return r}function Fn(t,e){var o=e.data,i=t.data;if(!(n(o.staticStyle)&&n(o.style)&&n(i.staticStyle)&&n(i.style))){var a,s,u=e.elm,c=i.staticStyle,l=i.normalizedStyle||i.style||{},f=c||l,p=Dn(e.data.style)||{};e.data.normalizedStyle=r(p.__ob__)?y({},p):p;var d=qn(e,!0);for(s in f)n(d[s])&&Pa(u,s,"");for(s in d)(a=d[s])!==f[s]&&Pa(u,s,null==a?"":a)}}function Un(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(/\s+/).forEach(function(e){return t.classList.add(e)}):t.classList.add(e);else{var n=" "+(t.getAttribute("class")||"")+" ";n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function Hn(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(/\s+/).forEach(function(e){return t.classList.remove(e)}):t.classList.remove(e);else{for(var n=" "+(t.getAttribute("class")||"")+" ",r=" "+e+" ";n.indexOf(r)>=0;)n=n.replace(r," ");t.setAttribute("class",n.trim())}}function Bn(t){if(t){if("object"==typeof t){var e={};return!1!==t.css&&y(e,Ma(t.name||"v")),y(e,t),e}return"string"==typeof t?Ma(t):void 0}}function zn(t){za(function(){za(t)})}function Vn(t,e){(t._transitionClasses||(t._transitionClasses=[])).push(e),Un(t,e)}function Wn(t,e){t._transitionClasses&&d(t._transitionClasses,e),Hn(t,e)}function Gn(t,e,n){var r=Kn(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!o)return n();var s=o===Da?Ua:Ba,u=0,c=function(){t.removeEventListener(s,l),n()},l=function(e){e.target===t&&++u>=a&&c()};setTimeout(function(){u<a&&c()},i+1),t.addEventListener(s,l)}function Kn(t,e){var n,r=window.getComputedStyle(t),o=r[Fa+"Delay"].split(", "),i=r[Fa+"Duration"].split(", "),a=Jn(o,i),s=r[Ha+"Delay"].split(", "),u=r[Ha+"Duration"].split(", "),c=Jn(s,u),l=0,f=0;return e===Da?a>0&&(n=Da,l=a,f=i.length):e===qa?c>0&&(n=qa,l=c,f=u.length):(l=Math.max(a,c),n=l>0?a>c?Da:qa:null,f=n?n===Da?i.length:u.length:0),{type:n,timeout:l,propCount:f,hasTransform:n===Da&&Va.test(r[Fa+"Property"])}}function Jn(t,e){for(;t.length<e.length;)t=t.concat(t);return Math.max.apply(null,e.map(function(e,n){return Zn(e)+Zn(t[n])}))}function Zn(t){return 1e3*Number(t.slice(0,-1))}function Yn(t,e){var o=t.elm;r(o._leaveCb)&&(o._leaveCb.cancelled=!0,o._leaveCb());var i=Bn(t.data.transition);if(!n(i)&&!r(o._enterCb)&&1===o.nodeType){for(var a=i.css,u=i.type,c=i.enterClass,l=i.enterToClass,p=i.enterActiveClass,d=i.appearClass,h=i.appearToClass,v=i.appearActiveClass,m=i.beforeEnter,g=i.enter,y=i.afterEnter,b=i.enterCancelled,_=i.beforeAppear,w=i.appear,x=i.afterAppear,$=i.appearCancelled,C=i.duration,O=Ci,S=Ci.$vnode;S&&S.parent;)S=S.parent,O=S.context;var A=!O._isMounted||!t.isRootInsert;if(!A||w||""===w){var j=A&&d?d:c,E=A&&v?v:p,T=A&&h?h:l,P=A?_||m:m,L=A&&"function"==typeof w?w:g,N=A?x||y:y,I=A?$||b:b,M=f(s(C)?C.enter:C),R=!1!==a&&!Yo,D=tr(L),q=o._enterCb=k(function(){R&&(Wn(o,T),Wn(o,E)),q.cancelled?(R&&Wn(o,j),I&&I(o)):N&&N(o),o._enterCb=null});t.data.show||tt(t.data.hook||(t.data.hook={}),"insert",function(){var e=o.parentNode,n=e&&e._pending&&e._pending[t.key];n&&n.tag===t.tag&&n.elm._leaveCb&&n.elm._leaveCb(),L&&L(o,q)}),P&&P(o),R&&(Vn(o,j),Vn(o,E),zn(function(){Vn(o,T),Wn(o,j),q.cancelled||D||(Qn(M)?setTimeout(q,M):Gn(o,u,q))})),t.data.show&&(e&&e(),L&&L(o,q)),R||D||q()}}}function Xn(t,e){function o(){$.cancelled||(t.data.show||((i.parentNode._pending||(i.parentNode._pending={}))[t.key]=t),h&&h(i),_&&(Vn(i,l),Vn(i,d),zn(function(){Vn(i,p),Wn(i,l),$.cancelled||w||(Qn(x)?setTimeout($,x):Gn(i,c,$))})),v&&v(i,$),_||w||$())}var i=t.elm;r(i._enterCb)&&(i._enterCb.cancelled=!0,i._enterCb());var a=Bn(t.data.transition);if(n(a))return e();if(!r(i._leaveCb)&&1===i.nodeType){var u=a.css,c=a.type,l=a.leaveClass,p=a.leaveToClass,d=a.leaveActiveClass,h=a.beforeLeave,v=a.leave,m=a.afterLeave,g=a.leaveCancelled,y=a.delayLeave,b=a.duration,_=!1!==u&&!Yo,w=tr(v),x=f(s(b)?b.leave:b),$=i._leaveCb=k(function(){i.parentNode&&i.parentNode._pending&&(i.parentNode._pending[t.key]=null),_&&(Wn(i,p),Wn(i,d)),$.cancelled?(_&&Wn(i,l),g&&g(i)):(e(),m&&m(i)),i._leaveCb=null});y?y(o):o()}}function Qn(t){return"number"==typeof t&&!isNaN(t)}function tr(t){if(n(t))return!1;var e=t.fns;return r(e)?tr(Array.isArray(e)?e[0]:e):(t._length||t.length)>1}function er(t,e){!0!==e.data.show&&Yn(e)}function nr(t,e,n){var r=e.value,o=t.multiple;if(!o||Array.isArray(r)){for(var i,a,s=0,u=t.options.length;s<u;s++)if(a=t.options[s],o)i=x(r,or(a))>-1,a.selected!==i&&(a.selected=i);else if(w(or(a),r))return void(t.selectedIndex!==s&&(t.selectedIndex=s));o||(t.selectedIndex=-1)}}function rr(t,e){for(var n=0,r=e.length;n<r;n++)if(w(or(e[n]),t))return!1;return!0}function or(t){return"_value"in t?t._value:t.value}function ir(t){t.target.composing=!0}function ar(t){t.target.composing&&(t.target.composing=!1,sr(t.target,"input"))}function sr(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0),t.dispatchEvent(n)}function ur(t){return!t.componentInstance||t.data&&t.data.transition?t:ur(t.componentInstance._vnode)}function cr(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?cr(ct(e.children)):t}function lr(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];var o=n._parentListeners;for(var i in o)e[Io(i)]=o[i];return e}function fr(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}function pr(t){for(;t=t.parent;)if(t.data.transition)return!0}function dr(t,e){return e.key===t.key&&e.tag===t.tag}function hr(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._enterCb()}function vr(t){t.data.newPos=t.elm.getBoundingClientRect()}function mr(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,o=e.top-n.top;if(r||o){t.data.moved=!0;var i=t.elm.style;i.transform=i.WebkitTransform="translate("+r+"px,"+o+"px)",i.transitionDuration="0s"}}function gr(t){return os=os||document.createElement("div"),os.innerHTML=t,os.textContent}function yr(t,e){var n=e?Us:Fs;return t.replace(n,function(t){return qs[t]})}function br(t,e){function n(e){l+=e,t=t.substring(e)}function r(t,n,r){var o,s;if(null==n&&(n=l),null==r&&(r=l),t&&(s=t.toLowerCase()),t)for(o=a.length-1;o>=0&&a[o].lowerCasedTag!==s;o--);else o=0;if(o>=0){for(var u=a.length-1;u>=o;u--)e.end&&e.end(a[u].tag,n,r);a.length=o,i=o&&a[o-1].tag}else"br"===s?e.start&&e.start(t,[],!0,n,r):"p"===s&&(e.start&&e.start(t,[],!1,n,r),e.end&&e.end(t,n,r))}for(var o,i,a=[],s=e.expectHTML,u=e.isUnaryTag||Do,c=e.canBeLeftOpenTag||Do,l=0;t;){if(o=t,i&&Rs(i)){var f=i.toLowerCase(),p=Ds[f]||(Ds[f]=new RegExp("([\\s\\S]*?)(</"+f+"[^>]*>)","i")),d=0,h=t.replace(p,function(t,n,r){return d=r.length,Rs(f)||"noscript"===f||(n=n.replace(/<!--([\s\S]*?)-->/g,"$1").replace(/<!\[CDATA\[([\s\S]*?)]]>/g,"$1")),e.chars&&e.chars(n),""});l+=t.length-h.length,t=h,r(f,l-d,l)}else{var v=t.indexOf("<");if(0===v){if(ms.test(t)){var m=t.indexOf("--\x3e");if(m>=0){n(m+3);continue}}if(gs.test(t)){var g=t.indexOf("]>");if(g>=0){n(g+2);continue}}var y=t.match(vs);if(y){n(y[0].length);continue}var b=t.match(hs);if(b){var _=l;n(b[0].length),r(b[1],_,l);continue}var w=function(){var e=t.match(ps);if(e){var r={tagName:e[1],attrs:[],start:l};n(e[0].length);for(var o,i;!(o=t.match(ds))&&(i=t.match(ls));)n(i[0].length),r.attrs.push(i);if(o)return r.unarySlash=o[1],n(o[0].length),r.end=l,r}}();if(w){(function(t){var n=t.tagName,o=t.unarySlash;s&&("p"===i&&us(n)&&r(i),c(n)&&i===n&&r(n));for(var l=u(n)||"html"===n&&"head"===i||!!o,f=t.attrs.length,p=new Array(f),d=0;d<f;d++){var h=t.attrs[d];ys&&-1===h[0].indexOf('""')&&(""===h[3]&&delete h[3],""===h[4]&&delete h[4],""===h[5]&&delete h[5]);var v=h[3]||h[4]||h[5]||"";p[d]={name:h[1],value:yr(v,e.shouldDecodeNewlines)}}l||(a.push({tag:n,lowerCasedTag:n.toLowerCase(),attrs:p}),i=n),e.start&&e.start(n,p,l,t.start,t.end)})(w);continue}}var x=void 0,k=void 0,$=void 0;if(v>=0){for(k=t.slice(v);!(hs.test(k)||ps.test(k)||ms.test(k)||gs.test(k)||($=k.indexOf("<",1))<0);)v+=$,k=t.slice(v);x=t.substring(0,v),n(v)}v<0&&(x=t,t=""),e.chars&&x&&e.chars(x)}if(t===o){e.chars&&e.chars(t);break}}r()}function _r(t,e){var n=e?Bs(e):Hs;if(n.test(t)){for(var r,o,i=[],a=n.lastIndex=0;r=n.exec(t);){o=r.index,o>a&&i.push(JSON.stringify(t.slice(a,o)));var s=an(r[1].trim());i.push("_s("+s+")"),a=o+r[0].length}return a<t.length&&i.push(JSON.stringify(t.slice(a))),i.join("+")}}function wr(t,e){function n(t){t.pre&&(s=!1),$s(t.tag)&&(u=!1)}bs=e.warn||un,Os=e.getTagNamespace||Do,Cs=e.mustUseProp||Do,$s=e.isPreTag||Do,xs=cn(e.modules,"preTransformNode"),ws=cn(e.modules,"transformNode"),ks=cn(e.modules,"postTransformNode"),_s=e.delimiters;var r,o,i=[],a=!1!==e.preserveWhitespace,s=!1,u=!1;return br(t,{warn:bs,expectHTML:e.expectHTML,isUnaryTag:e.isUnaryTag,canBeLeftOpenTag:e.canBeLeftOpenTag,shouldDecodeNewlines:e.shouldDecodeNewlines,start:function(t,a,c){var l=o&&o.ns||Os(t);Zo&&"svg"===l&&(a=Fr(a));var f={type:1,tag:t,attrsList:a,attrsMap:Rr(a),parent:o,children:[]};l&&(f.ns=l),qr(f)&&!ai()&&(f.forbidden=!0);for(var p=0;p<xs.length;p++)xs[p](f,e);if(s||(xr(f),f.pre&&(s=!0)),$s(f.tag)&&(u=!0),s)kr(f);else{Or(f),Sr(f),Tr(f),$r(f),f.plain=!f.key&&!a.length,Cr(f),Pr(f),Lr(f);for(var d=0;d<ws.length;d++)ws[d](f,e);Nr(f)}if(r?i.length||r.if&&(f.elseif||f.else)&&Er(r,{exp:f.elseif,block:f}):r=f,o&&!f.forbidden)if(f.elseif||f.else)Ar(f,o);else if(f.slotScope){o.plain=!1;var h=f.slotTarget||'"default"';(o.scopedSlots||(o.scopedSlots={}))[h]=f}else o.children.push(f),f.parent=o;c?n(f):(o=f,i.push(f));for(var v=0;v<ks.length;v++)ks[v](f,e)},end:function(){var t=i[i.length-1],e=t.children[t.children.length-1];e&&3===e.type&&" "===e.text&&!u&&t.children.pop(),i.length-=1,o=i[i.length-1],n(t)},chars:function(t){if(o&&(!Zo||"textarea"!==o.tag||o.attrsMap.placeholder!==t)){var e=o.children;if(t=u||t.trim()?Dr(o)?t:Ys(t):a&&e.length?" ":""){var n;!s&&" "!==t&&(n=_r(t,_s))?e.push({type:2,expression:n,text:t}):" "===t&&e.length&&" "===e[e.length-1].text||e.push({type:3,text:t})}}}}),r}function xr(t){null!=vn(t,"v-pre")&&(t.pre=!0)}function kr(t){var e=t.attrsList.length;if(e)for(var n=t.attrs=new Array(e),r=0;r<e;r++)n[r]={name:t.attrsList[r].name,value:JSON.stringify(t.attrsList[r].value)};else t.pre||(t.plain=!0)}function $r(t){var e=hn(t,"key");e&&(t.key=e)}function Cr(t){var e=hn(t,"ref");e&&(t.ref=e,t.refInFor=Ir(t))}function Or(t){var e;if(e=vn(t,"v-for")){var n=e.match(Ws);if(!n)return;t.for=n[2].trim();var r=n[1].trim(),o=r.match(Gs);o?(t.alias=o[1].trim(),t.iterator1=o[2].trim(),o[3]&&(t.iterator2=o[3].trim())):t.alias=r}}function Sr(t){var e=vn(t,"v-if");if(e)t.if=e,Er(t,{exp:e,block:t});else{null!=vn(t,"v-else")&&(t.else=!0);var n=vn(t,"v-else-if");n&&(t.elseif=n)}}function Ar(t,e){var n=jr(e.children);n&&n.if&&Er(n,{exp:t.elseif,block:t})}function jr(t){for(var e=t.length;e--;){if(1===t[e].type)return t[e];t.pop()}}function Er(t,e){t.ifConditions||(t.ifConditions=[]),t.ifConditions.push(e)}function Tr(t){null!=vn(t,"v-once")&&(t.once=!0)}function Pr(t){if("slot"===t.tag)t.slotName=hn(t,"name");else{var e=hn(t,"slot");e&&(t.slotTarget='""'===e?'"default"':e),"template"===t.tag&&(t.slotScope=vn(t,"scope"))}}function Lr(t){var e;(e=hn(t,"is"))&&(t.component=e),null!=vn(t,"inline-template")&&(t.inlineTemplate=!0)}function Nr(t){var e,n,r,o,i,a,s,u=t.attrsList;for(e=0,n=u.length;e<n;e++)if(r=o=u[e].name,i=u[e].value,Vs.test(r))if(t.hasBindings=!0,a=Mr(r),a&&(r=r.replace(Zs,"")),Js.test(r))r=r.replace(Js,""),i=an(i),s=!1,a&&(a.prop&&(s=!0,"innerHtml"===(r=Io(r))&&(r="innerHTML")),a.camel&&(r=Io(r)),a.sync&&dn(t,"update:"+Io(r),gn(i,"$event"))),s||Cs(t.tag,t.attrsMap.type,r)?ln(t,r,i):fn(t,r,i);else if(zs.test(r))r=r.replace(zs,""),dn(t,r,i,a,!1,bs);else{r=r.replace(Vs,"");var c=r.match(Ks),l=c&&c[1];l&&(r=r.slice(0,-(l.length+1))),pn(t,r,o,i,l,a)}else{fn(t,r,JSON.stringify(i))}}function Ir(t){for(var e=t;e;){if(void 0!==e.for)return!0;e=e.parent}return!1}function Mr(t){var e=t.match(Zs);if(e){var n={};return e.forEach(function(t){n[t.slice(1)]=!0}),n}}function Rr(t){for(var e={},n=0,r=t.length;n<r;n++)e[t[n].name]=t[n].value;return e}function Dr(t){return"script"===t.tag||"style"===t.tag}function qr(t){return"style"===t.tag||"script"===t.tag&&(!t.attrsMap.type||"text/javascript"===t.attrsMap.type)}function Fr(t){for(var e=[],n=0;n<t.length;n++){var r=t[n];Xs.test(r.name)||(r.name=r.name.replace(Qs,""),e.push(r))}return e}function Ur(t,e){t&&(Ss=tu(e.staticKeys||""),As=e.isReservedTag||Do,Br(t),zr(t,!1))}function Hr(t){return p("type,tag,attrsList,attrsMap,plain,parent,children,attrs"+(t?","+t:""))}function Br(t){if(t.static=Wr(t),1===t.type){if(!As(t.tag)&&"slot"!==t.tag&&null==t.attrsMap["inline-template"])return;for(var e=0,n=t.children.length;e<n;e++){var r=t.children[e];Br(r),r.static||(t.static=!1)}}}function zr(t,e){if(1===t.type){if((t.static||t.once)&&(t.staticInFor=e),t.static&&t.children.length&&(1!==t.children.length||3!==t.children[0].type))return void(t.staticRoot=!0);if(t.staticRoot=!1,t.children)for(var n=0,r=t.children.length;n<r;n++)zr(t.children[n],e||!!t.for);t.ifConditions&&Vr(t.ifConditions,e)}}function Vr(t,e){for(var n=1,r=t.length;n<r;n++)zr(t[n].block,e)}function Wr(t){return 2!==t.type&&(3===t.type||!(!t.pre&&(t.hasBindings||t.if||t.for||Lo(t.tag)||!As(t.tag)||Gr(t)||!Object.keys(t).every(Ss))))}function Gr(t){for(;t.parent;){if(t=t.parent,"template"!==t.tag)return!1;if(t.for)return!0}return!1}function Kr(t,e,n){var r=e?"nativeOn:{":"on:{";for(var o in t){r+='"'+o+'":'+Jr(o,t[o])+","}return r.slice(0,-1)+"}"}function Jr(t,e){if(!e)return"function(){}";if(Array.isArray(e))return"["+e.map(function(e){return Jr(t,e)}).join(",")+"]";var n=nu.test(e.value),r=eu.test(e.value);if(e.modifiers){var o="",i="",a=[];for(var s in e.modifiers)iu[s]?(i+=iu[s],ru[s]&&a.push(s)):a.push(s);a.length&&(o+=Zr(a)),i&&(o+=i);return"function($event){"+o+(n?e.value+"($event)":r?"("+e.value+")($event)":e.value)+"}"}return n||r?e.value:"function($event){"+e.value+"}"}function Zr(t){return"if(!('button' in $event)&&"+t.map(Yr).join("&&")+")return null;"}function Yr(t){var e=parseInt(t,10);if(e)return"$event.keyCode!=="+e;var n=ru[t];return"_k($event.keyCode,"+JSON.stringify(t)+(n?","+JSON.stringify(n):"")+")"}function Xr(t,e){t.wrapData=function(n){return"_b("+n+",'"+t.tag+"',"+e.value+(e.modifiers&&e.modifiers.prop?",true":"")+")"}}function Qr(t,e){var n=Ns,r=Ns=[],o=Is;Is=0,Ms=e,js=e.warn||un,Es=cn(e.modules,"transformCode"),Ts=cn(e.modules,"genData"),Ps=e.directives||{},Ls=e.isReservedTag||Do;var i=t?to(t):'_c("div")';return Ns=n,Is=o,{render:"with(this){return "+i+"}",staticRenderFns:r}}function to(t){if(t.staticRoot&&!t.staticProcessed)return eo(t);if(t.once&&!t.onceProcessed)return no(t);if(t.for&&!t.forProcessed)return io(t);if(t.if&&!t.ifProcessed)return ro(t);if("template"!==t.tag||t.slotTarget){if("slot"===t.tag)return bo(t);var e;if(t.component)e=_o(t.component,t);else{var n=t.plain?void 0:ao(t),r=t.inlineTemplate?null:po(t,!0);e="_c('"+t.tag+"'"+(n?","+n:"")+(r?","+r:"")+")"}for(var o=0;o<Es.length;o++)e=Es[o](t,e);return e}return po(t)||"void 0"}function eo(t){return t.staticProcessed=!0,Ns.push("with(this){return "+to(t)+"}"),"_m("+(Ns.length-1)+(t.staticInFor?",true":"")+")"}function no(t){if(t.onceProcessed=!0,t.if&&!t.ifProcessed)return ro(t);if(t.staticInFor){for(var e="",n=t.parent;n;){if(n.for){e=n.key;break}n=n.parent}return e?"_o("+to(t)+","+Is+++(e?","+e:"")+")":to(t)}return eo(t)}function ro(t){return t.ifProcessed=!0,oo(t.ifConditions.slice())}function oo(t){function e(t){return t.once?no(t):to(t)}if(!t.length)return"_e()";var n=t.shift();return n.exp?"("+n.exp+")?"+e(n.block)+":"+oo(t):""+e(n.block)}function io(t){var e=t.for,n=t.alias,r=t.iterator1?","+t.iterator1:"",o=t.iterator2?","+t.iterator2:"";return t.forProcessed=!0,"_l(("+e+"),function("+n+r+o+"){return "+to(t)+"})"}function ao(t){var e="{",n=so(t);n&&(e+=n+","),t.key&&(e+="key:"+t.key+","),t.ref&&(e+="ref:"+t.ref+","),t.refInFor&&(e+="refInFor:true,"),t.pre&&(e+="pre:true,"),t.component&&(e+='tag:"'+t.tag+'",');for(var r=0;r<Ts.length;r++)e+=Ts[r](t);if(t.attrs&&(e+="attrs:{"+wo(t.attrs)+"},"),t.props&&(e+="domProps:{"+wo(t.props)+"},"),t.events&&(e+=Kr(t.events,!1,js)+","),t.nativeEvents&&(e+=Kr(t.nativeEvents,!0,js)+","),t.slotTarget&&(e+="slot:"+t.slotTarget+","),t.scopedSlots&&(e+=co(t.scopedSlots)+","),t.model&&(e+="model:{value:"+t.model.value+",callback:"+t.model.callback+",expression:"+t.model.expression+"},"),t.inlineTemplate){var o=uo(t);o&&(e+=o+",")}return e=e.replace(/,$/,"")+"}",t.wrapData&&(e=t.wrapData(e)),e}function so(t){var e=t.directives;if(e){var n,r,o,i,a="directives:[",s=!1;for(n=0,r=e.length;n<r;n++){o=e[n],i=!0;var u=Ps[o.name]||au[o.name];u&&(i=!!u(t,o,js)),i&&(s=!0,a+='{name:"'+o.name+'",rawName:"'+o.rawName+'"'+(o.value?",value:("+o.value+"),expression:"+JSON.stringify(o.value):"")+(o.arg?',arg:"'+o.arg+'"':"")+(o.modifiers?",modifiers:"+JSON.stringify(o.modifiers):"")+"},")}return s?a.slice(0,-1)+"]":void 0}}function uo(t){var e=t.children[0];if(1===e.type){var n=Qr(e,Ms);return"inlineTemplate:{render:function(){"+n.render+"},staticRenderFns:["+n.staticRenderFns.map(function(t){return"function(){"+t+"}"}).join(",")+"]}"}}function co(t){return"scopedSlots:_u(["+Object.keys(t).map(function(e){return lo(e,t[e])}).join(",")+"])"}function lo(t,e){return e.for&&!e.forProcessed?fo(t,e):"{key:"+t+",fn:function("+String(e.attrsMap.scope)+"){return "+("template"===e.tag?po(e)||"void 0":to(e))+"}}"}function fo(t,e){var n=e.for,r=e.alias,o=e.iterator1?","+e.iterator1:"",i=e.iterator2?","+e.iterator2:"";return e.forProcessed=!0,"_l(("+n+"),function("+r+o+i+"){return "+lo(t,e)+"})"}function po(t,e){var n=t.children;if(n.length){var r=n[0];if(1===n.length&&r.for&&"template"!==r.tag&&"slot"!==r.tag)return to(r);var o=e?ho(n):0;return"["+n.map(go).join(",")+"]"+(o?","+o:"")}}function ho(t){for(var e=0,n=0;n<t.length;n++){var r=t[n];if(1===r.type){if(vo(r)||r.ifConditions&&r.ifConditions.some(function(t){return vo(t.block)})){e=2;break}(mo(r)||r.ifConditions&&r.ifConditions.some(function(t){return mo(t.block)}))&&(e=1)}}return e}function vo(t){return void 0!==t.for||"template"===t.tag||"slot"===t.tag}function mo(t){return!Ls(t.tag)}function go(t){return 1===t.type?to(t):yo(t)}function yo(t){return"_v("+(2===t.type?t.expression:xo(JSON.stringify(t.text)))+")"}function bo(t){var e=t.slotName||'"default"',n=po(t),r="_t("+e+(n?","+n:""),o=t.attrs&&"{"+t.attrs.map(function(t){return Io(t.name)+":"+t.value}).join(",")+"}",i=t.attrsMap["v-bind"];return!o&&!i||n||(r+=",null"),o&&(r+=","+o),i&&(r+=(o?"":",null")+","+i),r+")"}function _o(t,e){var n=e.inlineTemplate?null:po(e,!0);return"_c("+t+","+ao(e)+(n?","+n:"")+")"}function wo(t){for(var e="",n=0;n<t.length;n++){var r=t[n];e+='"'+r.name+'":'+xo(r.value)+","}return e.slice(0,-1)}function xo(t){return t.replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}function ko(t,e){var n=wr(t.trim(),e);Ur(n,e);var r=Qr(n,e);return{ast:n,render:r.render,staticRenderFns:r.staticRenderFns}}function $o(t,e){try{return new Function(t)}catch(n){return e.push({err:n,code:t}),_}}function Co(t,e){var n=(e.warn,vn(t,"class"));n&&(t.staticClass=JSON.stringify(n));var r=hn(t,"class",!1);r&&(t.classBinding=r)}function Oo(t){var e="";return t.staticClass&&(e+="staticClass:"+t.staticClass+","),t.classBinding&&(e+="class:"+t.classBinding+","),e}function So(t,e){var n=(e.warn,vn(t,"style"));if(n){t.staticStyle=JSON.stringify(ja(n))}var r=hn(t,"style",!1);r&&(t.styleBinding=r)}function Ao(t){var e="";return t.staticStyle&&(e+="staticStyle:"+t.staticStyle+","),t.styleBinding&&(e+="style:("+t.styleBinding+"),"),e}function jo(t,e){e.value&&ln(t,"textContent","_s("+e.value+")")}function Eo(t,e){e.value&&ln(t,"innerHTML","_s("+e.value+")")}function To(t){if(t.outerHTML)return t.outerHTML;var e=document.createElement("div");return e.appendChild(t.cloneNode(!0)),e.innerHTML}var Po=Object.prototype.toString,Lo=p("slot,component",!0),No=Object.prototype.hasOwnProperty,Io=v(function(t){return t.replace(/-(\w)/g,function(t,e){return e?e.toUpperCase():""})}),Mo=v(function(t){return t.charAt(0).toUpperCase()+t.slice(1)}),Ro=v(function(t){return t.replace(/([^-])([A-Z])/g,"$1-$2").replace(/([^-])([A-Z])/g,"$1-$2").toLowerCase()}),Do=function(){return!1},qo=function(t){return t},Fo="data-server-rendered",Uo=["component","directive","filter"],Ho=["beforeCreate","created","beforeMount","mounted","beforeUpdate","updated","beforeDestroy","destroyed","activated","deactivated"],Bo={optionMergeStrategies:Object.create(null),silent:!1,productionTip:!1,devtools:!1,performance:!1,errorHandler:null,ignoredElements:[],keyCodes:Object.create(null),isReservedTag:Do,isReservedAttr:Do,isUnknownElement:Do,getTagNamespace:_,parsePlatformTagName:qo,mustUseProp:Do,_lifecycleHooks:Ho},zo=Object.freeze({}),Vo=/[^\w.$]/,Wo=_,Go="__proto__"in{},Ko="undefined"!=typeof window,Jo=Ko&&window.navigator.userAgent.toLowerCase(),Zo=Jo&&/msie|trident/.test(Jo),Yo=Jo&&Jo.indexOf("msie 9.0")>0,Xo=Jo&&Jo.indexOf("edge/")>0,Qo=Jo&&Jo.indexOf("android")>0,ti=Jo&&/iphone|ipad|ipod|ios/.test(Jo),ei=Jo&&/chrome\/\d+/.test(Jo)&&!Xo,ni=!1;if(Ko)try{var ri={};Object.defineProperty(ri,"passive",{get:function(){ni=!0}}),window.addEventListener("test-passive",null,ri)}catch(t){}var oi,ii,ai=function(){return void 0===oi&&(oi=!Ko&&void 0!==t&&"server"===t.process.env.VUE_ENV),oi},si=Ko&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,ui="undefined"!=typeof Symbol&&A(Symbol)&&"undefined"!=typeof Reflect&&A(Reflect.ownKeys),ci=function(){function t(){r=!1;var t=n.slice(0);n.length=0;for(var e=0;e<t.length;e++)t[e]()}var e,n=[],r=!1;if("undefined"!=typeof Promise&&A(Promise)){var o=Promise.resolve(),i=function(t){console.error(t)};e=function(){o.then(t).catch(i),ti&&setTimeout(_)}}else if("undefined"==typeof MutationObserver||!A(MutationObserver)&&"[object MutationObserverConstructor]"!==MutationObserver.toString())e=function(){setTimeout(t,0)};else{var a=1,s=new MutationObserver(t),u=document.createTextNode(String(a));s.observe(u,{characterData:!0}),e=function(){a=(a+1)%2,u.data=String(a)}}return function(t,o){var i;if(n.push(function(){if(t)try{t.call(o)}catch(t){S(t,o,"nextTick")}else i&&i(o)}),r||(r=!0,e()),!t&&"undefined"!=typeof Promise)return new Promise(function(t,e){i=t})}}();ii="undefined"!=typeof Set&&A(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var li=0,fi=function(){this.id=li++,this.subs=[]};fi.prototype.addSub=function(t){this.subs.push(t)},fi.prototype.removeSub=function(t){d(this.subs,t)},fi.prototype.depend=function(){fi.target&&fi.target.addDep(this)},fi.prototype.notify=function(){for(var t=this.subs.slice(),e=0,n=t.length;e<n;e++)t[e].update()},fi.target=null;var pi=[],di=Array.prototype,hi=Object.create(di);["push","pop","shift","unshift","splice","sort","reverse"].forEach(function(t){var e=di[t];C(hi,t,function(){for(var n=arguments,r=arguments.length,o=new Array(r);r--;)o[r]=n[r];var i,a=e.apply(this,o),s=this.__ob__;switch(t){case"push":case"unshift":i=o;break;case"splice":i=o.slice(2)}return i&&s.observeArray(i),s.dep.notify(),a})});var vi=Object.getOwnPropertyNames(hi),mi={shouldConvert:!0,isSettingProps:!1},gi=function(t){if(this.value=t,this.dep=new fi,this.vmCount=0,C(t,"__ob__",this),Array.isArray(t)){(Go?T:P)(t,hi,vi),this.observeArray(t)}else this.walk(t)};gi.prototype.walk=function(t){for(var e=Object.keys(t),n=0;n<e.length;n++)N(t,e[n],t[e[n]])},gi.prototype.observeArray=function(t){for(var e=0,n=t.length;e<n;e++)L(t[e])};var yi=Bo.optionMergeStrategies;yi.data=function(t,e,n){return n?t||e?function(){var r="function"==typeof e?e.call(n):e,o="function"==typeof t?t.call(n):void 0;return r?D(r,o):o}:void 0:e?"function"!=typeof e?t:t?function(){return D(e.call(this),t.call(this))}:e:t},Ho.forEach(function(t){yi[t]=q}),Uo.forEach(function(t){yi[t+"s"]=F}),yi.watch=function(t,e){if(!e)return Object.create(t||null);if(!t)return e;var n={};y(n,t);for(var r in e){var o=n[r],i=e[r];o&&!Array.isArray(o)&&(o=[o]),n[r]=o?o.concat(i):[i]}return n},yi.props=yi.methods=yi.computed=function(t,e){if(!e)return Object.create(t||null);if(!t)return e;var n=Object.create(null);return y(n,t),y(n,e),n};var bi=function(t,e){return void 0===e?t:e},_i=function(t,e,n,r,o,i,a){this.tag=t,this.data=e,this.children=n,this.text=r,this.elm=o,this.ns=void 0,this.context=i,this.functionalContext=void 0,this.key=e&&e.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1},wi={child:{}};wi.child.get=function(){return this.componentInstance},Object.defineProperties(_i.prototype,wi);var xi,ki=function(){var t=new _i;return t.text="",t.isComment=!0,t},$i=v(function(t){var e="&"===t.charAt(0);t=e?t.slice(1):t;var n="~"===t.charAt(0);t=n?t.slice(1):t;var r="!"===t.charAt(0);return t=r?t.slice(1):t,{name:t,once:n,capture:r,passive:e}}),Ci=null,Oi=[],Si=[],Ai={},ji=!1,Ei=!1,Ti=0,Pi=0,Li=function(t,e,n,r){this.vm=t,t._watchers.push(this),r?(this.deep=!!r.deep,this.user=!!r.user,this.lazy=!!r.lazy,this.sync=!!r.sync):this.deep=this.user=this.lazy=this.sync=!1,this.cb=n,this.id=++Pi,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=new ii,this.newDepIds=new ii,this.expression="","function"==typeof e?this.getter=e:(this.getter=O(e),this.getter||(this.getter=function(){})),this.value=this.lazy?void 0:this.get()};Li.prototype.get=function(){j(this);var t,e=this.vm;if(this.user)try{t=this.getter.call(e,e)}catch(t){S(t,e,'getter for watcher "'+this.expression+'"')}else t=this.getter.call(e,e);return this.deep&&Et(t),E(),this.cleanupDeps(),t},Li.prototype.addDep=function(t){var e=t.id;this.newDepIds.has(e)||(this.newDepIds.add(e),this.newDeps.push(t),this.depIds.has(e)||t.addSub(this))},Li.prototype.cleanupDeps=function(){for(var t=this,e=this.deps.length;e--;){var n=t.deps[e];t.newDepIds.has(n.id)||n.removeSub(t)}var r=this.depIds;this.depIds=this.newDepIds,this.newDepIds=r,this.newDepIds.clear(),r=this.deps,this.deps=this.newDeps,this.newDeps=r,this.newDeps.length=0},Li.prototype.update=function(){this.lazy?this.dirty=!0:this.sync?this.run():jt(this)},Li.prototype.run=function(){if(this.active){var t=this.get();if(t!==this.value||s(t)||this.deep){var e=this.value;if(this.value=t,this.user)try{this.cb.call(this.vm,t,e)}catch(t){S(t,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,t,e)}}},Li.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},Li.prototype.depend=function(){for(var t=this,e=this.deps.length;e--;)t.deps[e].depend()},Li.prototype.teardown=function(){var t=this;if(this.active){this.vm._isBeingDestroyed||d(this.vm._watchers,this);for(var e=this.deps.length;e--;)t.deps[e].removeSub(t);this.active=!1}};var Ni=new ii,Ii={enumerable:!0,configurable:!0,get:_,set:_},Mi={lazy:!0},Ri={init:function(t,e,n,r){if(!t.componentInstance||t.componentInstance._isDestroyed){(t.componentInstance=Jt(t,Ci,n,r)).$mount(e?t.elm:void 0,e)}else if(t.data.keepAlive){var o=t;Ri.prepatch(o,o)}},prepatch:function(t,e){var n=e.componentOptions;bt(e.componentInstance=t.componentInstance,n.propsData,n.listeners,e,n.children)},insert:function(t){var e=t.context,n=t.componentInstance;n._isMounted||(n._isMounted=!0,kt(n,"mounted")),t.data.keepAlive&&(e._isMounted?St(n):wt(n,!0))},destroy:function(t){var e=t.componentInstance;e._isDestroyed||(t.data.keepAlive?xt(e,!0):e.$destroy())}},Di=Object.keys(Ri),qi=1,Fi=2,Ui=0;(function(t){t.prototype._init=function(t){var e=this;e._uid=Ui++;e._isVue=!0,t&&t._isComponent?pe(e,t):e.$options=B(de(e.constructor),t||{},e),e._renderProxy=e,e._self=e,gt(e),lt(e),fe(e),kt(e,"beforeCreate"),zt(e),Lt(e),Bt(e),kt(e,"created"),e.$options.el&&e.$mount(e.$options.el)}})(me),function(t){var e={};e.get=function(){return this._data};var n={};n.get=function(){return this._props},Object.defineProperty(t.prototype,"$data",e),Object.defineProperty(t.prototype,"$props",n),t.prototype.$set=I,t.prototype.$delete=M,t.prototype.$watch=function(t,e,n){var r=this;n=n||{},n.user=!0;var o=new Li(r,t,e,n);return n.immediate&&e.call(r,o.value),function(){o.teardown()}}}(me),function(t){var e=/^hook:/;t.prototype.$on=function(t,n){var r=this,o=this;if(Array.isArray(t))for(var i=0,a=t.length;i<a;i++)r.$on(t[i],n);else(o._events[t]||(o._events[t]=[])).push(n),e.test(t)&&(o._hasHookEvent=!0);return o},t.prototype.$once=function(t,e){function n(){r.$off(t,n),e.apply(r,arguments)}var r=this;return n.fn=e,r.$on(t,n),r},t.prototype.$off=function(t,e){var n=this,r=this;if(!arguments.length)return r._events=Object.create(null),r;if(Array.isArray(t)){for(var o=0,i=t.length;o<i;o++)n.$off(t[o],e);return r}var a=r._events[t];if(!a)return r;if(1===arguments.length)return r._events[t]=null,r;for(var s,u=a.length;u--;)if((s=a[u])===e||s.fn===e){a.splice(u,1);break}return r},t.prototype.$emit=function(t){var e=this,n=e._events[t];if(n){n=n.length>1?g(n):n;for(var r=g(arguments,1),o=0,i=n.length;o<i;o++)n[o].apply(e,r)}return e}}(me),function(t){t.prototype._update=function(t,e){var n=this;n._isMounted&&kt(n,"beforeUpdate");var r=n.$el,o=n._vnode,i=Ci;Ci=n,n._vnode=t,n.$el=o?n.__patch__(o,t):n.__patch__(n.$el,t,e,!1,n.$options._parentElm,n.$options._refElm),Ci=i,r&&(r.__vue__=null),n.$el&&(n.$el.__vue__=n),n.$vnode&&n.$parent&&n.$vnode===n.$parent._vnode&&(n.$parent.$el=n.$el)},t.prototype.$forceUpdate=function(){var t=this;t._watcher&&t._watcher.update()},t.prototype.$destroy=function(){var t=this;if(!t._isBeingDestroyed){kt(t,"beforeDestroy"),t._isBeingDestroyed=!0;var e=t.$parent;!e||e._isBeingDestroyed||t.$options.abstract||d(e.$children,t),t._watcher&&t._watcher.teardown();for(var n=t._watchers.length;n--;)t._watchers[n].teardown();t._data.__ob__&&t._data.__ob__.vmCount--,t._isDestroyed=!0,t.__patch__(t._vnode,null),kt(t,"destroyed"),t.$off(),t.$el&&(t.$el.__vue__=null),t.$options._parentElm=t.$options._refElm=null}}}(me),function(t){t.prototype.$nextTick=function(t){return ci(t,this)},t.prototype._render=function(){var t=this,e=t.$options,n=e.render,r=e.staticRenderFns,o=e._parentVnode;if(t._isMounted)for(var i in t.$slots)t.$slots[i]=Y(t.$slots[i]);t.$scopedSlots=o&&o.data.scopedSlots||zo,r&&!t._staticTrees&&(t._staticTrees=[]),t.$vnode=o;var a;try{a=n.call(t._renderProxy,t.$createElement)}catch(e){S(e,t,"render function"),a=t._vnode}return a instanceof _i||(a=ki()),a.parent=o,a},t.prototype._o=ue,t.prototype._n=f,t.prototype._s=l,t.prototype._l=ne,t.prototype._t=re,t.prototype._q=w,t.prototype._i=x,t.prototype._m=se,t.prototype._f=oe,t.prototype._k=ie,t.prototype._b=ae,t.prototype._v=J,t.prototype._e=ki,t.prototype._u=mt}(me);var Hi=[String,RegExp],Bi={name:"keep-alive",abstract:!0,props:{include:Hi,exclude:Hi},created:function(){this.cache=Object.create(null)},destroyed:function(){var t=this;for(var e in t.cache)Oe(t.cache[e])},watch:{include:function(t){Ce(this.cache,this._vnode,function(e){return $e(t,e)})},exclude:function(t){Ce(this.cache,this._vnode,function(e){return!$e(t,e)})}},render:function(){var t=ct(this.$slots.default),e=t&&t.componentOptions;if(e){var n=ke(e);if(n&&(this.include&&!$e(this.include,n)||this.exclude&&$e(this.exclude,n)))return t;var r=null==t.key?e.Ctor.cid+(e.tag?"::"+e.tag:""):t.key;this.cache[r]?t.componentInstance=this.cache[r].componentInstance:this.cache[r]=t,t.data.keepAlive=!0}return t}},zi={KeepAlive:Bi};(function(t){var e={};e.get=function(){return Bo},Object.defineProperty(t,"config",e),t.util={warn:Wo,extend:y,mergeOptions:B,defineReactive:N},t.set=I,t.delete=M,t.nextTick=ci,t.options=Object.create(null),Uo.forEach(function(e){t.options[e+"s"]=Object.create(null)}),t.options._base=t,y(t.options.components,zi),ge(t),ye(t),be(t),xe(t)})(me),Object.defineProperty(me.prototype,"$isServer",{get:ai}),Object.defineProperty(me.prototype,"$ssrContext",{get:function(){return this.$vnode.ssrContext}}),me.version="2.3.3";var Vi,Wi,Gi,Ki,Ji,Zi,Yi,Xi,Qi,ta=p("style,class"),ea=p("input,textarea,option,select"),na=function(t,e,n){return"value"===n&&ea(t)&&"button"!==e||"selected"===n&&"option"===t||"checked"===n&&"input"===t||"muted"===n&&"video"===t},ra=p("contenteditable,draggable,spellcheck"),oa=p("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,translate,truespeed,typemustmatch,visible"),ia="http://www.w3.org/1999/xlink",aa=function(t){return":"===t.charAt(5)&&"xlink"===t.slice(0,5)},sa=function(t){return aa(t)?t.slice(6,t.length):""},ua=function(t){return null==t||!1===t},ca={svg:"http://www.w3.org/2000/svg",math:"http://www.w3.org/1998/Math/MathML"},la=p("html,body,base,head,link,meta,style,title,address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,div,dd,dl,dt,figcaption,figure,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,menuitem,summary,content,element,shadow,template"),fa=p("svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view",!0),pa=function(t){return"pre"===t},da=function(t){return la(t)||fa(t)},ha=Object.create(null),va=Object.freeze({createElement:Ie,createElementNS:Me,createTextNode:Re,createComment:De,insertBefore:qe,removeChild:Fe,appendChild:Ue,parentNode:He,nextSibling:Be,tagName:ze,setTextContent:Ve,setAttribute:We}),ma={create:function(t,e){Ge(e)},update:function(t,e){t.data.ref!==e.data.ref&&(Ge(t,!0),Ge(e))},destroy:function(t){Ge(t,!0)}},ga=new _i("",{},[]),ya=["create","activate","update","remove","destroy"],ba={create:Ye,update:Ye,destroy:function(t){Ye(t,ga)}},_a=Object.create(null),wa=[ma,ba],xa={create:nn,update:nn},ka={create:on,update:on},$a=/[\w).+\-_$\]]/,Ca="__r",Oa="__c",Sa={create:Pn,update:Pn},Aa={create:Ln,update:Ln},ja=v(function(t){var e={};return t.split(/;(?![^(]*\))/g).forEach(function(t){if(t){var n=t.split(/:(.+)/);n.length>1&&(e[n[0].trim()]=n[1].trim())}}),e}),Ea=/^--/,Ta=/\s*!important$/,Pa=function(t,e,n){if(Ea.test(e))t.style.setProperty(e,n);else if(Ta.test(n))t.style.setProperty(e,n.replace(Ta,""),"important");else{var r=Na(e);if(Array.isArray(n))for(var o=0,i=n.length;o<i;o++)t.style[r]=n[o];else t.style[r]=n}},La=["Webkit","Moz","ms"],Na=v(function(t){if(Qi=Qi||document.createElement("div"),"filter"!==(t=Io(t))&&t in Qi.style)return t;for(var e=t.charAt(0).toUpperCase()+t.slice(1),n=0;n<La.length;n++){var r=La[n]+e;if(r in Qi.style)return r}}),Ia={create:Fn,update:Fn},Ma=v(function(t){return{enterClass:t+"-enter",enterToClass:t+"-enter-to",enterActiveClass:t+"-enter-active",leaveClass:t+"-leave",leaveToClass:t+"-leave-to",leaveActiveClass:t+"-leave-active"}}),Ra=Ko&&!Yo,Da="transition",qa="animation",Fa="transition",Ua="transitionend",Ha="animation",Ba="animationend";Ra&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(Fa="WebkitTransition",Ua="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(Ha="WebkitAnimation",Ba="webkitAnimationEnd"));var za=Ko&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout,Va=/\b(transform|all)(,|$)/,Wa=Ko?{create:er,activate:er,remove:function(t,e){!0!==t.data.show?Xn(t,e):e()}}:{},Ga=[xa,ka,Sa,Aa,Ia,Wa],Ka=Ga.concat(wa),Ja=function(t){function e(t){return new _i(E.tagName(t).toLowerCase(),{},[],void 0,t)}function i(t,e){function n(){0==--n.listeners&&s(t)}return n.listeners=e,n}function s(t){var e=E.parentNode(t);r(e)&&E.removeChild(e,t)}function u(t,e,n,i,a){if(t.isRootInsert=!a,!c(t,e,n,i)){var s=t.data,u=t.children,l=t.tag;r(l)?(t.elm=t.ns?E.createElementNS(t.ns,l):E.createElement(l,t),g(t),h(t,u,e),r(s)&&m(t,e),d(n,t.elm,i)):o(t.isComment)?(t.elm=E.createComment(t.text),d(n,t.elm,i)):(t.elm=E.createTextNode(t.text),d(n,t.elm,i))}}function c(t,e,n,i){var a=t.data;if(r(a)){var s=r(t.componentInstance)&&a.keepAlive;if(r(a=a.hook)&&r(a=a.init)&&a(t,!1,n,i),r(t.componentInstance))return l(t,e),o(s)&&f(t,e,n,i),!0}}function l(t,e){r(t.data.pendingInsert)&&e.push.apply(e,t.data.pendingInsert),t.elm=t.componentInstance.$el,v(t)?(m(t,e),g(t)):(Ge(t),e.push(t))}function f(t,e,n,o){for(var i,a=t;a.componentInstance;)if(a=a.componentInstance._vnode,r(i=a.data)&&r(i=i.transition)){for(i=0;i<A.activate.length;++i)A.activate[i](ga,a);e.push(a);break}d(n,t.elm,o)}function d(t,e,n){r(t)&&(r(n)?n.parentNode===t&&E.insertBefore(t,e,n):E.appendChild(t,e))}function h(t,e,n){if(Array.isArray(e))for(var r=0;r<e.length;++r)u(e[r],n,t.elm,null,!0);else a(t.text)&&E.appendChild(t.elm,E.createTextNode(t.text))}function v(t){for(;t.componentInstance;)t=t.componentInstance._vnode;return r(t.tag)}function m(t,e){for(var n=0;n<A.create.length;++n)A.create[n](ga,t);O=t.data.hook,r(O)&&(r(O.create)&&O.create(ga,t),r(O.insert)&&e.push(t))}function g(t){for(var e,n=t;n;)r(e=n.context)&&r(e=e.$options._scopeId)&&E.setAttribute(t.elm,e,""),n=n.parent;r(e=Ci)&&e!==t.context&&r(e=e.$options._scopeId)&&E.setAttribute(t.elm,e,"")}function y(t,e,n,r,o,i){for(;r<=o;++r)u(n[r],i,t,e)}function b(t){var e,n,o=t.data;if(r(o))for(r(e=o.hook)&&r(e=e.destroy)&&e(t),e=0;e<A.destroy.length;++e)A.destroy[e](t);if(r(e=t.children))for(n=0;n<t.children.length;++n)b(t.children[n])}function _(t,e,n,o){for(;n<=o;++n){var i=e[n];r(i)&&(r(i.tag)?(w(i),b(i)):s(i.elm))}}function w(t,e){if(r(e)||r(t.data)){var n,o=A.remove.length+1;for(r(e)?e.listeners+=o:e=i(t.elm,o),r(n=t.componentInstance)&&r(n=n._vnode)&&r(n.data)&&w(n,e),n=0;n<A.remove.length;++n)A.remove[n](t,e);r(n=t.data.hook)&&r(n=n.remove)?n(t,e):e()}else s(t.elm)}function x(t,e,o,i,a){for(var s,c,l,f,p=0,d=0,h=e.length-1,v=e[0],m=e[h],g=o.length-1,b=o[0],w=o[g],x=!a;p<=h&&d<=g;)n(v)?v=e[++p]:n(m)?m=e[--h]:Ke(v,b)?(k(v,b,i),v=e[++p],b=o[++d]):Ke(m,w)?(k(m,w,i),m=e[--h],w=o[--g]):Ke(v,w)?(k(v,w,i),x&&E.insertBefore(t,v.elm,E.nextSibling(m.elm)),v=e[++p],w=o[--g]):Ke(m,b)?(k(m,b,i),x&&E.insertBefore(t,m.elm,v.elm),m=e[--h],b=o[++d]):(n(s)&&(s=Ze(e,p,h)),c=r(b.key)?s[b.key]:null,n(c)?(u(b,i,t,v.elm),b=o[++d]):(l=e[c],Ke(l,b)?(k(l,b,i),e[c]=void 0,x&&E.insertBefore(t,b.elm,v.elm),b=o[++d]):(u(b,i,t,v.elm),b=o[++d])));p>h?(f=n(o[g+1])?null:o[g+1].elm,y(t,f,o,d,g,i)):d>g&&_(t,e,p,h)}function k(t,e,i,a){if(t!==e){if(o(e.isStatic)&&o(t.isStatic)&&e.key===t.key&&(o(e.isCloned)||o(e.isOnce)))return e.elm=t.elm,void(e.componentInstance=t.componentInstance);var s,u=e.data;r(u)&&r(s=u.hook)&&r(s=s.prepatch)&&s(t,e);var c=e.elm=t.elm,l=t.children,f=e.children;if(r(u)&&v(e)){for(s=0;s<A.update.length;++s)A.update[s](t,e);r(s=u.hook)&&r(s=s.update)&&s(t,e)}n(e.text)?r(l)&&r(f)?l!==f&&x(c,l,f,i,a):r(f)?(r(t.text)&&E.setTextContent(c,""),y(c,null,f,0,f.length-1,i)):r(l)?_(c,l,0,l.length-1):r(t.text)&&E.setTextContent(c,""):t.text!==e.text&&E.setTextContent(c,e.text),r(u)&&r(s=u.hook)&&r(s=s.postpatch)&&s(t,e)}}function $(t,e,n){if(o(n)&&r(t.parent))t.parent.data.pendingInsert=e;else for(var i=0;i<e.length;++i)e[i].data.hook.insert(e[i])}function C(t,e,n){e.elm=t;var o=e.tag,i=e.data,a=e.children;if(r(i)&&(r(O=i.hook)&&r(O=O.init)&&O(e,!0),r(O=e.componentInstance)))return l(e,n),!0;if(r(o)){if(r(a))if(t.hasChildNodes()){for(var s=!0,u=t.firstChild,c=0;c<a.length;c++){if(!u||!C(u,a[c],n)){s=!1;break}u=u.nextSibling}if(!s||u)return!1}else h(e,a,n);if(r(i))for(var f in i)if(!T(f)){m(e,n);break}}else t.data!==e.text&&(t.data=e.text);return!0}var O,S,A={},j=t.modules,E=t.nodeOps;for(O=0;O<ya.length;++O)for(A[ya[O]]=[],S=0;S<j.length;++S)r(j[S][ya[O]])&&A[ya[O]].push(j[S][ya[O]]);var T=p("attrs,style,class,staticClass,staticStyle,key");return function(t,i,a,s,c,l){if(n(i))return void(r(t)&&b(t));var f=!1,p=[];if(n(t))f=!0,u(i,p,c,l);else{var d=r(t.nodeType);if(!d&&Ke(t,i))k(t,i,p,s);else{if(d){if(1===t.nodeType&&t.hasAttribute(Fo)&&(t.removeAttribute(Fo),a=!0),o(a)&&C(t,i,p))return $(i,p,!0),t;t=e(t)}var h=t.elm,m=E.parentNode(h);if(u(i,p,h._leaveCb?null:m,E.nextSibling(h)),r(i.parent)){for(var g=i.parent;g;)g.elm=i.elm,g=g.parent;if(v(i))for(var y=0;y<A.create.length;++y)A.create[y](ga,i.parent)}r(m)?_(m,[t],0,0):r(t.tag)&&b(t)}}return $(i,p,f),i.elm}}({nodeOps:va,modules:Ka});Yo&&document.addEventListener("selectionchange",function(){var t=document.activeElement;t&&t.vmodel&&sr(t,"input")});var Za={inserted:function(t,e,n){if("select"===n.tag){var r=function(){nr(t,e,n.context)};r(),(Zo||Xo)&&setTimeout(r,0)}else"textarea"!==n.tag&&"text"!==t.type&&"password"!==t.type||(t._vModifiers=e.modifiers,e.modifiers.lazy||(t.addEventListener("change",ar),Qo||(t.addEventListener("compositionstart",ir),t.addEventListener("compositionend",ar)),Yo&&(t.vmodel=!0)))},componentUpdated:function(t,e,n){if("select"===n.tag){nr(t,e,n.context);(t.multiple?e.value.some(function(e){return rr(e,t.options)}):e.value!==e.oldValue&&rr(e.value,t.options))&&sr(t,"change")}}},Ya={bind:function(t,e,n){var r=e.value;n=ur(n);var o=n.data&&n.data.transition,i=t.__vOriginalDisplay="none"===t.style.display?"":t.style.display;r&&o&&!Yo?(n.data.show=!0,Yn(n,function(){t.style.display=i})):t.style.display=r?i:"none"},update:function(t,e,n){var r=e.value;r!==e.oldValue&&(n=ur(n),n.data&&n.data.transition&&!Yo?(n.data.show=!0,r?Yn(n,function(){t.style.display=t.__vOriginalDisplay}):Xn(n,function(){t.style.display="none"})):t.style.display=r?t.__vOriginalDisplay:"none")},unbind:function(t,e,n,r,o){o||(t.style.display=t.__vOriginalDisplay)}},Xa={model:Za,show:Ya},Qa={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]},ts={name:"transition",props:Qa,abstract:!0,render:function(t){var e=this,n=this.$slots.default;if(n&&(n=n.filter(function(t){return t.tag}),n.length)){var r=this.mode,o=n[0];if(pr(this.$vnode))return o;var i=cr(o);if(!i)return o;if(this._leaving)return fr(t,o);var s="__transition-"+this._uid+"-";i.key=null==i.key?s+i.tag:a(i.key)?0===String(i.key).indexOf(s)?i.key:s+i.key:i.key;var u=(i.data||(i.data={})).transition=lr(this),c=this._vnode,l=cr(c);if(i.data.directives&&i.data.directives.some(function(t){return"show"===t.name})&&(i.data.show=!0),l&&l.data&&!dr(i,l)){var f=l&&(l.data.transition=y({},u));if("out-in"===r)return this._leaving=!0,tt(f,"afterLeave",function(){e._leaving=!1,e.$forceUpdate()}),fr(t,o);if("in-out"===r){var p,d=function(){p()};tt(u,"afterEnter",d),tt(u,"enterCancelled",d),tt(f,"delayLeave",function(t){p=t})}}return o}}},es=y({tag:String,moveClass:String},Qa);delete es.mode;var ns={props:es,render:function(t){for(var e=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,o=this.$slots.default||[],i=this.children=[],a=lr(this),s=0;s<o.length;s++){var u=o[s];if(u.tag)if(null!=u.key&&0!==String(u.key).indexOf("__vlist"))i.push(u),n[u.key]=u,(u.data||(u.data={})).transition=a;else;}if(r){for(var c=[],l=[],f=0;f<r.length;f++){var p=r[f];p.data.transition=a,p.data.pos=p.elm.getBoundingClientRect(),n[p.key]?c.push(p):l.push(p)}this.kept=t(e,null,c),this.removed=l}return t(e,null,i)},beforeUpdate:function(){this.__patch__(this._vnode,this.kept,!1,!0),this._vnode=this.kept},updated:function(){var t=this.prevChildren,e=this.moveClass||(this.name||"v")+"-move";if(t.length&&this.hasMove(t[0].elm,e)){t.forEach(hr),t.forEach(vr),t.forEach(mr);var n=document.body;n.offsetHeight;t.forEach(function(t){if(t.data.moved){var n=t.elm,r=n.style;Vn(n,e),r.transform=r.WebkitTransform=r.transitionDuration="",n.addEventListener(Ua,n._moveCb=function t(r){r&&!/transform$/.test(r.propertyName)||(n.removeEventListener(Ua,t),n._moveCb=null,Wn(n,e))})}})}},methods:{hasMove:function(t,e){if(!Ra)return!1;if(null!=this._hasMove)return this._hasMove;var n=t.cloneNode();t._transitionClasses&&t._transitionClasses.forEach(function(t){Hn(n,t)}),Un(n,e),n.style.display="none",this.$el.appendChild(n);var r=Kn(n);return this.$el.removeChild(n),this._hasMove=r.hasTransform}}},rs={Transition:ts,TransitionGroup:ns};me.config.mustUseProp=na,me.config.isReservedTag=da,me.config.isReservedAttr=ta,me.config.getTagNamespace=Pe,me.config.isUnknownElement=Le,y(me.options.directives,Xa),y(me.options.components,rs),me.prototype.__patch__=Ko?Ja:_,me.prototype.$mount=function(t,e){return t=t&&Ko?Ne(t):void 0,yt(this,t,e)},setTimeout(function(){Bo.devtools&&si&&si.emit("init",me)},0);var os,is=!!Ko&&function(t,e){var n=document.createElement("div");return n.innerHTML='<div a="'+t+'">',n.innerHTML.indexOf(e)>0}("\n","&#10;"),as=p("area,base,br,col,embed,frame,hr,img,input,isindex,keygen,link,meta,param,source,track,wbr"),ss=p("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source"),us=p("address,article,aside,base,blockquote,body,caption,col,colgroup,dd,details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,title,tr,track"),cs=[/"([^"]*)"+/.source,/'([^']*)'+/.source,/([^\s"'=<>`]+)/.source],ls=new RegExp("^\\s*"+/([^\s"'<>\/=]+)/.source+"(?:\\s*("+/(?:=)/.source+")\\s*(?:"+cs.join("|")+"))?"),fs="[a-zA-Z_][\\w\\-\\.]*",ps=new RegExp("^<((?:"+fs+"\\:)?"+fs+")"),ds=/^\s*(\/?)>/,hs=new RegExp("^<\\/((?:"+fs+"\\:)?"+fs+")[^>]*>"),vs=/^<!DOCTYPE [^>]+>/i,ms=/^<!--/,gs=/^<!\[/,ys=!1;"x".replace(/x(.)?/g,function(t,e){ys=""===e});var bs,_s,ws,xs,ks,$s,Cs,Os,Ss,As,js,Es,Ts,Ps,Ls,Ns,Is,Ms,Rs=p("script,style,textarea",!0),Ds={},qs={"&lt;":"<","&gt;":">","&quot;":'"',"&amp;":"&","&#10;":"\n"},Fs=/&(?:lt|gt|quot|amp);/g,Us=/&(?:lt|gt|quot|amp|#10);/g,Hs=/\{\{((?:.|\n)+?)\}\}/g,Bs=v(function(t){var e=t[0].replace(/[-.*+?^${}()|[\]\/\\]/g,"\\$&"),n=t[1].replace(/[-.*+?^${}()|[\]\/\\]/g,"\\$&");return new RegExp(e+"((?:.|\\n)+?)"+n,"g")}),zs=/^@|^v-on:/,Vs=/^v-|^@|^:/,Ws=/(.*?)\s+(?:in|of)\s+(.*)/,Gs=/\((\{[^}]*\}|[^,]*),([^,]*)(?:,([^,]*))?\)/,Ks=/:(.*)$/,Js=/^:|^v-bind:/,Zs=/\.[^.]+/g,Ys=v(gr),Xs=/^xmlns:NS\d+/,Qs=/^NS\d+:/,tu=v(Hr),eu=/^\s*([\w$_]+|\([^)]*?\))\s*=>|^function\s*\(/,nu=/^\s*[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?']|\[".*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*\s*$/,ru={esc:27,tab:9,enter:13,space:32,up:38,left:37,right:39,down:40,delete:[8,46]},ou=function(t){return"if("+t+")return null;"},iu={stop:"$event.stopPropagation();",prevent:"$event.preventDefault();",self:ou("$event.target !== $event.currentTarget"),ctrl:ou("!$event.ctrlKey"),shift:ou("!$event.shiftKey"),alt:ou("!$event.altKey"),meta:ou("!$event.metaKey"),left:ou("'button' in $event && $event.button !== 0"),middle:ou("'button' in $event && $event.button !== 1"),right:ou("'button' in $event && $event.button !== 2")},au={bind:Xr,cloak:_},su=(new RegExp("\\b"+"do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,super,throw,while,yield,delete,export,import,return,switch,default,extends,finally,continue,debugger,function,arguments".split(",").join("\\b|\\b")+"\\b"),new RegExp("\\b"+"delete,typeof,void".split(",").join("\\s*\\([^\\)]*\\)|\\b")+"\\s*\\([^\\)]*\\)"),{staticKeys:["staticClass"],transformNode:Co,genData:Oo}),uu={staticKeys:["staticStyle"],transformNode:So,genData:Ao},cu=[su,uu],lu={model:$n,text:jo,html:Eo},fu={expectHTML:!0,modules:cu,directives:lu,isPreTag:pa,isUnaryTag:as,mustUseProp:na,canBeLeftOpenTag:ss,isReservedTag:da,getTagNamespace:Pe,staticKeys:function(t){return t.reduce(function(t,e){return t.concat(e.staticKeys||[])},[]).join(",")}(cu)},pu=function(t){function e(e,n){var r=Object.create(t),o=[],i=[];if(r.warn=function(t,e){(e?i:o).push(t)},n){n.modules&&(r.modules=(t.modules||[]).concat(n.modules)),n.directives&&(r.directives=y(Object.create(t.directives),n.directives));for(var a in n)"modules"!==a&&"directives"!==a&&(r[a]=n[a])}var s=ko(e,r);return s.errors=o,s.tips=i,s}function n(t,n,o){n=n||{};var i=n.delimiters?String(n.delimiters)+t:t;if(r[i])return r[i];var a=e(t,n),s={},u=[];s.render=$o(a.render,u);var c=a.staticRenderFns.length;s.staticRenderFns=new Array(c);for(var l=0;l<c;l++)s.staticRenderFns[l]=$o(a.staticRenderFns[l],u);return r[i]=s}var r=Object.create(null);return{compile:e,compileToFunctions:n}}(fu),du=pu.compileToFunctions,hu=v(function(t){var e=Ne(t);return e&&e.innerHTML}),vu=me.prototype.$mount;me.prototype.$mount=function(t,e){if((t=t&&Ne(t))===document.body||t===document.documentElement)return this;var n=this.$options;if(!n.render){var r=n.template;if(r)if("string"==typeof r)"#"===r.charAt(0)&&(r=hu(r));else{if(!r.nodeType)return this;r=r.innerHTML}else t&&(r=To(t));if(r){var o=du(r,{shouldDecodeNewlines:is,delimiters:n.delimiters},this),i=o.render,a=o.staticRenderFns;n.render=i,n.staticRenderFns=a}}return vu.call(this,t,e)},me.compile=du,e.a=me}).call(e,n(2))},function(t,e,n){"use strict";function r(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e<t.length;e++)n[e]=t[e];return n}return Array.from(t)}function o(t){return t.map(function(t){return"dropdown"===t.type?t.items:[t]}).reduce(function(t,e){return[].concat(r(t),r(e))},[])}var i=n(12),a=n(1),s=n(17),u=n.n(s),c=n(9),l=n(31),f=n(6),p="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};i.a.use(a.e);var d=new a.e.Store({state:{config:{},page:{html:"",attributes:{},headings:[]},loaded:!1,showMobileSidebar:!1,jumping:!1,activeId:"",searchState:{placeHolder:"Type to search",emptyState:"No results"},searching:!1,searchResult:null,searchKeyword:"",showSidebar:!0},mutations:{SET_CONFIG:function(t,e){t.config=Object.assign({title:document.title},e),"boolean"==typeof t.config.sidebar&&(t.showSidebar=t.config.sidebar)},TOGGLE_DROPDOWN:function(t,e){t.config.nav=t.config.nav.map(function(t,n){return n===e?Object.assign({},t,{show:!t.show}):t})},UPDATE_PAGE:function(t,e){t.page={attributes:Object.assign({title:null,search:null,icons:null,sidebar:t.showSidebar},e.attributes),html:e.html,headings:e.headings},t.loaded=!0,t.activeId=""},TOGGLE_MOBILE_SIDEBAR:function(t,e){t.showMobileSidebar=void 0===e?!t.showMobileSidebar:e},TOGGLE_SIDEBAR:function(t,e){var n=void 0;if(void 0===e){n=!u()(t.page.attributes.sidebar,t.showSidebar)}else n=e;t.showSidebar=n,t.page.attributes.sidebar=n},UPDATE_JUMPING:function(t,e){t.jumping=e},UPDATE_ACTIVE_ID:function(t,e){t.activeId=e},START_SEARCHING:function(t){t.searching=!0},STOP_SEARCHING:function(t,e){t.searching=!1,t.searchResult=e},UPDATE_SEARCH_KEYWORD:function(t,e){t.searchKeyword=e}},actions:{toggleDropdown:function(t,e){(0,t.commit)("TOGGLE_DROPDOWN",e)},updatePage:function(t,e){(0,t.commit)("UPDATE_PAGE",e)},toggleMobileSidebar:function(t,e){(0,t.commit)("TOGGLE_MOBILE_SIDEBAR",e)},toggleSidebar:function(t,e){(0,t.commit)("TOGGLE_SIDEBAR",e)},startJumping:function(t){(0,t.commit)("UPDATE_JUMPING",!0)},stopJumping:function(t){(0,t.commit)("UPDATE_JUMPING",!1)},updateActiveId:function(t,e){(0,t.commit)("UPDATE_ACTIVE_ID",e)},jumpToId:function(t,e){var r=t.dispatch;r("updateActiveId",e),r("startJumping"),f.a.emit("jump:started",e),n.i(l.a)(e,function(){return setTimeout(function(){r("stopJumping"),f.a.emit("jump:stopped",e)},400)})},startSearching:function(t){(0,t.commit)("START_SEARCHING"),f.a.emit("search:started")},stopSearching:function(t,e){(0,t.commit)("STOP_SEARCHING",e),f.a.emit("search:stopped",e)},updateSearchKeyword:function(t,e){(0,t.commit)("UPDATE_SEARCH_KEYWORD",e)},searchReset:function(t){var e=t.commit;e("UPDATE_SEARCH_KEYWORD",""),e("STOP_SEARCHING",null)}},getters:{currentTitle:function(t,e){var n=e.currentNavItem;return n&&n.title},currentNavItem:function(t,e){var n=e.currentNav,r=t.route.path;return o(n).filter(function(t){return t.path===r})[0]},currentNav:function(t){var e=t.config.nav,r=t.page.attributes;return Array.isArray(e)?e:n.i(c.b)(e,"Object")?r&&r.nav?e[r.nav]:e.default:[]},documentTitle:function(t,e){var n=e.currentTitle,r=t.config.title,o=t.page.attributes;return o&&o.title?r?o.title+" - "+r:o.title:n?r?n+" - "+r:n:t.config.title},currentTags:function(t){var e=t.page.attributes;return"string"==typeof e.search?[e.search]:Array.isArray(e.search)?e.search:[]},showSidebar:function(t){return"boolean"==typeof t.page.attributes.sidebar?t.page.attributes.sidebar:t.showSidebar},showToc:function(t){var e=t.config,n=t.page.attributes,r=t.route,o=!0;return void 0!==n.toc&&(o=n.toc),void 0!==e.toc&&(o=e.toc),"function"==typeof o&&(o=o(r)),o},showCustomToc:function(t,e){var n=e.showToc;return"string"==typeof n||"object"===(void 0===n?"undefined":p(n))}}});e.a=d},function(t,e,n){"use strict";function r(t){return function(){var e=t.apply(this,arguments);return new Promise(function(t,n){function r(o,i){try{var a=e[o](i),s=a.value}catch(t){return void n(t)}if(!a.done)return Promise.resolve(s).then(function(t){r("next",t)},function(t){r("throw",t)});t(s)}return r("next")})}}function o(t){return/\.(html|md)$/.test(t)}var i=n(7),a=n.n(i),s=n(11),u=n.n(s),c=n(10),l=n(9),f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};e.a=function(){var t=r(a.a.mark(function t(e){var r,i,s,p,d,h=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},v=h.fallback,m=h.progress,g=void 0===m||m,y=h.marked,b=h.componentName,_=void 0===b?"custom-resource":b;return a.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(r=void 0,i=void 0,s=void 0,p=void 0,!0===e&&(e=v),"string"==typeof e?s=e:"object"===(void 0===e?"undefined":f(e))&&e.source&&(s=e.source),!o(s)){t.next=20;break}return g&&u.a.start(),t.next=10,fetch(s,{credentials:n.i(l.a)(s)});case 10:if(d=t.sent,g&&u.a.done(),404!==d.status){t.next=14;break}throw new Error(s+" not found");case 14:return t.next=16,d.text();case 16:r=t.sent,i=/\.html$/.test(s)?r:n.i(c.a)(r),t.next=21;break;case 20:"string"==typeof s&&(r=s,i=n.i(c.a)(r,y));case 21:return"object"===(void 0===e?"undefined":f(e))&&(e.markdown?(r=e.markdown,i=n.i(c.a)(r,y)):e.html&&(i=e.html),e.component&&(p=Object.assign({name:_},e.component,{template:"<div>"+i+"</div>"}))),t.abrupt("return",{component:p,html:i});case 23:case"end":return t.stop()}},t,this)}));return function(e){return t.apply(this,arguments)}}()},function(t,e,n){"use strict";function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}n.d(e,"a",function(){return s}),n.d(e,"b",function(){return u});var o=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),i=function(){function t(){r(this,t),this.beforeParseParsers=[],this.afterParseParsers=[]}return o(t,[{key:"beforeParse",value:function(t){this.beforeParseParsers.push(t)}},{key:"afterParse",value:function(t){this.afterParseParsers.push(t)}},{key:"parse",value:function(t,e){return this.beforeParseParsers.forEach(function(e){t=e(t)}),t=e(t),this.afterParseParsers.forEach(function(e){t=e(t)}),t}}]),t}(),a=new i,s=function(t){return a.beforeParse(t)},u=function(t){return a.afterParse(t)};e.c=a},function(t,e,n){"use strict";e.a=function(t){return t=t.replace(/<(?:.|\n)*?>/gm,"").replace(/[!\"#$%&'\(\)\*\+,\/:;<=>\?\@\[\\\]\^`\{\|\}~]/g,"").replace(/(\s|\.)/g,"-").replace(/-+/g,"-").toLowerCase(),/^[\d]+/.test(t)&&(t="_"+t),t}},function(t,e){t.exports=function(){for(var t=0;t<arguments.length;t++)if(void 0!==arguments[t])return arguments[t]}},function(t,e){t.exports={"custom-toc":"_13JmIB1emdpmGGUjth0wc2_0"}},function(t,e,n){"use strict";function r(t){if(null===t||void 0===t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}var o=Object.getOwnPropertySymbols,i=Object.prototype.hasOwnProperty,a=Object.prototype.propertyIsEnumerable;t.exports=function(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},n=0;n<10;n++)e["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(e).map(function(t){return e[t]}).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach(function(t){r[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(t){return!1}}()?Object.assign:function(t,e){for(var n,s,u=r(t),c=1;c<arguments.length;c++){n=Object(arguments[c]);for(var l in n)i.call(n,l)&&(u[l]=n[l]);if(o){s=o(n);for(var f=0;f<s.length;f++)a.call(n,s[f])&&(u[s[f]]=n[s[f]])}}return u}},function(t,e){t.exports='<svg id="i-link" viewBox="0 0 32 32" width="32" height="32" fill="none" stroke="currentcolor" stroke-linecap="round" stroke-linejoin="round" stroke-width="6.25%">\n <path d="M18 8 C18 8 24 2 27 5 30 8 29 12 24 16 19 20 16 21 14 17 M14 24 C14 24 8 30 5 27 2 24 3 20 8 16 13 12 16 11 18 15" />\n</svg>\n'},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r="function"==typeof fetch?fetch:function(t,e){return e=e||{},new Promise(function(n,r){function o(){var t,e=[],n=[],r={};return i.getAllResponseHeaders().replace(/^(.*?):\s*([\s\S]*?)$/gm,function(o,i,a){e.push(i=i.toLowerCase()),n.push([i,a]),t=r[i],r[i]=t?t+","+a:a}),{ok:1==(i.status/200|0),status:i.status,statusText:i.statusText,url:i.responseURL,clone:o,text:function(){return Promise.resolve(i.responseText)},json:function(){return Promise.resolve(i.responseText).then(JSON.parse)},xml:function(){return Promise.resolve(i.responseXML)},blob:function(){return Promise.resolve(new Blob([i.response]))},headers:{keys:function(){return e},entries:function(){return n},get:function(t){return r[t.toLowerCase()]},has:function(t){return t.toLowerCase()in r}}}}var i=new XMLHttpRequest;i.open(e.method||"get",t);for(var a in e.headers)i.setRequestHeader(a,e.headers[a]);i.withCredentials="include"==e.credentials,i.onload=function(){n(o())},i.onerror=r,i.send(e.body)})};e.default=r},function(t,e,n){function r(t){o||n(62)}var o=!1,i=n(0)(n(36),n(119),r,null,null);i.options.__file="/Users/egoist/dev/docute/src/components/HeaderIcons.vue",i.esModule&&Object.keys(i.esModule).some(function(t){return"default"!==t&&"__"!==t.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),i.options.functional&&console.error("[vue-loader] HeaderIcons.vue: functional components are not supported with templates, they should use render functions."),t.exports=i.exports},function(t,e,n){function r(t){o||n(70)}var o=!1,i=n(0)(n(37),n(126),r,null,null);i.options.__file="/Users/egoist/dev/docute/src/components/HeaderNav.vue",i.esModule&&Object.keys(i.esModule).some(function(t){return"default"!==t&&"__"!==t.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),i.options.functional&&console.error("[vue-loader] HeaderNav.vue: functional components are not supported with templates, they should use render functions."),t.exports=i.exports},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,e,n){"use strict";function r(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e<t.length;e++)n[e]=t[e];return n}return Array.from(t)}function o(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(b)throw new Error("You can only initialize Docute for once!");y.a.commit("SET_CONFIG",t),b=n.i(g.a)(t),y.a.state.config.debug&&(u.a.config.devtools=!0);for(var e=y.a.state.config.plugins||[],o=[].concat(r(f.a),r(e)),i=0;i<o.length;i++){var a=o[i];"function"==typeof a&&a({Vue:u.a,store:y.a,router:b,registerComponent:p.a,event:h.a,mapState:c.a,mapGetters:c.b,mapActions:c.c,mapMutations:c.d,beforeParse:d.a,afterParse:d.b})}n.i(l.sync)(y.a,b);var s=new u.a({store:y.a,router:b,render:function(t){return t(m.a)}});document.addEventListener("DOMContentLoaded",function(){s.$mount("#app")})}Object.defineProperty(e,"__esModule",{value:!0}),n.d(e,"version",function(){return _}),n.d(e,"router",function(){return b}),n.d(e,"init",function(){return o}),n.d(e,"isDev",function(){return w});var i=n(131),a=(n.n(i),n(97)),s=(n.n(a),n(51)),u=(n.n(s),n(12)),c=n(1),l=n(130),f=(n.n(l),n(27)),p=n(5),d=n(15),h=n(6),v=n(103),m=n.n(v),g=n(28),y=n(13);n.d(e,"store",function(){return y.a}),window.Vue=u.a;var b=void 0,_="3.4.7",w="localhost"===location.hostname},function(t,e,n){"use strict";var r=n(53),o=(n.n(r),n(17)),i=n.n(o);e.a=function(){return function(t){(0,t.registerComponent)("content:start",{name:"announcement",render:function(){var t=arguments[0],e=this.$store.state,n=e.config,r=e.page.attributes,o=i()(r.announcement,n.announcement);if(o){o="function"==typeof o?o(this.$route):o;var a=void 0,s=void 0;"string"==typeof o?s=o:(a=o.type,s=o.html);var u=["inner-2x","announcement"];return a&&u.push("announcement-"+a),t("div",{class:u,domProps:{innerHTML:s}},[])}}})}}},function(t,e,n){"use strict";var r=n(26);e.a=[n.i(r.a)()]},function(t,e,n){"use strict";var r=n(12),o=n(129),i=n(114),a=n.n(i),s=n(112),u=n.n(s),c=n(113),l=n.n(c);r.a.use(o.a),e.a=function(t){var e=t.landing,n=t.routerMode,r=[{path:e?"/home":"/",component:a.a,meta:{name:"home"}},{path:"/404",component:u.a,meta:{name:404}},{path:"/*",component:a.a,meta:{name:"page"}}];return e&&r.unshift({path:"/",component:l.a,meta:{name:"landing"}}),new o.a({mode:n,routes:r})}},function(t,e,n){"use strict";function r(t){t=t||"";var e=t.split(/(\r?\n)/);return e[0]&&/= yaml =|---/.test(e[0])?o(t):{attributes:{},body:t}}function o(t){var e=s.exec(t);if(!e)return{attributes:{},body:t};var r=e[e.length-1].replace(/^\s+|\s+$/g,"");return{attributes:n.i(i.a)(r)||{},body:t.replace(e[0],""),frontmatter:r}}var i=n(33),a="^(\\ufeff?(= yaml =|---)$([\\s\\S]*?)(?:\\2|\\.\\.\\.)$"+("win32"===n.i({env:n.i({NODE_ENV:"production"})}).platform?"\\r?":"")+"(?:\\n)?)",s=new RegExp(a,"m");e.a=r},function(t,e,n){"use strict";function r(t,e){return"function"==typeof l.a.state.config.highlight?l.a.state.config.highlight(t,e):i.a.highlight(t,i.a.languages[e]||i.a.languages.markup)}e.a=r;var o=n(79),i=n.n(o),a=n(78),s=(n.n(a),n(77)),u=(n.n(s),n(75)),c=(n.n(u),n(76)),l=(n.n(c),n(13))},function(t,e,n){"use strict";var r=n(74),o=n.n(r);n(4);e.a=function(t,e){o()("#"+t,{duration:300,a11y:!0,offset:-20,callback:e,container:".content-wrap"})}},function(t,e,n){"use strict";var r=n(10);e.a=new r.a.Renderer},function(t,e,n){"use strict";function r(t){return{parent:null,length:0,level:t,lines:[],children:[],addChild:function(t){this.children.push(t),t.parent=this,++this.length}}}function o(t){var e,n=v.regLevel,o=v.invalidLine,i=t.split("\n"),a=0,s=0,u=[],c=new r(-1),l=new r(0);c.addChild(l);var f=[],d="";u.push(l),f.push(a);for(var h=0,m=i.length;h<m;++h)if(d=i[h],!d.match(o)){if((a=(e=n.exec(d))?e[1].length:0)>s){var g=l;l=new r(a),g.addChild(l),u.push(l),f.push(a)}else if(a<s){for(var y=!1,b=f.length-1;b>=0;--b)if(f[b]==a){l=new r(a),u.push(l),f.push(a),null!=u[b].parent&&u[b].parent.addChild(l),y=!0;break}if(!y)return void p.push("Error: Invalid indentation at line "+h+": "+d)}l.lines.push(d.replace(v.trim,"")),s=a}return c}function i(t){t=t.replace(v.trim,"");var e=null;if("true"==t)return!0;if("false"==t)return!1;if(".NaN"==t)return Number.NaN;if("null"==t)return null;if(".inf"==t)return Number.POSITIVE_INFINITY;if("-.inf"==t)return Number.NEGATIVE_INFINITY;if(e=t.match(v.dashesString))return e[1];if(e=t.match(v.quotesString))return e[1];if(e=t.match(v.float))return parseFloat(e[0]);if(e=t.match(v.integer))return parseInt(e[0]);if(isNaN(e=Date.parse(t))){if(e=t.match(v.single_key_value)){var n={};return n[e[1]]=i(e[2]),n}if(e=t.match(v.array)){for(var r=0,o=" ",n=[],a="",s=!1,u=0,c=e[1].length;u<c;++u){if("'"==(o=e[1][u])||'"'==o){if(!1===s){s=o,a+=o;continue}if("'"==o&&"'"==s||'"'==o&&'"'==s){s=!1,a+=o;continue}}else if(!1!==s||"["!=o&&"{"!=o)if(!1!==s||"]"!=o&&"}"!=o){if(!1===s&&0==r&&","==o){n.push(i(a)),a="";continue}}else--r;else++r;a+=o}return a.length>0&&n.push(i(a)),n}if(e=t.match(v.map)){for(var r=0,o=" ",n=[],a="",s=!1,u=0,c=e[1].length;u<c;++u){if("'"==(o=e[1][u])||'"'==o){if(!1===s){s=o,a+=o;continue}if("'"==o&&"'"==s||'"'==o&&'"'==s){s=!1,a+=o;continue}}else if(!1!==s||"["!=o&&"{"!=o)if(!1!==s||"]"!=o&&"}"!=o){if(!1===s&&0==r&&","==o){n.push(a),a="";continue}}else--r;else++r;a+=o}a.length>0&&n.push(a);for(var l={},u=0,c=n.length;u<c;++u)(e=n[u].match(v.key_value))&&(l[e[1]]=i(e[2]));return l}return t}return new Date(e)}function a(t){for(var e=t.lines,n=t.children,r=e.join(" "),o=[r],i=0,s=n.length;i<s;++i)o.push(a(n[i]));return o.join("\n")}function s(t){for(var e=t.lines,n=t.children,r=e.join("\n"),o=0,i=n.length;o<i;++o)r+=s(n[o]);return r}function u(t){for(var e=null,n={},r=null,o=null,c=null,l=-1,f=[],h=!0,m=0,g=t.length;m<g;++m)if(-1==l||l==t[m].level){f.push(m),l=t[m].level,r=t[m].lines,o=t[m].children,c=null;for(var y=0,b=r.length;y<b;++y){var _=r[y];if(e=_.match(v.key)){var w=e[1];if("-"==w[0]&&(w=w.replace(v.item,""),h&&(h=!1,void 0===n.length&&(n=[])),null!=c&&n.push(c),c={},h=!0),void 0!==e[2]){var x=e[2].replace(v.trim,"");if("&"==x[0]){var k=u(o);null!=c?c[w]=k:n[w]=k,d[x.substr(1)]=k}else if("|"==x[0])null!=c?c[w]=s(o.shift()):n[w]=s(o.shift());else if("*"==x[0]){var $=x.substr(1),C={};if(void 0===d[$])p.push("Reference '"+$+"' not found!");else{for(var O in d[$])C[O]=d[$][O];null!=c?c[w]=C:n[w]=C}}else">"==x[0]?null!=c?c[w]=a(o.shift()):n[w]=a(o.shift()):null!=c?c[w]=i(x):n[w]=i(x)}else null!=c?c[w]=u(o):n[w]=u(o)}else{if(_.match(/^-\s*$/)){h&&(h=!1,void 0===n.length&&(n=[])),null!=c&&n.push(c),c={},h=!0;continue}if(e=_.match(/^-\s*(.*)/)){null!=c?c.push(i(e[1])):(h&&(h=!1,void 0===n.length&&(n=[])),n.push(i(e[1])));continue}}}null!=c&&(h&&(h=!1,void 0===n.length&&(n=[])),n.push(c))}for(var m=f.length-1;m>=0;--m)t.splice.call(t,f[m],1);return n}function c(t){return u(t.children)}function l(t){var e,n=t.split("\n"),r=v.comment;for(var o in n)(e=n[o].match(r))&&void 0!==e[3]&&(n[o]=e[0].substr(0,e[0].length-e[3].length));return n.join("\n")}function f(t){p=[],d=[],h=(new Date).getTime();var e=l(t),n=o(e),r=c(n);return h=(new Date).getTime()-h,r}var p=[],d=[],h=0,v={regLevel:new RegExp("^([\\s\\-]+)"),invalidLine:new RegExp("^\\-\\-\\-|^\\.\\.\\.|^\\s*#.*|^\\s*$"),dashesString:new RegExp('^\\s*\\"([^\\"]*)\\"\\s*$'),quotesString:new RegExp("^\\s*\\'([^\\']*)\\'\\s*$"),float:new RegExp("^[+-]?[0-9]+\\.[0-9]+(e[+-]?[0-9]+(\\.[0-9]+)?)?$"),integer:new RegExp("^[+-]?[0-9]+$"),array:new RegExp("\\[\\s*(.*)\\s*\\]"),map:new RegExp("\\{\\s*(.*)\\s*\\}"),key_value:new RegExp("([a-z0-9_-][ a-z0-9_-]*):( .+)","i"),single_key_value:new RegExp("^([a-z0-9_-][ a-z0-9_-]*):( .+?)$","i"),key:new RegExp("([a-z0-9_-][ a-z0-9_-]+):( .+)?","i"),item:new RegExp("^-\\s+"),trim:new RegExp("^\\s+|\\s+$"),comment:new RegExp("([^\\'\\\"#]+([\\'\\\"][^\\'\\\"]*[\\'\\\"])*)*(#.*)?")};e.a=f},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1),o=n(4),i=n(49),a=n.n(i);e.default={name:"app",computed:Object.assign({},n.i(r.a)(["jumping","config","activeId"])),mounted:function(){var t=this;this.detectClick(),this.$watch("activeId",function(){if(t.$store.state.config.syncTocPosition){var e=n.i(o.a)(".sidebar-heading-anchor.active");e&&(e.scrollIntoViewIfNeeded?e.scrollIntoViewIfNeeded():a()(e,n.i(o.a)(".sidebar"),{onlyScrollIfNeeded:!0,offsetBottom:100}))}})},methods:Object.assign({},n.i(r.c)(["jumpToId"]),{detectClick:function(){var t=this;document.addEventListener("click",function(e){t.handleNavigateAttribute(e)})},handleNavigateAttribute:function(t){var e=t.target.closest("[jump-to-id]"),n=e&&e.getAttribute("jump-to-id");if(n)return t.preventDefault(),this.$router.push({query:Object.assign({},this.$route.query,{id:n})}),this.jumpToId(n);var r=t.target.closest("[router-link]"),o=r&&r.getAttribute("router-link");return o?(t.preventDefault(),this.$router.push(o)):void 0}})}},function(t,e,n){"use strict";function r(t){return function(){var e=t.apply(this,arguments);return new Promise(function(t,n){function r(o,i){try{var a=e[o](i),s=a.value}catch(t){return void n(t)}if(!a.done)return Promise.resolve(s).then(function(t){r("next",t)},function(t){r("throw",t)});t(s)}return r("next")})}}Object.defineProperty(e,"__esModule",{value:!0});var o=n(7),i=n.n(o),a=n(14);e.default={props:{toc:{type:[String,Object],required:!0}},data:function(){return{content:{}}},created:function(){this.fetchResource()},methods:{fetchResource:function(){function t(){return e.apply(this,arguments)}var e=r(i.a.mark(function t(){return i.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,n.i(a.a)(this.toc,{progress:!1,componentName:"custom-toc-content",marked:{context:{path:this.$route.path,routerMode:this.$router.mode}}});case 2:this.content=t.sent;case 3:case"end":return t.stop()}},t,this)}));return t}()}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(3),o=n(4);e.default={props:{currentIcons:{type:Array,default:function(){return[]}},showNav:{type:Boolean}},methods:{hintPosition:function(t){return(this.showNav||o.b)&&t===this.currentIcons.length-1?"hint--bottom-left":"hint--bottom"}},components:{SvgIcon:r.a}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(3),o=n(107),i=n.n(o),a=n(8);e.default={props:{currentNav:{type:Array,default:function(){return[]}},hasNav:{type:Boolean},showNav:{type:Boolean}},methods:{getTitle:function(t){var e=this,n=t.items,r=n.filter(function(t){return t.matchPath&&t.matchPath.test(e.$route.path)})[0];return r?r.title:t.title}},components:{SvgIcon:r.a,NavLink:i.a,CustomComponents:a.a}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1),o=n(23),i=n.n(o),a=n(22),s=n.n(a),u=n(8),c=n(5);e.default={props:{currentIcons:{type:Array},hasNav:{type:Boolean},showNav:{type:Boolean}},computed:Object.assign({},n.i(r.b)(["currentNav"]),{hasComponentsAroundIcons:function(){return c.b.count("icons:start")>0||c.b.count("icons:end")>0}}),components:{HeaderNav:i.a,HeaderIcons:s.a,CustomComponents:u.a}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1),o=n(22),i=n.n(o),a=n(3),s=n(4);e.default={props:{currentIcons:{type:Array,default:function(){return[]}}},computed:Object.assign({},n.i(r.a)(["config","showMobileSidebar"])),mounted:function(){var t=this;this.$watch("showMobileSidebar",function(){var e=t.$refs.icon,r=n.i(s.a)(".sidebar");r.classList.contains("visible")?(r.classList.remove("visible"),e.style.color="#999"):(r.classList.add("visible"),e.style.color="#333")}),document.addEventListener("click",function(e){var r=t.$refs.header,o=n.i(s.a)(".sidebar");s.b&&r&&!o.contains(e.target)&&!r.contains(e.target)&&t.toggleMobileSidebar(!1)})},methods:Object.assign({},n.i(r.c)(["toggleMobileSidebar"])),components:{HeaderIcons:i.a,SvgIcon:a.a}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default={props:{item:{required:!0}},methods:{isExternal:function(t){return/^https?:\/\//.test(t)}}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1),o=n(3);e.default={data:function(){return{keyword:this.$route.query.keyword||"",focus:!1,debouncedURLChange:setTimeout(function(){},0)}},mounted:function(){var t=this;this.search(this.keyword),this.$watch("searchKeyword",function(e){t.keyword=e})},computed:Object.assign({},n.i(r.a)(["config","searchKeyword","searchState"])),methods:Object.assign({},n.i(r.c)(["search","updateSearchKeyword","searchReset"]),{handleSearch:function(t){var e=this;clearTimeout(this.debouncedURLChange),t!==this.$route.query.keyword&&(this.debouncedURLChange=setTimeout(function(){e.$router.push({query:Object.assign({},e.$route.query,{keyword:t})})},700)),this.search(t)},toggleFocus:function(){this.focus=!this.focus},handleClear:function(){this.searchReset(),this.keyword="",this.$refs.input.focus()}}),components:{SvgIcon:o.a}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1);e.default={computed:Object.assign({},n.i(r.a)(["pluginSearch","searchState"]),n.i(r.a)({searchResult:function(t){return t.searchResult.filter(function(t){return Boolean(t.title)||Boolean(t.content)})}})),methods:Object.assign({},n.i(r.c)(["jumpToId"]),{handleClick:function(t){var e=t.path,n=t.id;e===this.$route.path&&this.jumpToId(n),this.$router.push({path:e,query:Object.assign({},this.$route.query,{id:n})})},isActive:function(t){return t.path===this.$route.path&&t.id===this.$route.query.id}})}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(3),o=n(1);e.default={methods:Object.assign({},n.i(o.c)(["toggleSidebar"])),components:{SvgIcon:r.a}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1);e.default={props:{headings:{type:Array,required:!0}},computed:Object.assign({},n.i(r.a)(["activeId","config"]),{visibleBlockIndexes:function(){var t=this;if(!this.activeId)return[];var e=[],n=this.headings.filter(function(e){return t.activeId===e.slug})[0];if(!n)return[];e.push(n.index);var r=this.headings[n.index];return r&&function n(r){e.push(r.parent);var o=t.headings.filter(function(t){return t.index===r.parent})[0];o&&n(o)}(r),e.filter(function(t){return t>=0})}}),methods:Object.assign({},n.i(r.c)(["jumpToId"]),{getQuery:function(t){return Object.assign({},this.$route.query,{id:t.slug})},hasChildren:function(t){return this.headings.filter(function(e){return e.parent===t}).length>0},isVisible:function(t,e){return t<=(this.config.tocVisibleDepth||4)||-1!==this.visibleBlockIndexes.indexOf(e)},navigate:function(t){this.jumpToId(t)}})}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(11),o=n.n(r);e.default={name:"not-found",data:function(){return{from:null}},beforeRouteEnter:function(t,e,n){n(function(t){t.from=e})},mounted:function(){o.a.done()}}},function(t,e,n){"use strict";function r(t){return function(){var e=t.apply(this,arguments);return new Promise(function(t,n){function r(o,i){try{var a=e[o](i),s=a.value}catch(t){return void n(t)}if(!a.done)return Promise.resolve(s).then(function(t){r("next",t)},function(t){r("throw",t)});t(s)}return r("next")})}}Object.defineProperty(e,"__esModule",{value:!0});var o=n(7),i=n.n(o),a=n(1),s=n(14),u=n(6);e.default={name:"landing",data:function(){return{content:{html:null,component:null}}},computed:Object.assign({},n.i(a.a)(["config"])),created:function(){this.fetchLanding()},methods:{fetchLanding:function(){function t(){return e.apply(this,arguments)}var e=r(i.a.mark(function t(){return i.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,n.i(s.a)(this.config.landing,{fallback:"landing.html",componentName:"custom-landing",marked:{context:{path:this.$route.path,routerMode:this.$router.mode}}});case 2:this.content=t.sent,this.$nextTick(function(){return u.a.emit("landing:updated")});case 4:case"end":return t.stop()}},t,this)}));return t}()}}},function(t,e,n){"use strict";function r(t){return function(){var e=t.apply(this,arguments);return new Promise(function(t,n){function r(o,i){try{var a=e[o](i),s=a.value}catch(t){return void n(t)}if(!a.done)return Promise.resolve(s).then(function(t){r("next",t)},function(t){r("throw",t)});t(s)}return r("next")})}}function o(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e<t.length;e++)n[e]=t[e];return n}return Array.from(t)}Object.defineProperty(e,"__esModule",{value:!0});var i=n(7),a=n.n(i),s=n(98),u=n.n(s),c=n(105),l=n.n(c),f=n(106),p=n.n(f),d=n(23),h=n.n(d),v=n(111),m=n.n(v),g=n(108),y=n.n(g),b=n(109),_=n.n(b),w=n(110),x=n.n(w),k=n(8),$=n(104),C=n.n($),O=n(30),S=n(29),A=n(1),j=n(11),E=n.n(j),T=n(95),P=n.n(T),L=n(4),N=n(10),I=n(32),M=n(20),R=n.n(M),D=n(16),q=n(6),F=n(9),U=n(5),H=n(15);N.a.setOptions({highlight:function(t,e){if("markdown"===e){var r=n.i(S.a)(t),o=n.i(O.a)(r.body,"markdown");if(!r.frontmatter)return o;return'<span class="token comment">---</span>\n'+n.i(O.a)(r.frontmatter,"yaml")+'\n<span class="token comment">---</span>\n'+o}return n.i(O.a)(t,e)}}),e.default={name:"page",data:function(){return{isMobile:L.b}},created:function(){this.toggleMobileSidebar(!1),this.fetchData()},mounted:function(){var t=this;this.$watch("$route.path",function(){return t.fetchData()}),q.a.on("reload",function(){return t.fetchData()}),this.scrollSpy()},computed:Object.assign({},n.i(A.a)({id:function(t){return t.route.query.id}}),n.i(A.a)(["config","page","loaded","jumping","activeId","pluginSearch","searchResult","searchKeyword"]),n.i(A.b)(["documentTitle","showSidebar","currentNav","showToc","showCustomToc","currentNavItem"]),{currentNavSource:function(){var t=this.$route,e=this.config,n=this.currentNavItem&&this.currentNavItem.source,r=t.meta&&"home"===t.meta.name&&(e.home||"./README.md"),o=/\/$/.test(t.path)?"."+t.path+"README.md":"."+t.path+".md",i=n||r||o;return/^https?:\/\//.test(i)?i:u()(e.url||".",i)},currentIcons:function(){var t=this.$store.state,e=[],r=t.config,o=r.disableDefaultIcons,i=r.icons,a=void 0===i?[]:i,s=r["edit-link"],c=r.repo,l=r.twitter,f=t.page.attributes;if(!o){if(s){var p=/^https?:\/\//.test(this.currentNavSource),d=p?this.currentNavSource:u()(s,this.currentNavSource);e.push({link:d,label:p?"View page source":"Edit this page",icon:"edit"})}c&&e.push({link:"https://github.com/"+c,label:"Star me on GitHub",icon:"github"}),l&&e.push({link:"https://twitter.com/"+l,label:"Follow me on Twitter",icon:"twitter"})}var h=void 0;return h=n.i(F.b)(a,"Object")&&f?a[f.icons]||a.default:a.default||a,e.concat(h)},hasNav:function(){return this.currentNav&&this.currentNav.length>0},showNav:function(){var t=U.b.count("nav:start")>0,e=U.b.count("nav:end")>0;return this.hasNav||t||e},docComponent:function(){if(this.currentNavItemComponent)return Object.assign({name:"custom-page"},this.currentNavItemComponent,{template:'<div class="doc-component markdown-body content">'+this.page.html+"</div>"})},currentNavItemComponent:function(){return this.currentNavItem&&this.currentNavItem.component}}),methods:Object.assign({},n.i(A.c)(["updatePage","toggleMobileSidebar","jumpToId","updateActiveId"]),{scrollSpy:function(){var t=this,e=function(){var e=t.$route.meta&&t.$route.meta.name,r=["home","page"].indexOf(e)>-1,i=n.i(L.c)(".markdown-toc-heading");if(!t.jumping&&r&&0!==i.length){var a=[].concat(o(i)).map(function(t){return{top:t.getBoundingClientRect().top,id:t.id}}),s=n.i(F.c)(a.filter(function(t){return t.top<0}),"top")[0],u=n.i(F.d)(a.filter(function(t){return t.top>0}),"top")[0],c={};c=s&&u&&u.top>100?s:u||a[a.length-1],c.id&&t.updateActiveId(c.id)}};this.$refs.contentWrap.addEventListener("scroll",P()(e,300))},fetchData:function(){function t(){return e.apply(this,arguments)}var e=r(a.a.mark(function t(){var e,r,o,i,s=this;return a.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(E.a.start(),e=[],I.a.heading=function(t,r){var o=e.length,i=s.config.slugify?s.config.slugify(t):n.i(D.a)(t),a=i,u=e.filter(function(t){return t.directSlug===i});return u.length>0&&(a+=u.length),1!==r&&e.push({level:r,text:t,slug:a,directSlug:i,index:o}),"<h"+r+' id="'+a+'" class="'+(1===r?"markdown-heading":"markdown-heading markdown-toc-heading")+'">\n '+(1===r?"":' <span class="anchor" jump-to-id="'+a+'">'+R.a+"</span>")+"\n "+t+"\n </h"+r+">"},r=void 0,!this.currentNavItem||!this.currentNavItem.markdown){t.next=8;break}r=this.currentNavItem.markdown,t.next=18;break;case 8:return t.next=10,fetch(this.currentNavSource,{credentials:n.i(F.a)(this.currentNavSource)});case 10:if(o=t.sent,E.a.inc(),404!==o.status){t.next=15;break}return this.$router.replace("/404"),t.abrupt("return");case 15:return t.next=17,o.text();case 17:r=t.sent;case 18:i=n.i(S.a)(r),N.a.setOptions(Object.assign({},this.config.marked,{renderer:I.a,context:{path:this.$route.path,routerMode:this.$router.mode}})),this.updatePage({html:H.c.parse(i.body,N.a),attributes:i.attributes,headings:this.handleRelation(e)}),document.title=this.documentTitle,setTimeout(function(){E.a.done(),q.a.emit("content:updated",s),s.id?s.jumpToId(s.id):s.$refs.contentWrap.scrollTop=0,s.$refs.sidebar&&(s.$refs.sidebar.scrollTop=0)});case 23:case"end":return t.stop()}},t,this)}));return t}(),handleRelation:function(t){function e(e,n){var r=t.slice(0,n).filter(function(t){return t.level===e}),o=r[r.length-1];return o&&o.index}return t.map(function(t,n){return t.level>2&&(t.parent=e(t.level-1,n)),t})}}),components:{HomeHeader:l.a,MobileHeader:p.a,Toc:m.a,HeaderNav:h.a,SearchBox:y.a,SearchResult:_.a,SidebarToggle:x.a,CustomComponents:k.a,CustomToc:C.a}}},function(t,e,n){"use strict";function r(t,e,n){n=n||{},9===e.nodeType&&(e=o.getWindow(e));var r=n.allowHorizontalScroll,i=n.onlyScrollIfNeeded,a=n.alignWithTop,s=n.alignWithLeft,u=n.offsetTop||0,c=n.offsetLeft||0,l=n.offsetBottom||0,f=n.offsetRight||0;r=void 0===r||r;var p=o.isWindow(e),d=o.offset(t),h=o.outerHeight(t),v=o.outerWidth(t),m=void 0,g=void 0,y=void 0,b=void 0,_=void 0,w=void 0,x=void 0,k=void 0,$=void 0,C=void 0;p?(x=e,C=o.height(x),$=o.width(x),k={left:o.scrollLeft(x),top:o.scrollTop(x)},_={left:d.left-k.left-c,top:d.top-k.top-u},w={left:d.left+v-(k.left+$)+f,top:d.top+h-(k.top+C)+l},b=k):(m=o.offset(e),g=e.clientHeight,y=e.clientWidth,b={left:e.scrollLeft,top:e.scrollTop},_={left:d.left-(m.left+(parseFloat(o.css(e,"borderLeftWidth"))||0))-c,top:d.top-(m.top+(parseFloat(o.css(e,"borderTopWidth"))||0))-u},w={left:d.left+v-(m.left+y+(parseFloat(o.css(e,"borderRightWidth"))||0))+f,top:d.top+h-(m.top+g+(parseFloat(o.css(e,"borderBottomWidth"))||0))+l}),_.top<0||w.top>0?!0===a?o.scrollTop(e,b.top+_.top):!1===a?o.scrollTop(e,b.top+w.top):_.top<0?o.scrollTop(e,b.top+_.top):o.scrollTop(e,b.top+w.top):i||(a=void 0===a||!!a,a?o.scrollTop(e,b.top+_.top):o.scrollTop(e,b.top+w.top)),r&&(_.left<0||w.left>0?!0===s?o.scrollLeft(e,b.left+_.left):!1===s?o.scrollLeft(e,b.left+w.left):_.left<0?o.scrollLeft(e,b.left+_.left):o.scrollLeft(e,b.left+w.left):i||(s=void 0===s||!!s,s?o.scrollLeft(e,b.left+_.left):o.scrollLeft(e,b.left+w.left)))}var o=n(50);t.exports=r},function(t,e,n){"use strict";t.exports=n(48)},function(t,e,n){"use strict";function r(t){var e=void 0,n=void 0,r=void 0,o=t.ownerDocument,i=o.body,a=o&&o.documentElement;return e=t.getBoundingClientRect(),n=e.left,r=e.top,n-=a.clientLeft||i.clientLeft||0,r-=a.clientTop||i.clientTop||0,{left:n,top:r}}function o(t,e){var n=t["page"+(e?"Y":"X")+"Offset"],r="scroll"+(e?"Top":"Left");if("number"!=typeof n){var o=t.document;n=o.documentElement[r],"number"!=typeof n&&(n=o.body[r])}return n}function i(t){return o(t)}function a(t){return o(t,!0)}function s(t){var e=r(t),n=t.ownerDocument,o=n.defaultView||n.parentWindow;return e.left+=i(o),e.top+=a(o),e}function u(t,e,n){var r="",o=t.ownerDocument,i=n||o.defaultView.getComputedStyle(t,null);return i&&(r=i.getPropertyValue(e)||i[e]),r}function c(t,e){var n=t[$]&&t[$][e];if(x.test(n)&&!k.test(e)){var r=t.style,o=r[O],i=t[C][O];t[C][O]=t[$][O],r[O]="fontSize"===e?"1em":n||0,n=r.pixelLeft+S,r[O]=o,t[C][O]=i}return""===n?"auto":n}function l(t,e){for(var n=0;n<t.length;n++)e(t[n])}function f(t){return"border-box"===A(t,"boxSizing")}function p(t,e,n){var r={},o=t.style,i=void 0;for(i in e)e.hasOwnProperty(i)&&(r[i]=o[i],o[i]=e[i]);n.call(t);for(i in e)e.hasOwnProperty(i)&&(o[i]=r[i])}function d(t,e,n){var r=0,o=void 0,i=void 0,a=void 0;for(i=0;i<e.length;i++)if(o=e[i])for(a=0;a<n.length;a++){var s=void 0;s="border"===o?o+n[a]+"Width":o+n[a],r+=parseFloat(A(t,s))||0}return r}function h(t){return null!=t&&t==t.window}function v(t,e,n){if(h(t))return"width"===e?L.viewportWidth(t):L.viewportHeight(t);if(9===t.nodeType)return"width"===e?L.docWidth(t):L.docHeight(t);var r="width"===e?["Left","Right"]:["Top","Bottom"],o="width"===e?t.offsetWidth:t.offsetHeight,i=A(t),a=f(t,i),s=0;(null==o||o<=0)&&(o=void 0,s=A(t,e),(null==s||Number(s)<0)&&(s=t.style[e]||0),s=parseFloat(s)||0),void 0===n&&(n=a?P:E);var u=void 0!==o||a,c=o||s;if(n===E)return u?c-d(t,["border","padding"],r,i):s;if(u){var l=n===T?-d(t,["border"],r,i):d(t,["margin"],r,i);return c+(n===P?0:l)}return s+d(t,j.slice(n),r,i)}function m(t){var e=void 0,n=arguments;return 0!==t.offsetWidth?e=v.apply(void 0,n):p(t,N,function(){e=v.apply(void 0,n)}),e}function g(t,e,n){var r=n;{if("object"!==(void 0===e?"undefined":_(e)))return void 0!==r?("number"==typeof r&&(r+="px"),void(t.style[e]=r)):A(t,e);for(var o in e)e.hasOwnProperty(o)&&g(t,o,e[o])}}function y(t,e){"static"===g(t,"position")&&(t.style.position="relative");var n=s(t),r={},o=void 0,i=void 0;for(i in e)e.hasOwnProperty(i)&&(o=parseFloat(g(t,i))||0,r[i]=o+e[i]-n[i]);g(t,r)}var b=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t},_="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol?"symbol":typeof t},w=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,x=new RegExp("^("+w+")(?!px)[a-z%]+$","i"),k=/^(top|right|bottom|left)$/,$="currentStyle",C="runtimeStyle",O="left",S="px",A=void 0;"undefined"!=typeof window&&(A=window.getComputedStyle?u:c);var j=["margin","border","padding"],E=-1,T=2,P=1,L={};l(["Width","Height"],function(t){L["doc"+t]=function(e){var n=e.document;return Math.max(n.documentElement["scroll"+t],n.body["scroll"+t],L["viewport"+t](n))},L["viewport"+t]=function(e){var n="client"+t,r=e.document,o=r.body,i=r.documentElement,a=i[n];return"CSS1Compat"===r.compatMode&&a||o&&o[n]||a}});var N={position:"absolute",visibility:"hidden",display:"block"};l(["width","height"],function(t){var e=t.charAt(0).toUpperCase()+t.slice(1);L["outer"+e]=function(e,n){return e&&m(e,t,n?0:P)};var n="width"===t?["Left","Right"]:["Top","Bottom"];L[t]=function(e,r){if(void 0===r)return e&&m(e,t,E);if(e){var o=A(e);return f(e)&&(r+=d(e,["padding","border"],n,o)),g(e,t,r)}}}),t.exports=b({getWindow:function(t){var e=t.ownerDocument||t;return e.defaultView||e.parentWindow},offset:function(t,e){if(void 0===e)return s(t);y(t,e)},isWindow:h,each:l,css:g,clone:function(t){var e={};for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);if(t.overflow)for(var n in t)t.hasOwnProperty(n)&&(e.overflow[n]=t.overflow[n]);return e},scrollLeft:function(t,e){if(h(t)){if(void 0===e)return i(t);window.scrollTo(e,a(t))}else{if(void 0===e)return t.scrollLeft;t.scrollLeft=e}},scrollTop:function(t,e){if(h(t)){if(void 0===e)return a(t);window.scrollTo(i(t),e)}else{if(void 0===e)return t.scrollTop;t.scrollTop=e}},viewportWidth:0,viewportHeight:0},L)},function(t,e){(function(t){"function"!=typeof t.matches&&(t.matches=t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||function(t){for(var e=this,n=(e.document||e.ownerDocument).querySelectorAll(t),r=0;n[r]&&n[r]!==e;)++r;return Boolean(n[r])}),"function"!=typeof t.closest&&(t.closest=function(t){for(var e=this;e&&1===e.nodeType;){if(e.matches(t))return e;e=e.parentNode}return null})})(window.Element.prototype)},function(t,e,n){(function(e,n){t.exports=n()})(0,function(){"use strict";function t(){function t(t){return i[t]||(i[t]=[])}function e(e,n){return t(e).push(n),function(){return r(e,n)}}function n(t,n){var o=function(){for(var e=[],i=arguments.length;i--;)e[i]=arguments[i];r(t,o),n.apply(void 0,e)};return e(t,o)}function r(e,n){var r=t(e),o=r.indexOf(n);-1!==o&&r.splice(o,1)}function o(e){for(var n=[],r=arguments.length-1;r-- >0;)n[r]=arguments[r+1];for(var o=0,i=t("*");o<i.length;o+=1){i[o].apply(void 0,[e].concat(n))}for(var a=0,s=t(e);a<s.length;a+=1){s[a].apply(void 0,n)}}var i={};return{on:e,off:r,once:n,emit:o}}return t})},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e){},function(t,e,n){(function(e,n){t.exports=n()})(0,function(){"use strict";var t=function(t,e,n,r){return(t/=r/2)<1?n/2*t*t+e:(t--,-n/2*(t*(t-2)-1)+e)};return function(){function e(){return s.scrollY||s.pageYOffset||s.scrollTop||0}function n(t){return t.getBoundingClientRect().top-(s.getBoundingClientRect?s.getBoundingClientRect().top:0)+c}function r(t){s.scrollTo?s.scrollTo(0,t):s.scrollTop=t}function o(t){m||(m=t),g=t-m,y=p(g,c,h,v),r(y),g<v?window.requestAnimationFrame(o):i()}function i(){r(c+h),u&&d&&(u.setAttribute("tabindex","-1"),u.focus()),"function"==typeof b&&b(),m=!1}function a(r,i){switch(void 0===i&&(i={}),v=i.duration||1e3,f=i.offset||0,b=i.callback,p=i.easing||t,d=i.a11y||!1,typeof i.container){case"object":s=i.container;break;case"string":s=document.querySelector(i.container);break;default:s=window}switch(c=e(),typeof r){case"number":u=void 0,d=!1,l=c+r;break;case"object":u=r,l=n(u);break;case"string":u=document.querySelector(r),l=n(u)}switch(h=l-c+f,typeof i.duration){case"number":v=i.duration;break;case"function":v=i.duration(h)}window.requestAnimationFrame(o)}var s,u,c,l,f,p,d,h,v,m,g,y,b;return a}()})},function(t,e){(function(t){var e={variable:[{pattern:/\$?\(\([\w\W]+?\)\)/,inside:{variable:[{pattern:/(^\$\(\([\w\W]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b-?(?:0x[\dA-Fa-f]+|\d*\.?\d+(?:[Ee]-?\d+)?)\b/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\([^)]+\)|`[^`]+`/,inside:{variable:/^\$\(|^`|\)$|`$/}},/\$(?:[a-z0-9_#\?\*!@]+|\{[^}]+\})/i]};t.languages.bash={shebang:{pattern:/^#!\s*\/bin\/bash|^#!\s*\/bin\/sh/,alias:"important"},comment:{pattern:/(^|[^"{\\])#.*/,lookbehind:!0},string:[{pattern:/((?:^|[^<])<<\s*)(?:"|')?(\w+?)(?:"|')?\s*\r?\n(?:[\s\S])*?\r?\n\2/g,lookbehind:!0,greedy:!0,inside:e},{pattern:/(["'])(?:\\\\|\\?[^\\])*?\1/g,greedy:!0,inside:e}],variable:e.variable,function:{pattern:/(^|\s|;|\||&)(?:alias|apropos|apt-get|aptitude|aspell|awk|basename|bash|bc|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chmod|chown|chroot|chkconfig|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|cut|date|dc|dd|ddrescue|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|ethtool|eval|exec|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|grep|groupadd|groupdel|groupmod|groups|gzip|hash|head|help|hg|history|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|jobs|join|kill|killall|less|link|ln|locate|logname|logout|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|make|man|mkdir|mkfifo|mkisofs|mknod|more|most|mount|mtools|mtr|mv|mmv|nano|netstat|nice|nl|nohup|notify-send|npm|nslookup|open|op|passwd|paste|pathchk|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|rename|renice|remsync|rev|rm|rmdir|rsync|screen|scp|sdiff|sed|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|sync|tail|tar|tee|test|time|timeout|times|touch|top|traceroute|trap|tr|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|uptime|useradd|userdel|usermod|users|uuencode|uudecode|v|vdir|vi|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yes|zip)(?=$|\s|;|\||&)/,lookbehind:!0},keyword:{pattern:/(^|\s|;|\||&)(?:let|:|\.|if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)(?=$|\s|;|\||&)/,lookbehind:!0},boolean:{pattern:/(^|\s|;|\||&)(?:true|false)(?=$|\s|;|\||&)/,lookbehind:!0},operator:/&&?|\|\|?|==?|!=?|<<<?|>>|<=?|>=?|=~/,punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];]/};var n=e.variable[1].inside;n.function=t.languages.bash.function,n.keyword=t.languages.bash.keyword,n.boolean=t.languages.bash.boolean,n.operator=t.languages.bash.operator,n.punctuation=t.languages.bash.punctuation})(Prism)},function(t,e){Prism.languages.json={property:/"(?:\\.|[^|"])*"(?=\s*:)/gi,string:/"(?!:)(?:\\.|[^|"])*"(?!:)/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee][+-]?\d+)?)\b/g,punctuation:/[{}[\]);,]/g,operator:/:/g,boolean:/\b(true|false)\b/gi,null:/\bnull\b/gi},Prism.languages.jsonp=Prism.languages.json},function(t,e){Prism.languages.markdown=Prism.languages.extend("markup",{}),Prism.languages.insertBefore("markdown","prolog",{blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},code:[{pattern:/^(?: {4}|\t).+/m,alias:"keyword"},{pattern:/``.+?``|`[^`\n]+`/,alias:"keyword"}],title:[{pattern:/\w+.*(?:\r?\n|\r)(?:==+|--+)/,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#+.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])([\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:/(^|[^\\])(\*\*|__)(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^\*\*|^__|\*\*$|__$/}},italic:{pattern:/(^|[^\\])([*_])(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^[*_]|[*_]$/}},url:{pattern:/!?\[[^\]]+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)| ?\[[^\]\n]*\])/,inside:{variable:{pattern:/(!?\[)[^\]]+(?=\]$)/,lookbehind:!0},string:{pattern:/"(?:\\.|[^"\\])*"(?=\)$)/}}}}),Prism.languages.markdown.bold.inside.url=Prism.util.clone(Prism.languages.markdown.url),Prism.languages.markdown.italic.inside.url=Prism.util.clone(Prism.languages.markdown.url),Prism.languages.markdown.bold.inside.italic=Prism.util.clone(Prism.languages.markdown.italic),Prism.languages.markdown.italic.inside.bold=Prism.util.clone(Prism.languages.markdown.bold)},function(t,e){Prism.languages.yaml={scalar:{pattern:/([\-:]\s*(![^\s]+)?[ \t]*[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)[^\r\n]+(?:\3[^\r\n]+)*)/,lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:/(\s*(?:^|[:\-,[{\r\n?])[ \t]*(![^\s]+)?[ \t]*)[^\r\n{[\]},#\s]+?(?=\s*:\s)/,lookbehind:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)(\d{4}-\d\d?-\d\d?([tT]|[ \t]+)\d\d?:\d{2}:\d{2}(\.\d*)?[ \t]*(Z|[-+]\d\d?(:\d{2})?)?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(:\d{2}(\.\d*)?)?)(?=[ \t]*($|,|]|}))/m,lookbehind:!0,alias:"number"},boolean:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)(true|false)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},null:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)(null|~)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},string:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')(?=[ \t]*($|,|]|}))/m,lookbehind:!0},number:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)[+\-]?(0x[\da-f]+|0o[0-7]+|(\d+\.?\d*|\.?\d+)(e[\+\-]?\d+)?|\.inf|\.nan)[ \t]*(?=$|,|]|})/im,lookbehind:!0},tag:/![^\s]+/,important:/[&*][\w]+/,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./}},function(t,e,n){(function(e){var n="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},r=function(){var t=/\blang(?:uage)?-(\w+)\b/i,e=0,r=n.Prism={util:{encode:function(t){return t instanceof o?new o(t.type,r.util.encode(t.content),t.alias):"Array"===r.util.type(t)?t.map(r.util.encode):t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\u00a0/g," ")},type:function(t){return Object.prototype.toString.call(t).match(/\[object (\w+)\]/)[1]},objId:function(t){return t.__id||Object.defineProperty(t,"__id",{value:++e}),t.__id},clone:function(t){switch(r.util.type(t)){case"Object":var e={};for(var n in t)t.hasOwnProperty(n)&&(e[n]=r.util.clone(t[n]));return e;case"Array":return t.map&&t.map(function(t){return r.util.clone(t)})}return t}},languages:{extend:function(t,e){var n=r.util.clone(r.languages[t]);for(var o in e)n[o]=e[o];return n},insertBefore:function(t,e,n,o){o=o||r.languages;var i=o[t];if(2==arguments.length){n=arguments[1];for(var a in n)n.hasOwnProperty(a)&&(i[a]=n[a]);return i}var s={};for(var u in i)if(i.hasOwnProperty(u)){if(u==e)for(var a in n)n.hasOwnProperty(a)&&(s[a]=n[a]);s[u]=i[u]}return r.languages.DFS(r.languages,function(e,n){n===o[t]&&e!=t&&(this[e]=s)}),o[t]=s},DFS:function(t,e,n,o){o=o||{};for(var i in t)t.hasOwnProperty(i)&&(e.call(t,i,t[i],n||i),"Object"!==r.util.type(t[i])||o[r.util.objId(t[i])]?"Array"!==r.util.type(t[i])||o[r.util.objId(t[i])]||(o[r.util.objId(t[i])]=!0,r.languages.DFS(t[i],e,i,o)):(o[r.util.objId(t[i])]=!0,r.languages.DFS(t[i],e,null,o)))}},plugins:{},highlightAll:function(t,e){var n={callback:e,selector:'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'};r.hooks.run("before-highlightall",n);for(var o,i=n.elements||document.querySelectorAll(n.selector),a=0;o=i[a++];)r.highlightElement(o,!0===t,n.callback)},highlightElement:function(e,o,i){for(var a,s,u=e;u&&!t.test(u.className);)u=u.parentNode;u&&(a=(u.className.match(t)||[,""])[1].toLowerCase(),s=r.languages[a]),e.className=e.className.replace(t,"").replace(/\s+/g," ")+" language-"+a,u=e.parentNode,/pre/i.test(u.nodeName)&&(u.className=u.className.replace(t,"").replace(/\s+/g," ")+" language-"+a);var c=e.textContent,l={element:e,language:a,grammar:s,code:c};if(r.hooks.run("before-sanity-check",l),!l.code||!l.grammar)return l.code&&(l.element.textContent=l.code),void r.hooks.run("complete",l);if(r.hooks.run("before-highlight",l),o&&n.Worker){var f=new Worker(r.filename);f.onmessage=function(t){l.highlightedCode=t.data,r.hooks.run("before-insert",l),l.element.innerHTML=l.highlightedCode,i&&i.call(l.element),r.hooks.run("after-highlight",l),r.hooks.run("complete",l)},f.postMessage(JSON.stringify({language:l.language,code:l.code,immediateClose:!0}))}else l.highlightedCode=r.highlight(l.code,l.grammar,l.language),r.hooks.run("before-insert",l),l.element.innerHTML=l.highlightedCode,i&&i.call(e),r.hooks.run("after-highlight",l),r.hooks.run("complete",l)},highlight:function(t,e,n){var i=r.tokenize(t,e);return o.stringify(r.util.encode(i),n)},tokenize:function(t,e,n){var o=r.Token,i=[t],a=e.rest;if(a){for(var s in a)e[s]=a[s];delete e.rest}t:for(var s in e)if(e.hasOwnProperty(s)&&e[s]){var u=e[s];u="Array"===r.util.type(u)?u:[u];for(var c=0;c<u.length;++c){var l=u[c],f=l.inside,p=!!l.lookbehind,d=!!l.greedy,h=0,v=l.alias;if(d&&!l.pattern.global){var m=l.pattern.toString().match(/[imuy]*$/)[0];l.pattern=RegExp(l.pattern.source,m+"g")}l=l.pattern||l;for(var g=0,y=0;g<i.length;y+=i[g].length,++g){var b=i[g];if(i.length>t.length)break t;if(!(b instanceof o)){l.lastIndex=0;var _=l.exec(b),w=1;if(!_&&d&&g!=i.length-1){if(l.lastIndex=y,!(_=l.exec(t)))break;for(var x=_.index+(p?_[1].length:0),k=_.index+_[0].length,$=g,C=y,O=i.length;$<O&&C<k;++$)C+=i[$].length,x>=C&&(++g,y=C);if(i[g]instanceof o||i[$-1].greedy)continue;w=$-g,b=t.slice(y,C),_.index-=y}if(_){p&&(h=_[1].length);var x=_.index+h,_=_[0].slice(h),k=x+_.length,S=b.slice(0,x),A=b.slice(k),j=[g,w];S&&j.push(S);var E=new o(s,f?r.tokenize(_,f):_,v,_,d);j.push(E),A&&j.push(A),Array.prototype.splice.apply(i,j)}}}}}return i},hooks:{all:{},add:function(t,e){var n=r.hooks.all;n[t]=n[t]||[],n[t].push(e)},run:function(t,e){var n=r.hooks.all[t];if(n&&n.length)for(var o,i=0;o=n[i++];)o(e)}}},o=r.Token=function(t,e,n,r,o){this.type=t,this.content=e,this.alias=n,this.length=0|(r||"").length,this.greedy=!!o};if(o.stringify=function(t,e,n){if("string"==typeof t)return t;if("Array"===r.util.type(t))return t.map(function(n){return o.stringify(n,e,t)}).join("");var i={type:t.type,content:o.stringify(t.content,e,n),tag:"span",classes:["token",t.type],attributes:{},language:e,parent:n};if("comment"==i.type&&(i.attributes.spellcheck="true"),t.alias){var a="Array"===r.util.type(t.alias)?t.alias:[t.alias];Array.prototype.push.apply(i.classes,a)}r.hooks.run("wrap",i);var s=Object.keys(i.attributes).map(function(t){return t+'="'+(i.attributes[t]||"").replace(/"/g,"&quot;")+'"'}).join(" ");return"<"+i.tag+' class="'+i.classes.join(" ")+'"'+(s?" "+s:"")+">"+i.content+"</"+i.tag+">"},!n.document)return n.addEventListener?(n.addEventListener("message",function(t){var e=JSON.parse(t.data),o=e.language,i=e.code,a=e.immediateClose;n.postMessage(r.highlight(i,r.languages[o],o)),a&&n.close()},!1),n.Prism):n.Prism;var i=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return i&&(r.filename=i.src,document.addEventListener&&!i.hasAttribute("data-manual")&&("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(r.highlightAll):window.setTimeout(r.highlightAll,16):document.addEventListener("DOMContentLoaded",r.highlightAll))),n.Prism}();void 0!==t&&t.exports&&(t.exports=r),void 0!==e&&(e.Prism=r),r.languages.markup={comment:/<!--[\w\W]*?-->/,prolog:/<\?[\w\W]+?\?>/,doctype:/<!DOCTYPE[\w\W]+?>/i,cdata:/<!\[CDATA\[[\w\W]*?]]>/i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i,inside:{punctuation:/[=>"']/}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},r.hooks.add("wrap",function(t){"entity"===t.type&&(t.attributes.title=t.content.replace(/&amp;/,"&"))}),r.languages.xml=r.languages.markup,r.languages.html=r.languages.markup,r.languages.mathml=r.languages.markup,r.languages.svg=r.languages.markup,r.languages.css={comment:/\/\*[\w\W]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*?(?=\s*\{)/,string:{pattern:/("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},r.languages.css.atrule.inside.rest=r.util.clone(r.languages.css),r.languages.markup&&(r.languages.insertBefore("markup","tag",{style:{pattern:/(<style[\w\W]*?>)[\w\W]*?(?=<\/style>)/i,lookbehind:!0,inside:r.languages.css,alias:"language-css"}}),r.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|').*?\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:r.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:r.languages.css}},alias:"language-css"}},r.languages.markup.tag)),r.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:{pattern:/(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(true|false)\b/,function:/[a-z0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/},r.languages.javascript=r.languages.extend("clike",{keyword:/\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,function:/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*\*?|\/|~|\^|%|\.{3}/}),r.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^\/])\/(?!\/)(\[.+?]|\\.|[^\/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0,greedy:!0}}),r.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\\\|\\?[^\\])*?`/,greedy:!0,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:r.languages.javascript}},string:/[\s\S]+/}}}),r.languages.markup&&r.languages.insertBefore("markup","tag",{script:{pattern:/(<script[\w\W]*?>)[\w\W]*?(?=<\/script>)/i,lookbehind:!0,inside:r.languages.javascript,alias:"language-javascript"}}),r.languages.js=r.languages.javascript,function(){"undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector&&(self.Prism.fileHighlight=function(){var t={js:"javascript",py:"python",rb:"ruby",ps1:"powershell",psm1:"powershell",sh:"bash",bat:"batch",h:"c",tex:"latex"};Array.prototype.forEach&&Array.prototype.slice.call(document.querySelectorAll("pre[data-src]")).forEach(function(e){for(var n,o=e.getAttribute("data-src"),i=e,a=/\blang(?:uage)?-(?!\*)(\w+)\b/i;i&&!a.test(i.className);)i=i.parentNode;if(i&&(n=(e.className.match(a)||[,""])[1]),!n){var s=(o.match(/\.(\w+)$/)||[,""])[1];n=t[s]||s}var u=document.createElement("code");u.className="language-"+n,e.textContent="",u.textContent="Loading…",e.appendChild(u);var c=new XMLHttpRequest;c.open("GET",o,!0),c.onreadystatechange=function(){4==c.readyState&&(c.status<400&&c.responseText?(u.textContent=c.responseText,r.highlightElement(u)):c.status>=400?u.textContent="✖ Error "+c.status+" while fetching file: "+c.statusText:u.textContent="✖ Error: File does not exist or is empty")},c.send(null)})},document.addEventListener("DOMContentLoaded",self.Prism.fileHighlight))}()}).call(e,n(2))},function(t,e,n){(function(e){(function(n){function r(){}function o(t,e){return function(){t.apply(e,arguments)}}function i(t){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof t)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],f(t,this)}function a(t,e){for(;3===t._state;)t=t._value;if(0===t._state)return void t._deferreds.push(e);t._handled=!0,i._immediateFn(function(){var n=1===t._state?e.onFulfilled:e.onRejected;if(null===n)return void(1===t._state?s:u)(e.promise,t._value);var r;try{r=n(t._value)}catch(t){return void u(e.promise,t)}s(e.promise,r)})}function s(t,e){try{if(e===t)throw new TypeError("A promise cannot be resolved with itself.");if(e&&("object"==typeof e||"function"==typeof e)){var n=e.then;if(e instanceof i)return t._state=3,t._value=e,void c(t);if("function"==typeof n)return void f(o(n,e),t)}t._state=1,t._value=e,c(t)}catch(e){u(t,e)}}function u(t,e){t._state=2,t._value=e,c(t)}function c(t){2===t._state&&0===t._deferreds.length&&i._immediateFn(function(){t._handled||i._unhandledRejectionFn(t._value)});for(var e=0,n=t._deferreds.length;e<n;e++)a(t,t._deferreds[e]);t._deferreds=null}function l(t,e,n){this.onFulfilled="function"==typeof t?t:null,this.onRejected="function"==typeof e?e:null,this.promise=n}function f(t,e){var n=!1;try{t(function(t){n||(n=!0,s(e,t))},function(t){n||(n=!0,u(e,t))})}catch(t){if(n)return;n=!0,u(e,t)}}var p=setTimeout;i.prototype.catch=function(t){return this.then(null,t)},i.prototype.then=function(t,e){var n=new this.constructor(r);return a(this,new l(t,e,n)),n},i.all=function(t){var e=Array.prototype.slice.call(t);return new i(function(t,n){function r(i,a){try{if(a&&("object"==typeof a||"function"==typeof a)){var s=a.then;if("function"==typeof s)return void s.call(a,function(t){r(i,t)},n)}e[i]=a,0==--o&&t(e)}catch(t){n(t)}}if(0===e.length)return t([]);for(var o=e.length,i=0;i<e.length;i++)r(i,e[i])})},i.resolve=function(t){return t&&"object"==typeof t&&t.constructor===i?t:new i(function(e){e(t)})},i.reject=function(t){return new i(function(e,n){n(t)})},i.race=function(t){return new i(function(e,n){for(var r=0,o=t.length;r<o;r++)t[r].then(e,n)})},i._immediateFn="function"==typeof e&&function(t){e(t)}||function(t){p(t,0)},i._unhandledRejectionFn=function(t){"undefined"!=typeof console&&console&&console.warn("Possible Unhandled Promise Rejection:",t)},i._setImmediateFn=function(t){i._immediateFn=t},i._setUnhandledRejectionFn=function(t){i._unhandledRejectionFn=t},void 0!==t&&t.exports?t.exports=i:n.Promise||(n.Promise=i)})(this)}).call(e,n(96).setImmediate)},function(t,e,n){(function(t,r){var o;(function(i){function a(t){throw new RangeError(P[t])}function s(t,e){for(var n=t.length,r=[];n--;)r[n]=e(t[n]);return r}function u(t,e){var n=t.split("@"),r="";return n.length>1&&(r=n[0]+"@",t=n[1]),t=t.replace(T,"."),r+s(t.split("."),e).join(".")}function c(t){for(var e,n,r=[],o=0,i=t.length;o<i;)e=t.charCodeAt(o++),e>=55296&&e<=56319&&o<i?(n=t.charCodeAt(o++),56320==(64512&n)?r.push(((1023&e)<<10)+(1023&n)+65536):(r.push(e),o--)):r.push(e);return r}function l(t){return s(t,function(t){var e="";return t>65535&&(t-=65536,e+=I(t>>>10&1023|55296),t=56320|1023&t),e+=I(t)}).join("")}function f(t){return t-48<10?t-22:t-65<26?t-65:t-97<26?t-97:w}function p(t,e){return t+22+75*(t<26)-((0!=e)<<5)}function d(t,e,n){var r=0;for(t=n?N(t/C):t>>1,t+=N(t/e);t>L*k>>1;r+=w)t=N(t/L);return N(r+(L+1)*t/(t+$))}function h(t){var e,n,r,o,i,s,u,c,p,h,v=[],m=t.length,g=0,y=S,b=O;for(n=t.lastIndexOf(A),n<0&&(n=0),r=0;r<n;++r)t.charCodeAt(r)>=128&&a("not-basic"),v.push(t.charCodeAt(r));for(o=n>0?n+1:0;o<m;){for(i=g,s=1,u=w;o>=m&&a("invalid-input"),c=f(t.charCodeAt(o++)),(c>=w||c>N((_-g)/s))&&a("overflow"),g+=c*s,p=u<=b?x:u>=b+k?k:u-b,!(c<p);u+=w)h=w-p,s>N(_/h)&&a("overflow"),s*=h;e=v.length+1,b=d(g-i,e,0==i),N(g/e)>_-y&&a("overflow"),y+=N(g/e),g%=e,v.splice(g++,0,y)}return l(v)}function v(t){var e,n,r,o,i,s,u,l,f,h,v,m,g,y,b,$=[];for(t=c(t),m=t.length,e=S,n=0,i=O,s=0;s<m;++s)(v=t[s])<128&&$.push(I(v));for(r=o=$.length,o&&$.push(A);r<m;){for(u=_,s=0;s<m;++s)(v=t[s])>=e&&v<u&&(u=v);for(g=r+1,u-e>N((_-n)/g)&&a("overflow"),n+=(u-e)*g,e=u,s=0;s<m;++s)if(v=t[s],v<e&&++n>_&&a("overflow"),v==e){for(l=n,f=w;h=f<=i?x:f>=i+k?k:f-i,!(l<h);f+=w)b=l-h,y=w-h,$.push(I(p(h+b%y,0))),l=N(b/y);$.push(I(p(l,0))),i=d(n,g,r==o),n=0,++r}++n,++e}return $.join("")}function m(t){return u(t,function(t){return j.test(t)?h(t.slice(4).toLowerCase()):t})}function g(t){return u(t,function(t){return E.test(t)?"xn--"+v(t):t})}var y=("object"==typeof e&&e&&e.nodeType,"object"==typeof t&&t&&t.nodeType,"object"==typeof r&&r);var b,_=2147483647,w=36,x=1,k=26,$=38,C=700,O=72,S=128,A="-",j=/^xn--/,E=/[^\x20-\x7E]/,T=/[\x2E\u3002\uFF0E\uFF61]/g,P={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},L=w-x,N=Math.floor,I=String.fromCharCode;b={version:"1.4.1",ucs2:{decode:c,encode:l},decode:h,encode:v,toASCII:g,toUnicode:m},void 0!==(o=function(){return b}.call(e,n,e,t))&&(t.exports=o)})()}).call(e,n(24)(t),n(2))},function(t,e,n){"use strict";function r(t,e){return Object.prototype.hasOwnProperty.call(t,e)}t.exports=function(t,e,n,i){e=e||"&",n=n||"=";var a={};if("string"!=typeof t||0===t.length)return a;t=t.split(e);var s=1e3;i&&"number"==typeof i.maxKeys&&(s=i.maxKeys);var u=t.length;s>0&&u>s&&(u=s);for(var c=0;c<u;++c){var l,f,p,d,h=t[c].replace(/\+/g,"%20"),v=h.indexOf(n);v>=0?(l=h.substr(0,v),f=h.substr(v+1)):(l=h,f=""),p=decodeURIComponent(l),d=decodeURIComponent(f),r(a,p)?o(a[p])?a[p].push(d):a[p]=[a[p],d]:a[p]=d}return a};var o=Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)}},function(t,e,n){"use strict";function r(t,e){if(t.map)return t.map(e);for(var n=[],r=0;r<t.length;r++)n.push(e(t[r],r));return n}var o=function(t){switch(typeof t){case"string":return t;case"boolean":return t?"true":"false";case"number":return isFinite(t)?t:"";default:return""}};t.exports=function(t,e,n,s){return e=e||"&",n=n||"=",null===t&&(t=void 0),"object"==typeof t?r(a(t),function(a){var s=encodeURIComponent(o(a))+n;return i(t[a])?r(t[a],function(t){return s+encodeURIComponent(o(t))}).join(e):s+encodeURIComponent(o(t[a]))}).join(e):s?encodeURIComponent(o(s))+n+encodeURIComponent(o(t)):""};var i=Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)},a=Object.keys||function(t){var e=[];for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&e.push(n);return e}},function(t,e,n){"use strict";e.decode=e.parse=n(82),e.encode=e.stringify=n(83)},function(t,e){t.exports='<svg id="i-close" viewBox="0 0 32 32" width="32" height="32" fill="none" stroke="currentcolor" stroke-linecap="round" stroke-linejoin="round" stroke-width="6.25%">\n <path d="M2 30 L30 2 M30 30 L2 2" />\n</svg>\n'},function(t,e){t.exports='<svg id="i-edit" viewBox="0 0 32 32" width="32" height="32" fill="none" stroke="currentcolor" stroke-linecap="round" stroke-linejoin="round" stroke-width="6.25%">\n <path d="M30 7 L25 2 5 22 3 29 10 27 Z M21 6 L26 11 Z M5 22 L10 27 Z" />\n</svg>\n'},function(t,e){t.exports='<svg id="i-github" viewBox="0 0 64 64" width="32" height="32">\n <path stroke-width="0" fill="currentColor" d="M32 0 C14 0 0 14 0 32 0 53 19 62 22 62 24 62 24 61 24 60 L24 55 C17 57 14 53 13 50 13 50 13 49 11 47 10 46 6 44 10 44 13 44 15 48 15 48 18 52 22 51 24 50 24 48 26 46 26 46 18 45 12 42 12 31 12 27 13 24 15 22 15 22 13 18 15 13 15 13 20 13 24 17 27 15 37 15 40 17 44 13 49 13 49 13 51 20 49 22 49 22 51 24 52 27 52 31 52 42 45 45 38 46 39 47 40 49 40 52 L40 60 C40 61 40 62 42 62 45 62 64 53 64 32 64 14 50 0 32 0 Z" />\n</svg>\n'},function(t,e){t.exports='<svg id="i-info" viewBox="0 0 32 32" width="32" height="32" fill="none" stroke="currentcolor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">\n <path d="M16 14 L16 23 M16 8 L16 10" />\n <circle cx="16" cy="16" r="14" />\n</svg>\n'},function(t,e){t.exports='<svg id="i-menu" viewBox="0 0 32 32" width="32" height="32" fill="none" stroke="currentcolor" stroke-linecap="round" stroke-linejoin="round" stroke-width="6.25%">\n <path d="M4 8 L28 8 M4 16 L28 16 M4 24 L28 24" />\n</svg>\n'},function(t,e){t.exports='<svg id="i-search" viewBox="0 0 32 32" width="32" height="32" fill="none" stroke="currentcolor" stroke-linecap="round" stroke-linejoin="round" stroke-width="6.25%">\n <circle cx="14" cy="14" r="12" />\n <path d="M23 23 L30 30" />\n</svg>\n'},function(t,e){t.exports='<svg id="i-twitter" viewBox="0 0 64 64" width="32" height="32">\n <path stroke-width="0" fill="currentColor" d="M60 16 L54 17 L58 12 L51 14 C42 4 28 15 32 24 C16 24 8 12 8 12 C8 12 2 21 12 28 L6 26 C6 32 10 36 17 38 L10 38 C14 46 21 46 21 46 C21 46 15 51 4 51 C37 67 57 37 54 21 Z" />\n</svg>\n'},function(t,e,n){(function(e){var r="object"==typeof e?e:"object"==typeof window?window:"object"==typeof self?self:this,o=r.regeneratorRuntime&&Object.getOwnPropertyNames(r).indexOf("regeneratorRuntime")>=0,i=o&&r.regeneratorRuntime;if(r.regeneratorRuntime=void 0,t.exports=n(93),o)r.regeneratorRuntime=i;else try{delete r.regeneratorRuntime}catch(t){r.regeneratorRuntime=void 0}}).call(e,n(2))},function(t,e,n){(function(e){!function(e){"use strict";function r(t,e,n,r){var o=e&&e.prototype instanceof i?e:i,a=Object.create(o.prototype),s=new h(r||[]);return a._invoke=l(t,n,s),a}function o(t,e,n){try{return{type:"normal",arg:t.call(e,n)}}catch(t){return{type:"throw",arg:t}}}function i(){}function a(){}function s(){}function u(t){["next","throw","return"].forEach(function(e){t[e]=function(t){return this._invoke(e,t)}})}function c(t){function e(n,r,i,a){var s=o(t[n],t,r);if("throw"!==s.type){var u=s.arg,c=u.value;return c&&"object"==typeof c&&b.call(c,"__await")?Promise.resolve(c.__await).then(function(t){e("next",t,i,a)},function(t){e("throw",t,i,a)}):Promise.resolve(c).then(function(t){u.value=t,i(u)},a)}a(s.arg)}function r(t,n){function r(){return new Promise(function(r,o){e(t,n,r,o)})}return i=i?i.then(r,r):r()}n.i({env:n.i({NODE_ENV:"production"})}).domain&&(e=n.i({env:n.i({NODE_ENV:"production"})}).domain.bind(e));var i;this._invoke=r}function l(t,e,n){var r=O;return function(i,a){if(r===A)throw new Error("Generator is already running");if(r===j){if("throw"===i)throw a;return m()}for(n.method=i,n.arg=a;;){var s=n.delegate;if(s){var u=f(s,n);if(u){if(u===E)continue;return u}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(r===O)throw r=j,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);r=A;var c=o(t,e,n);if("normal"===c.type){if(r=n.done?j:S,c.arg===E)continue;return{value:c.arg,done:n.done}}"throw"===c.type&&(r=j,n.method="throw",n.arg=c.arg)}}}function f(t,e){var n=t.iterator[e.method];if(n===g){if(e.delegate=null,"throw"===e.method){if(t.iterator.return&&(e.method="return",e.arg=g,f(t,e),"throw"===e.method))return E;e.method="throw",e.arg=new TypeError("The iterator does not provide a 'throw' method")}return E}var r=o(n,t.iterator,e.arg);if("throw"===r.type)return e.method="throw",e.arg=r.arg,e.delegate=null,E;var i=r.arg;return i?i.done?(e[t.resultName]=i.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=g),e.delegate=null,E):i:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,E)}function p(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function d(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function h(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(p,this),this.reset(!0)}function v(t){if(t){var e=t[w];if(e)return e.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var n=-1,r=function e(){for(;++n<t.length;)if(b.call(t,n))return e.value=t[n],e.done=!1,e;return e.value=g,e.done=!0,e};return r.next=r}}return{next:m}}function m(){return{value:g,done:!0}}var g,y=Object.prototype,b=y.hasOwnProperty,_="function"==typeof Symbol?Symbol:{},w=_.iterator||"@@iterator",x=_.asyncIterator||"@@asyncIterator",k=_.toStringTag||"@@toStringTag",$="object"==typeof t,C=e.regeneratorRuntime;if(C)return void($&&(t.exports=C));C=e.regeneratorRuntime=$?t.exports:{},C.wrap=r;var O="suspendedStart",S="suspendedYield",A="executing",j="completed",E={},T={};T[w]=function(){return this};var P=Object.getPrototypeOf,L=P&&P(P(v([])));L&&L!==y&&b.call(L,w)&&(T=L);var N=s.prototype=i.prototype=Object.create(T);a.prototype=N.constructor=s,s.constructor=a,s[k]=a.displayName="GeneratorFunction",C.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===a||"GeneratorFunction"===(e.displayName||e.name))},C.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,s):(t.__proto__=s,k in t||(t[k]="GeneratorFunction")),t.prototype=Object.create(N),t},C.awrap=function(t){return{__await:t}},u(c.prototype),c.prototype[x]=function(){return this},C.AsyncIterator=c,C.async=function(t,e,n,o){var i=new c(r(t,e,n,o));return C.isGeneratorFunction(e)?i:i.next().then(function(t){return t.done?t.value:i.next()})},u(N),N[k]="Generator",N.toString=function(){return"[object Generator]"},C.keys=function(t){var e=[];for(var n in t)e.push(n);return e.reverse(),function n(){for(;e.length;){var r=e.pop();if(r in t)return n.value=r,n.done=!1,n}return n.done=!0,n}},C.values=v,h.prototype={constructor:h,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=g,this.done=!1,this.delegate=null,this.method="next",this.arg=g,this.tryEntries.forEach(d),!t)for(var e in this)"t"===e.charAt(0)&&b.call(this,e)&&!isNaN(+e.slice(1))&&(this[e]=g)},stop:function(){this.done=!0;var t=this.tryEntries[0],e=t.completion;if("throw"===e.type)throw e.arg;return this.rval},dispatchException:function(t){function e(e,r){return i.type="throw",i.arg=t,n.next=e,r&&(n.method="next",n.arg=g),!!r}if(this.done)throw t;for(var n=this,r=this.tryEntries.length-1;r>=0;--r){var o=this.tryEntries[r],i=o.completion;if("root"===o.tryLoc)return e("end");if(o.tryLoc<=this.prev){var a=b.call(o,"catchLoc"),s=b.call(o,"finallyLoc");if(a&&s){if(this.prev<o.catchLoc)return e(o.catchLoc,!0);if(this.prev<o.finallyLoc)return e(o.finallyLoc)}else if(a){if(this.prev<o.catchLoc)return e(o.catchLoc,!0)}else{if(!s)throw new Error("try statement without catch or finally");if(this.prev<o.finallyLoc)return e(o.finallyLoc)}}}},abrupt:function(t,e){for(var n=this.tryEntries.length-1;n>=0;--n){var r=this.tryEntries[n];if(r.tryLoc<=this.prev&&b.call(r,"finallyLoc")&&this.prev<r.finallyLoc){var o=r;break}}o&&("break"===t||"continue"===t)&&o.tryLoc<=e&&e<=o.finallyLoc&&(o=null);var i=o?o.completion:{};return i.type=t,i.arg=e,o?(this.method="next",this.next=o.finallyLoc,E):this.complete(i)},complete:function(t,e){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&e&&(this.next=e),E},finish:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),d(n),E}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var r=n.completion;if("throw"===r.type){var o=r.arg;d(n)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,n){return this.delegate={iterator:v(t),resultName:e,nextLoc:n},"next"===this.method&&(this.arg=g),E}}}("object"==typeof e?e:"object"==typeof window?window:"object"==typeof self?self:this)}).call(e,n(2))},function(t,e,n){(function(t){(function(t,e){"use strict";function r(t){"function"!=typeof t&&(t=new Function(""+t));for(var e=new Array(arguments.length-1),n=0;n<e.length;n++)e[n]=arguments[n+1];var r={callback:t,args:e};return c[u]=r,s(u),u++}function o(t){delete c[t]}function i(t){var n=t.callback,r=t.args;switch(r.length){case 0:n();break;case 1:n(r[0]);break;case 2:n(r[0],r[1]);break;case 3:n(r[0],r[1],r[2]);break;default:n.apply(e,r)}}function a(t){if(l)setTimeout(a,0,t);else{var e=c[t];if(e){l=!0;try{i(e)}finally{o(t),l=!1}}}}if(!t.setImmediate){var s,u=1,c={},l=!1,f=t.document,p=Object.getPrototypeOf&&Object.getPrototypeOf(t);p=p&&p.setTimeout?p:t,"[object process]"==={}.toString.call(t.process)?function(){s=function(t){n.i({env:n.i({NODE_ENV:"production"})}).nextTick(function(){a(t)})}}():!function(){if(t.postMessage&&!t.importScripts){var e=!0,n=t.onmessage;return t.onmessage=function(){e=!1},t.postMessage("","*"),t.onmessage=n,e}}()?t.MessageChannel?function(){var t=new MessageChannel;t.port1.onmessage=function(t){a(t.data)},s=function(e){t.port2.postMessage(e)}}():f&&"onreadystatechange"in f.createElement("script")?function(){var t=f.documentElement;s=function(e){var n=f.createElement("script");n.onreadystatechange=function(){a(e),n.onreadystatechange=null,t.removeChild(n),n=null},t.appendChild(n)}}():function(){s=function(t){setTimeout(a,0,t)}}():function(){var e="setImmediate$"+Math.random()+"$",n=function(n){n.source===t&&"string"==typeof n.data&&0===n.data.indexOf(e)&&a(+n.data.slice(e.length))};t.addEventListener?t.addEventListener("message",n,!1):t.attachEvent("onmessage",n),s=function(n){t.postMessage(e+n,"*")}}(),p.setImmediate=r,p.clearImmediate=o}})("undefined"==typeof self?void 0===t?this:t:self)}).call(e,n(2))},function(t,e){function n(t,e){function n(){a=0,s=+new Date,i=t.apply(r,o),r=null,o=null}var r,o,i,a,s=0;return function(){r=this,o=arguments;var t=new Date-s;return a||(t>=e?n():a=setTimeout(n,e-t)),i}}t.exports=n},function(t,e,n){function r(t,e){this._id=t,this._clearFn=e}var o=Function.prototype.apply;e.setTimeout=function(){return new r(o.call(setTimeout,window,arguments),clearTimeout)},e.setInterval=function(){return new r(o.call(setInterval,window,arguments),clearInterval)},e.clearTimeout=e.clearInterval=function(t){t&&t.close()},r.prototype.unref=r.prototype.ref=function(){},r.prototype.close=function(){this._clearFn.call(window,this._id)},e.enroll=function(t,e){clearTimeout(t._idleTimeoutId),t._idleTimeout=e},e.unenroll=function(t){clearTimeout(t._idleTimeoutId),t._idleTimeout=-1},e._unrefActive=e.active=function(t){clearTimeout(t._idleTimeoutId);var e=t._idleTimeout;e>=0&&(t._idleTimeoutId=setTimeout(function(){t._onTimeout&&t._onTimeout()},e))},n(94),e.setImmediate=setImmediate,e.clearImmediate=clearImmediate},function(t,e,n){window.fetch||(window.fetch=n(21).default||n(21))},function(t,e,n){function r(t){var e=i.call(arguments,1);return o(t,e.join("/").replace(/\/+/g,"/"))}var o=n(99).resolve,i=Array.prototype.slice;t.exports=r},function(t,e,n){"use strict";function r(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}function o(t,e,n){if(t&&c.isObject(t)&&t instanceof r)return t;var o=new r;return o.parse(t,e,n),o}function i(t){return c.isString(t)&&(t=o(t)),t instanceof r?t.format():r.prototype.format.call(t)}function a(t,e){return o(t,!1,!0).resolve(e)}function s(t,e){return t?o(t,!1,!0).resolveObject(e):e}var u=n(81),c=n(100);e.parse=o,e.resolve=a,e.resolveObject=s,e.format=i,e.Url=r;var l=/^([a-z0-9.+-]+:)/i,f=/:[0-9]*$/,p=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,d=["<",">",'"',"`"," ","\r","\n","\t"],h=["{","}","|","\\","^","`"].concat(d),v=["'"].concat(h),m=["%","/","?",";","#"].concat(v),g=["/","?","#"],y={javascript:!0,"javascript:":!0},b={javascript:!0,"javascript:":!0},_={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},w=n(84);r.prototype.parse=function(t,e,n){if(!c.isString(t))throw new TypeError("Parameter 'url' must be a string, not "+typeof t);var r=t.indexOf("?"),o=-1!==r&&r<t.indexOf("#")?"?":"#",i=t.split(o);i[0]=i[0].replace(/\\/g,"/"),t=i.join(o);var a=t;if(a=a.trim(),!n&&1===t.split("#").length){var s=p.exec(a);if(s)return this.path=a,this.href=a,this.pathname=s[1],s[2]?(this.search=s[2],this.query=e?w.parse(this.search.substr(1)):this.search.substr(1)):e&&(this.search="",this.query={}),this}var f=l.exec(a);if(f){f=f[0];var d=f.toLowerCase();this.protocol=d,a=a.substr(f.length)}if(n||f||a.match(/^\/\/[^@\/]+@[^@\/]+/)){var h="//"===a.substr(0,2);!h||f&&b[f]||(a=a.substr(2),this.slashes=!0)}if(!b[f]&&(h||f&&!_[f])){for(var x=-1,k=0;k<g.length;k++){var $=a.indexOf(g[k]);-1!==$&&(-1===x||$<x)&&(x=$)}var C,O;O=-1===x?a.lastIndexOf("@"):a.lastIndexOf("@",x),-1!==O&&(C=a.slice(0,O),a=a.slice(O+1),this.auth=decodeURIComponent(C)),x=-1;for(var k=0;k<m.length;k++){var $=a.indexOf(m[k]);-1!==$&&(-1===x||$<x)&&(x=$)}-1===x&&(x=a.length),this.host=a.slice(0,x),a=a.slice(x),this.parseHost(),this.hostname=this.hostname||"";var S="["===this.hostname[0]&&"]"===this.hostname[this.hostname.length-1];if(!S)for(var A=this.hostname.split(/\./),k=0,j=A.length;k<j;k++){var E=A[k];if(E&&!E.match(/^[+a-z0-9A-Z_-]{0,63}$/)){for(var T="",P=0,L=E.length;P<L;P++)E.charCodeAt(P)>127?T+="x":T+=E[P];if(!T.match(/^[+a-z0-9A-Z_-]{0,63}$/)){var N=A.slice(0,k),I=A.slice(k+1),M=E.match(/^([+a-z0-9A-Z_-]{0,63})(.*)$/);M&&(N.push(M[1]),I.unshift(M[2])),I.length&&(a="/"+I.join(".")+a),this.hostname=N.join(".");break}}}this.hostname.length>255?this.hostname="":this.hostname=this.hostname.toLowerCase(),S||(this.hostname=u.toASCII(this.hostname));var R=this.port?":"+this.port:"",D=this.hostname||"";this.host=D+R,this.href+=this.host,S&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==a[0]&&(a="/"+a))}if(!y[d])for(var k=0,j=v.length;k<j;k++){var q=v[k];if(-1!==a.indexOf(q)){var F=encodeURIComponent(q);F===q&&(F=escape(q)),a=a.split(q).join(F)}}var U=a.indexOf("#");-1!==U&&(this.hash=a.substr(U),a=a.slice(0,U));var H=a.indexOf("?");if(-1!==H?(this.search=a.substr(H),this.query=a.substr(H+1),e&&(this.query=w.parse(this.query)),a=a.slice(0,H)):e&&(this.search="",this.query={}),a&&(this.pathname=a),_[d]&&this.hostname&&!this.pathname&&(this.pathname="/"),this.pathname||this.search){var R=this.pathname||"",B=this.search||"";this.path=R+B}return this.href=this.format(),this},r.prototype.format=function(){var t=this.auth||"";t&&(t=encodeURIComponent(t),t=t.replace(/%3A/i,":"),t+="@");var e=this.protocol||"",n=this.pathname||"",r=this.hash||"",o=!1,i="";this.host?o=t+this.host:this.hostname&&(o=t+(-1===this.hostname.indexOf(":")?this.hostname:"["+this.hostname+"]"),this.port&&(o+=":"+this.port)),this.query&&c.isObject(this.query)&&Object.keys(this.query).length&&(i=w.stringify(this.query));var a=this.search||i&&"?"+i||"";return e&&":"!==e.substr(-1)&&(e+=":"),this.slashes||(!e||_[e])&&!1!==o?(o="//"+(o||""),n&&"/"!==n.charAt(0)&&(n="/"+n)):o||(o=""),r&&"#"!==r.charAt(0)&&(r="#"+r),a&&"?"!==a.charAt(0)&&(a="?"+a),n=n.replace(/[?#]/g,function(t){return encodeURIComponent(t)}),a=a.replace("#","%23"),e+o+n+a+r},r.prototype.resolve=function(t){return this.resolveObject(o(t,!1,!0)).format()},r.prototype.resolveObject=function(t){if(c.isString(t)){var e=new r;e.parse(t,!1,!0),t=e}for(var n=new r,o=Object.keys(this),i=0;i<o.length;i++){var a=o[i];n[a]=this[a]}if(n.hash=t.hash,""===t.href)return n.href=n.format(),n;if(t.slashes&&!t.protocol){for(var s=Object.keys(t),u=0;u<s.length;u++){var l=s[u];"protocol"!==l&&(n[l]=t[l])}return _[n.protocol]&&n.hostname&&!n.pathname&&(n.path=n.pathname="/"),n.href=n.format(),n}if(t.protocol&&t.protocol!==n.protocol){if(!_[t.protocol]){for(var f=Object.keys(t),p=0;p<f.length;p++){var d=f[p];n[d]=t[d]}return n.href=n.format(),n}if(n.protocol=t.protocol,t.host||b[t.protocol])n.pathname=t.pathname;else{for(var h=(t.pathname||"").split("/");h.length&&!(t.host=h.shift()););t.host||(t.host=""),t.hostname||(t.hostname=""),""!==h[0]&&h.unshift(""),h.length<2&&h.unshift(""),n.pathname=h.join("/")}if(n.search=t.search,n.query=t.query,n.host=t.host||"",n.auth=t.auth,n.hostname=t.hostname||t.host,n.port=t.port,n.pathname||n.search){var v=n.pathname||"",m=n.search||"";n.path=v+m}return n.slashes=n.slashes||t.slashes,n.href=n.format(),n}var g=n.pathname&&"/"===n.pathname.charAt(0),y=t.host||t.pathname&&"/"===t.pathname.charAt(0),w=y||g||n.host&&t.pathname,x=w,k=n.pathname&&n.pathname.split("/")||[],h=t.pathname&&t.pathname.split("/")||[],$=n.protocol&&!_[n.protocol];if($&&(n.hostname="",n.port=null,n.host&&(""===k[0]?k[0]=n.host:k.unshift(n.host)),n.host="",t.protocol&&(t.hostname=null,t.port=null,t.host&&(""===h[0]?h[0]=t.host:h.unshift(t.host)),t.host=null),w=w&&(""===h[0]||""===k[0])),y)n.host=t.host||""===t.host?t.host:n.host,n.hostname=t.hostname||""===t.hostname?t.hostname:n.hostname,n.search=t.search,n.query=t.query,k=h;else if(h.length)k||(k=[]),k.pop(),k=k.concat(h),n.search=t.search,n.query=t.query;else if(!c.isNullOrUndefined(t.search)){if($){n.hostname=n.host=k.shift();var C=!!(n.host&&n.host.indexOf("@")>0)&&n.host.split("@");C&&(n.auth=C.shift(),n.host=n.hostname=C.shift())}return n.search=t.search,n.query=t.query,c.isNull(n.pathname)&&c.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.href=n.format(),n}if(!k.length)return n.pathname=null,n.search?n.path="/"+n.search:n.path=null,n.href=n.format(),n;for(var O=k.slice(-1)[0],S=(n.host||t.host||k.length>1)&&("."===O||".."===O)||""===O,A=0,j=k.length;j>=0;j--)O=k[j],"."===O?k.splice(j,1):".."===O?(k.splice(j,1),A++):A&&(k.splice(j,1),A--);if(!w&&!x)for(;A--;A)k.unshift("..");!w||""===k[0]||k[0]&&"/"===k[0].charAt(0)||k.unshift(""),S&&"/"!==k.join("/").substr(-1)&&k.push("");var E=""===k[0]||k[0]&&"/"===k[0].charAt(0);if($){n.hostname=n.host=E?"":k.length?k.shift():"";var C=!!(n.host&&n.host.indexOf("@")>0)&&n.host.split("@");C&&(n.auth=C.shift(),n.host=n.hostname=C.shift())}return w=w||n.host&&k.length,w&&!E&&k.unshift(""),k.length?n.pathname=k.join("/"):(n.pathname=null,n.path=null),c.isNull(n.pathname)&&c.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.auth=t.auth||n.auth,n.slashes=n.slashes||t.slashes,n.href=n.format(),n},r.prototype.parseHost=function(){var t=this.host,e=f.exec(t);e&&(e=e[0],":"!==e&&(this.port=e.substr(1)),t=t.substr(0,t.length-e.length)),t&&(this.hostname=t)}},function(t,e,n){"use strict";t.exports={isString:function(t){return"string"==typeof t},isObject:function(t){return"object"==typeof t&&null!==t},isNull:function(t){return null===t},isNullOrUndefined:function(t){return null==t}}},function(t,e){function n(t,e){r(e,l,function(){s[t].instances.push(this)}),r(e,"beforeDestroy",function(){var e=s[t].instances;e.splice(e.indexOf(this),1)})}function r(t,e,n){var r=t[e];t[e]=r?Array.isArray(r)?r.concat(n):[r,n]:[n]}function o(t){return function(e,n){try{t(e,n)}catch(t){console.error(t),console.warn("Something went wrong during Vue component hot-reload. Full reload required.")}}}var i,a,s=window.__VUE_HOT_MAP__=Object.create(null),u=!1,c=!1,l="beforeCreate";e.install=function(t,n){if(!u)return u=!0,i=t.__esModule?t.default:t,a=i.version.split(".").map(Number),c=n,i.config._lifecycleHooks.indexOf("init")>-1&&(l="init"),e.compatible=a[0]>=2,e.compatible?void 0:void console.warn("[HMR] You are using a version of vue-hot-reload-api that is only compatible with Vue.js core ^2.0.0.")},e.createRecord=function(t,e){var r=null;"function"==typeof e&&(r=e,e=r.options),n(t,e),s[t]={Ctor:i.extend(e),instances:[]}},e.rerender=o(function(t,e){var n=s[t];if(!e)return void n.instances.slice().forEach(function(t){t.$forceUpdate()});"function"==typeof e&&(e=e.options),n.Ctor.options.render=e.render,n.Ctor.options.staticRenderFns=e.staticRenderFns,n.instances.slice().forEach(function(t){t.$options.render=e.render,t.$options.staticRenderFns=e.staticRenderFns,t._staticTrees=[],t.$forceUpdate()})}),e.reload=o(function(t,e){var r=s[t];if(e){"function"==typeof e&&(e=e.options),n(t,e),a[1]<2&&(r.Ctor.extendOptions=e);var o=r.Ctor.super.extend(e);r.Ctor.options=o.options,r.Ctor.cid=o.cid,r.Ctor.prototype=o.prototype,o.release&&o.release()}r.instances.slice().forEach(function(t){t.$vnode&&t.$vnode.context?t.$vnode.context.$forceUpdate():console.warn("Root or manually mounted instance modified. Full reload required.")})})},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=function(t){return t&&"object"==typeof t&&"default"in t?t.default:t}(n(19)),o=function(t){return void 0===t&&(t={}),{name:"inline",functional:!0,props:{name:{type:String,required:!0}},render:function(e,n){var o=t[n.props.name];return"string"==typeof o?e("span",r({domProps:{innerHTML:o}},n.data)):e("span",n.data,o)}}},i=function(t,e){var n=e.data;return t.component("inline",o(n))};e.default=i,e.makeComponent=o},function(t,e,n){function r(t){o||(n(56),n(57),n(61),n(58),n(60),n(59))}var o=!1,i=n(0)(n(34),n(117),r,null,null);i.options.__file="/Users/egoist/dev/docute/src/components/App.vue",i.esModule&&Object.keys(i.esModule).some(function(t){return"default"!==t&&"__"!==t.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),i.options.functional&&console.error("[vue-loader] App.vue: functional components are not supported with templates, they should use render functions."),t.exports=i.exports},function(t,e,n){(function(t){function e(t){r||(o.$style=n(18),Object.defineProperty(this,"$style",{get:function(){return o.$style}}))}var r=!1,o={};t.hot&&t.hot.accept(['!!../../node_modules/extract-text-webpack-plugin/loader.js?{"omit":1,"remove":true}!vue-style-loader!css-loader?{"autoprefixer":false,"sourceMap":true,"minimize":true,"localIdentName":"[hash:base64]_0","modules":true,"importLoaders":true}!../../node_modules/vue-loader/lib/style-compiler/index?{"vue":true,"id":"data-v-35e0aeec","scoped":false,"hasInlineConfig":true}!../../node_modules/vue-loader/lib/selector?type=styles&index=0!./CustomToc.vue'],function(){var t=o.$style;if(t){var e=n(18);JSON.stringify(e)!==JSON.stringify(t)&&(o.$style=e,n(101).rerender("data-v-35e0aeec"))}});var i=n(0)(n(35),n(118),e,null,null);i.options.__file="/Users/egoist/dev/docute/src/components/CustomToc.vue",i.esModule&&Object.keys(i.esModule).some(function(t){return"default"!==t&&"__"!==t.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),i.options.functional&&console.error("[vue-loader] CustomToc.vue: functional components are not supported with templates, they should use render functions."),t.exports=i.exports}).call(e,n(24)(t))},function(t,e,n){function r(t){o||(n(65),n(66))}var o=!1,i=n(0)(n(38),n(123),r,null,null);i.options.__file="/Users/egoist/dev/docute/src/components/HomeHeader.vue",i.esModule&&Object.keys(i.esModule).some(function(t){return"default"!==t&&"__"!==t.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),i.options.functional&&console.error("[vue-loader] HomeHeader.vue: functional components are not supported with templates, they should use render functions."),t.exports=i.exports},function(t,e,n){function r(t){o||n(73)}var o=!1,i=n(0)(n(39),n(128),r,null,null);i.options.__file="/Users/egoist/dev/docute/src/components/MobileHeader.vue",i.esModule&&Object.keys(i.esModule).some(function(t){return"default"!==t&&"__"!==t.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),i.options.functional&&console.error("[vue-loader] MobileHeader.vue: functional components are not supported with templates, they should use render functions."),t.exports=i.exports},function(t,e,n){var r=n(0)(n(40),n(121),null,null,null);r.options.__file="/Users/egoist/dev/docute/src/components/NavLink.vue",r.esModule&&Object.keys(r.esModule).some(function(t){return"default"!==t&&"__"!==t.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),r.options.functional&&console.error("[vue-loader] NavLink.vue: functional components are not supported with templates, they should use render functions."),t.exports=r.exports},function(t,e,n){function r(t){o||n(67)}var o=!1,i=n(0)(n(41),n(124),r,null,null);i.options.__file="/Users/egoist/dev/docute/src/components/SearchBox.vue",i.esModule&&Object.keys(i.esModule).some(function(t){return"default"!==t&&"__"!==t.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),i.options.functional&&console.error("[vue-loader] SearchBox.vue: functional components are not supported with templates, they should use render functions."),t.exports=i.exports},function(t,e,n){function r(t){o||n(64)}var o=!1,i=n(0)(n(42),n(122),r,null,null);i.options.__file="/Users/egoist/dev/docute/src/components/SearchResult.vue",i.esModule&&Object.keys(i.esModule).some(function(t){return"default"!==t&&"__"!==t.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),i.options.functional&&console.error("[vue-loader] SearchResult.vue: functional components are not supported with templates, they should use render functions."),t.exports=i.exports},function(t,e,n){function r(t){o||n(54)}var o=!1,i=n(0)(n(43),n(115),r,null,null);i.options.__file="/Users/egoist/dev/docute/src/components/SidebarToggle.vue",i.esModule&&Object.keys(i.esModule).some(function(t){return"default"!==t&&"__"!==t.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),i.options.functional&&console.error("[vue-loader] SidebarToggle.vue: functional components are not supported with templates, they should use render functions."),t.exports=i.exports},function(t,e,n){function r(t){o||n(55)}var o=!1,i=n(0)(n(44),n(116),r,null,null);i.options.__file="/Users/egoist/dev/docute/src/components/Toc.vue",i.esModule&&Object.keys(i.esModule).some(function(t){return"default"!==t&&"__"!==t.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),i.options.functional&&console.error("[vue-loader] Toc.vue: functional components are not supported with templates, they should use render functions."),t.exports=i.exports},function(t,e,n){function r(t){o||(n(72),n(71))}var o=!1,i=n(0)(n(45),n(127),r,"data-v-ebc5a04e",null);i.options.__file="/Users/egoist/dev/docute/src/views/404.vue",i.esModule&&Object.keys(i.esModule).some(function(t){return"default"!==t&&"__"!==t.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),i.options.functional&&console.error("[vue-loader] 404.vue: functional components are not supported with templates, they should use render functions."),t.exports=i.exports},function(t,e,n){function r(t){o||n(63)}var o=!1,i=n(0)(n(46),n(120),r,null,null);i.options.__file="/Users/egoist/dev/docute/src/views/Landing.vue",i.esModule&&Object.keys(i.esModule).some(function(t){return"default"!==t&&"__"!==t.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),i.options.functional&&console.error("[vue-loader] Landing.vue: functional components are not supported with templates, they should use render functions."),t.exports=i.exports},function(t,e,n){function r(t){o||(n(68),n(69))}var o=!1,i=n(0)(n(47),n(125),r,null,null);i.options.__file="/Users/egoist/dev/docute/src/views/Page.vue",i.esModule&&Object.keys(i.esModule).some(function(t){return"default"!==t&&"__"!==t.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),i.options.functional&&console.error("[vue-loader] Page.vue: functional components are not supported with templates, they should use render functions."),t.exports=i.exports},function(t,e,n){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"sidebar-toggle inner-x"},[n("svg-icon",{staticClass:"toggle-trigger",attrs:{name:"menu"},on:{click:function(e){t.toggleSidebar()}}})],1)},staticRenderFns:[]},t.exports.render._withStripped=!0},function(t,e,n){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("ul",{staticClass:"sidebar-headings"},t._l(t.headings,function(e){return n("li",{staticClass:"sidebar-heading",class:{"has-children":t.hasChildren(e.index),visible:t.isVisible(e.level,e.parent)},attrs:{"data-level":e.level}},[n("router-link",{staticClass:"sidebar-heading-anchor",class:{active:t.activeId===e.slug},attrs:{exact:"",to:{query:t.getQuery(e)}},domProps:{innerHTML:t._s(e.text.replace(/<(?:.|\n)*?>/gm,""))},nativeOn:{click:function(n){t.navigate(e.slug)}}})],1)}))},staticRenderFns:[]},t.exports.render._withStripped=!0},function(t,e,n){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{attrs:{id:"app"}},[n("router-view")],1)},staticRenderFns:[]},t.exports.render._withStripped=!0},function(t,e,n){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.content.component?n(t.content.component,{tag:"component",class:t.$style["custom-toc"]}):t.content.html?n("div",{class:t.$style["custom-toc"],domProps:{innerHTML:t._s(t.content.html)}}):t._e()},staticRenderFns:[]},t.exports.render._withStripped=!0},function(t,e,n){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.currentIcons.length>0?n("div",{staticClass:"header-icons"},t._l(t.currentIcons,function(e,r){return n("a",{staticClass:"header-icon hint--rounded",class:t.hintPosition(r),attrs:{target:"_blank","aria-label":e.label,href:e.link}},[e.icon?n("svg-icon",{staticClass:"svg-icon",attrs:{name:e.icon}}):t._e(),t._v(" "),e.html?n("span",{staticClass:"icon-html",domProps:{innerHTML:t._s(e.html)}}):t._e(),t._v(" "),e.svgId?n("svg",{class:e.svgClass},[n("use",{attrs:{"xlink:href":"#"+e.svgId}})]):t._e()],1)})):t._e()},staticRenderFns:[]},t.exports.render._withStripped=!0},function(t,e,n){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.content.component?n(t.content.component,{tag:"component",staticClass:"landing"}):t.content.html?n("div",{staticClass:"landing",domProps:{innerHTML:t._s(t.content.html)}}):t._e()},staticRenderFns:[]},t.exports.render._withStripped=!0},function(t,e,n){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.isExternal(t.item.path)?n("a",{staticClass:"router-link",attrs:{href:t.item.path,target:"_blank"}},[t._v("\n "+t._s(t.item.title)+"\n")]):n("router-link",{staticClass:"router-link",class:{"router-link-active":t.item.path===t.$route.path},attrs:{to:t.item.path,exact:""}},[t._v("\n "+t._s(t.item.title)+"\n")])},staticRenderFns:[]},t.exports.render._withStripped=!0},function(t,e,n){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"search-result"},[0===t.searchResult.length?n("div",{staticClass:"empty-search-result inner-x"},[t._v("\n "+t._s(t.searchState.emptyState)+"\n ")]):t._e(),t._v(" "),t._l(t.searchResult,function(e){return n("div",{staticClass:"inner-x result-item",class:{active:t.isActive(e)},on:{click:function(n){t.handleClick(e)}}},[n("span",{staticClass:"result-title",domProps:{innerHTML:t._s(e.title)}}),t._v(" "),e.content?n("div",{staticClass:"result-content",domProps:{innerHTML:t._s(e.content)}}):t._e()])})],2)},staticRenderFns:[]},t.exports.render._withStripped=!0},function(t,e,n){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.hasNav||t.currentIcons.length>0||t.hasComponentsAroundIcons?n("header",{staticClass:"header is-desktop"},[n("div",{staticClass:"header-container"},[n("header-nav",{attrs:{"current-nav":t.currentNav,"has-nav":t.hasNav,"show-nav":t.showNav}}),t._v(" "),t.currentIcons.length>0||t.hasComponentsAroundIcons?n("div",{staticClass:"header-right"},[n("custom-components",{attrs:{place:"icons:start"}}),t._v(" "),n("header-icons",{attrs:{"current-icons":t.currentIcons,"show-nav":t.showNav}}),t._v(" "),n("custom-components",{attrs:{place:"icons:end"}})],1):t._e()],1)]):t._e()},staticRenderFns:[]},t.exports.render._withStripped=!0},function(t,e,n){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"search-form",class:{focus:t.focus}},[n("input",{directives:[{name:"model",rawName:"v-model",value:t.keyword,expression:"keyword"}],ref:"input",staticClass:"search-box inner-x",attrs:{type:"text",placeholder:t.searchState.placeHolder},domProps:{value:t.keyword},on:{focus:t.toggleFocus,blur:t.toggleFocus,input:[function(e){e.target.composing||(t.keyword=e.target.value)},function(e){t.handleSearch(t.keyword)}]}}),t._v(" "),t.keyword?n("svg-icon",{staticClass:"svg-icon close",attrs:{name:"close"},on:{click:t.handleClear}}):n("svg-icon",{staticClass:"svg-icon do-search",attrs:{name:"search"},on:{click:function(e){t.handleSearch(t.keyword)}}})],1)},staticRenderFns:[]},t.exports.render._withStripped=!0},function(t,e,n){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"page",class:{"no-sidebar":!t.showSidebar}},[t.isMobile||t.config.disableSidebarToggle?t._e():n("sidebar-toggle"),t._v(" "),t.loaded&&(t.showSidebar||t.isMobile)?n("figure",{ref:"sidebar",staticClass:"sidebar"},[t.pluginSearch?n("search-box"):t._e(),t._v(" "),t.pluginSearch&&t.searchResult&&t.searchKeyword?n("search-result"):t._e(),t._v(" "),t.loaded?n("custom-components",{attrs:{place:"sidebar:start"}}):t._e(),t._v(" "),n("header-nav",{staticClass:"is-mobile inner-x",attrs:{"has-nav":t.hasNav,"show-nav":t.showNav,"current-nav":t.currentNav}}),t._v(" "),t.showCustomToc?n("custom-toc",{attrs:{toc:t.showToc}}):t.showToc?n("toc",{attrs:{headings:t.page.headings}}):t._e(),t._v(" "),t.loaded?n("custom-components",{attrs:{place:"sidebar:end"}}):t._e()],1):t._e(),t._v(" "),t.loaded?n("mobile-header",{attrs:{"current-icons":t.currentIcons}}):t._e(),t._v(" "),n("section",{staticClass:"main"},[t.loaded?n("home-header",{attrs:{"current-icons":t.currentIcons,"has-nav":t.hasNav,"show-nav":t.showNav}}):t._e(),t._v(" "),n("div",{ref:"contentWrap",staticClass:"content-wrap"},[t.loaded?n("custom-components",{attrs:{place:"content:start"}}):t._e(),t._v(" "),t.docComponent?n(t.docComponent,{tag:"component"}):n("div",{staticClass:"markdown-body content",domProps:{innerHTML:t._s(t.page.html)}}),t._v(" "),t.loaded?n("custom-components",{attrs:{place:"content:end"}}):t._e()],1)],1)],1)},staticRenderFns:[]},t.exports.render._withStripped=!0},function(t,e,n){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.showNav?n("div",{staticClass:"header-nav"},[n("custom-components",{attrs:{place:"nav:start"}}),t._v(" "),t.hasNav?n("ul",{staticClass:"nav-list"},t._l(t.currentNav,function(e,r){return n("li",{staticClass:"nav-item"},["dropdown"===e.type?n("div",{staticClass:"nav-item-dropdown",attrs:{onClick:"return true"}},[t._v("\n "+t._s(t.getTitle(e))+"\n "),n("span",{staticClass:"arrow"}),t._v(" "),n("ul",{staticClass:"dropdown-list"},t._l(e.items,function(e){return n("li",{staticClass:"dropdown-item",style:{padding:"sep"===e.type?"0":"0 20px"}},["sep"===e.type?n("span",{staticClass:"sep"}):"label"===e.type?n("span",{staticClass:"label"},[t._v(t._s(e.title))]):n("nav-link",{attrs:{item:e}})],1)}))]):n("nav-link",{attrs:{item:e}})],1)})):t._e(),t._v(" "),n("custom-components",{attrs:{place:"nav:end"}})],1):t._e()},staticRenderFns:[]},t.exports.render._withStripped=!0},function(t,e,n){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"not-found"},[t.from?n("div",{staticClass:"message"},[n("h2",[t._v("\n Cannot find resource at "+t._s(t.from.path)+"\n ")]),t._v(" "),n("router-link",{attrs:{to:"/"}},[t._v("← Back home")])],1):t._e()])},staticRenderFns:[]},t.exports.render._withStripped=!0},function(t,e,n){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("header",{ref:"header",staticClass:"mobile-header is-mobile-flex"},[n("div",{staticClass:"header-left",on:{click:function(e){t.toggleMobileSidebar()}}},[n("h1",{staticClass:"site-title"},[n("svg-icon",{ref:"icon",staticClass:"svg-icon",attrs:{name:"menu"}}),t._v(" "),t.config.disableHeaderTitle?t._e():n("span",[t._v(t._s(t.config.title))])],1)]),t._v(" "),n("div",{staticClass:"header-right"},[n("header-icons",{attrs:{"current-icons":t.currentIcons}})],1)])},staticRenderFns:[]},t.exports.render._withStripped=!0},function(t,e,n){"use strict";function r(t,e){}function o(t,e){switch(typeof e){case"undefined":return;case"object":return e;case"function":return e(t);case"boolean":return e?t.params:void 0}}function i(t,e,n){void 0===e&&(e={});var r,o=n||a;try{r=o(t||"")}catch(t){r={}}for(var i in e){var s=e[i];r[i]=Array.isArray(s)?s.slice():s}return r}function a(t){var e={};return(t=t.trim().replace(/^(\?|#|&)/,""))?(t.split("&").forEach(function(t){var n=t.replace(/\+/g," ").split("="),r=Pt(n.shift()),o=n.length>0?Pt(n.join("=")):null;void 0===e[r]?e[r]=o:Array.isArray(e[r])?e[r].push(o):e[r]=[e[r],o]}),e):e}function s(t){var e=t?Object.keys(t).map(function(e){var n=t[e];if(void 0===n)return"";if(null===n)return Tt(e);if(Array.isArray(n)){var r=[];return n.slice().forEach(function(t){void 0!==t&&(null===t?r.push(Tt(e)):r.push(Tt(e)+"="+Tt(t)))}),r.join("&")}return Tt(e)+"="+Tt(n)}).filter(function(t){return t.length>0}).join("&"):null;return e?"?"+e:""}function u(t,e,n,r){var o=r&&r.options.stringifyQuery,i={name:e.name||t&&t.name,meta:t&&t.meta||{},path:e.path||"/",hash:e.hash||"",query:e.query||{},params:e.params||{},fullPath:l(e,o),matched:t?c(t):[]};return n&&(i.redirectedFrom=l(n,o)),Object.freeze(i)}function c(t){for(var e=[];t;)e.unshift(t),t=t.parent;return e}function l(t,e){var n=t.path,r=t.query;void 0===r&&(r={});var o=t.hash;void 0===o&&(o="");var i=e||s;return(n||"/")+i(r)+o}function f(t,e){return e===Nt?t===e:!!e&&(t.path&&e.path?t.path.replace(Lt,"")===e.path.replace(Lt,"")&&t.hash===e.hash&&p(t.query,e.query):!(!t.name||!e.name)&&(t.name===e.name&&t.hash===e.hash&&p(t.query,e.query)&&p(t.params,e.params)))}function p(t,e){void 0===t&&(t={}),void 0===e&&(e={});var n=Object.keys(t),r=Object.keys(e);return n.length===r.length&&n.every(function(n){return String(t[n])===String(e[n])})}function d(t,e){return 0===t.path.replace(Lt,"/").indexOf(e.path.replace(Lt,"/"))&&(!e.hash||t.hash===e.hash)&&h(t.query,e.query)}function h(t,e){for(var n in e)if(!(n in t))return!1;return!0}function v(t){if(!(t.metaKey||t.ctrlKey||t.shiftKey||t.defaultPrevented||void 0!==t.button&&0!==t.button)){if(t.currentTarget&&t.currentTarget.getAttribute){if(/\b_blank\b/i.test(t.currentTarget.getAttribute("target")))return}return t.preventDefault&&t.preventDefault(),!0}}function m(t){if(t)for(var e,n=0;n<t.length;n++){if(e=t[n],"a"===e.tag)return e;if(e.children&&(e=m(e.children)))return e}}function g(t){if(!g.installed){g.installed=!0,At=t,Object.defineProperty(t.prototype,"$router",{get:function(){return this.$root._router}}),Object.defineProperty(t.prototype,"$route",{get:function(){return this.$root._route}});var e=function(t){return void 0!==t},n=function(t,n){var r=t.$options._parentVnode;e(r)&&e(r=r.data)&&e(r=r.registerRouteInstance)&&r(t,n)};t.mixin({beforeCreate:function(){e(this.$options.router)&&(this._router=this.$options.router,this._router.init(this),t.util.defineReactive(this,"_route",this._router.history.current)),n(this,this)},destroyed:function(){n(this)}}),t.component("router-view",jt),t.component("router-link",Rt);var r=t.config.optionMergeStrategies;r.beforeRouteEnter=r.beforeRouteLeave=r.created}}function y(t,e,n){var r=t.charAt(0);if("/"===r)return t;if("?"===r||"#"===r)return e+t;var o=e.split("/");n&&o[o.length-1]||o.pop();for(var i=t.replace(/^\//,"").split("/"),a=0;a<i.length;a++){var s=i[a];".."===s?o.pop():"."!==s&&o.push(s)}return""!==o[0]&&o.unshift(""),o.join("/")}function b(t){var e="",n="",r=t.indexOf("#");r>=0&&(e=t.slice(r),t=t.slice(0,r));var o=t.indexOf("?");return o>=0&&(n=t.slice(o+1),t=t.slice(0,o)),{path:t,query:n,hash:e}}function _(t){return t.replace(/\/\//g,"/")}function w(t,e){for(var n,r=[],o=0,i=0,a="",s=e&&e.delimiter||"/";null!=(n=Vt.exec(t));){var u=n[0],c=n[1],l=n.index;if(a+=t.slice(i,l),i=l+u.length,c)a+=c[1];else{var f=t[i],p=n[2],d=n[3],h=n[4],v=n[5],m=n[6],g=n[7];a&&(r.push(a),a="");var y=null!=p&&null!=f&&f!==p,b="+"===m||"*"===m,_="?"===m||"*"===m,w=n[2]||s,x=h||v;r.push({name:d||o++,prefix:p||"",delimiter:w,optional:_,repeat:b,partial:y,asterisk:!!g,pattern:x?S(x):g?".*":"[^"+O(w)+"]+?"})}}return i<t.length&&(a+=t.substr(i)),a&&r.push(a),r}function x(t,e){return C(w(t,e))}function k(t){return encodeURI(t).replace(/[\/?#]/g,function(t){return"%"+t.charCodeAt(0).toString(16).toUpperCase()})}function $(t){return encodeURI(t).replace(/[?#]/g,function(t){return"%"+t.charCodeAt(0).toString(16).toUpperCase()})}function C(t){for(var e=new Array(t.length),n=0;n<t.length;n++)"object"==typeof t[n]&&(e[n]=new RegExp("^(?:"+t[n].pattern+")$"));return function(n,r){for(var o="",i=n||{},a=r||{},s=a.pretty?k:encodeURIComponent,u=0;u<t.length;u++){var c=t[u];if("string"!=typeof c){var l,f=i[c.name];if(null==f){if(c.optional){c.partial&&(o+=c.prefix);continue}throw new TypeError('Expected "'+c.name+'" to be defined')}if(qt(f)){if(!c.repeat)throw new TypeError('Expected "'+c.name+'" to not repeat, but received `'+JSON.stringify(f)+"`");if(0===f.length){if(c.optional)continue;throw new TypeError('Expected "'+c.name+'" to not be empty')}for(var p=0;p<f.length;p++){if(l=s(f[p]),!e[u].test(l))throw new TypeError('Expected all "'+c.name+'" to match "'+c.pattern+'", but received `'+JSON.stringify(l)+"`");o+=(0===p?c.prefix:c.delimiter)+l}}else{if(l=c.asterisk?$(f):s(f),!e[u].test(l))throw new TypeError('Expected "'+c.name+'" to match "'+c.pattern+'", but received "'+l+'"');o+=c.prefix+l}}else o+=c}return o}}function O(t){return t.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}function S(t){return t.replace(/([=!:$\/()])/g,"\\$1")}function A(t,e){return t.keys=e,t}function j(t){return t.sensitive?"":"i"}function E(t,e){var n=t.source.match(/\((?!\?)/g);if(n)for(var r=0;r<n.length;r++)e.push({name:r,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,asterisk:!1,pattern:null});return A(t,e)}function T(t,e,n){for(var r=[],o=0;o<t.length;o++)r.push(N(t[o],e,n).source);return A(new RegExp("(?:"+r.join("|")+")",j(n)),e)}function P(t,e,n){return L(w(t,n),e,n)}function L(t,e,n){qt(e)||(n=e||n,e=[]),n=n||{};for(var r=n.strict,o=!1!==n.end,i="",a=0;a<t.length;a++){var s=t[a];if("string"==typeof s)i+=O(s);else{var u=O(s.prefix),c="(?:"+s.pattern+")";e.push(s),s.repeat&&(c+="(?:"+u+c+")*"),c=s.optional?s.partial?u+"("+c+")?":"(?:"+u+"("+c+"))?":u+"("+c+")",i+=c}}var l=O(n.delimiter||"/"),f=i.slice(-l.length)===l;return r||(i=(f?i.slice(0,-l.length):i)+"(?:"+l+"(?=$))?"),i+=o?"$":r&&f?"":"(?="+l+"|$)",A(new RegExp("^"+i,j(n)),e)}function N(t,e,n){return qt(e)||(n=e||n,e=[]),n=n||{},t instanceof RegExp?E(t,e):qt(t)?T(t,e,n):P(t,e,n)}function I(t,e,n){try{return(Wt[t]||(Wt[t]=Ft.compile(t)))(e||{},{pretty:!0})}catch(t){return""}}function M(t,e,n,r){var o=e||[],i=n||Object.create(null),a=r||Object.create(null);t.forEach(function(t){R(o,i,a,t)});for(var s=0,u=o.length;s<u;s++)"*"===o[s]&&(o.push(o.splice(s,1)[0]),u--,s--);return{pathList:o,pathMap:i,nameMap:a}}function R(t,e,n,r,o,i){var a=r.path,s=r.name,u=q(a,o),c={path:u,regex:D(u),components:r.components||{default:r.component},instances:{},name:s,parent:o,matchAs:i,redirect:r.redirect,beforeEnter:r.beforeEnter,meta:r.meta||{},props:null==r.props?{}:r.components?r.props:{default:r.props}};if(r.children&&r.children.forEach(function(r){var o=i?_(i+"/"+r.path):void 0;R(t,e,n,r,c,o)}),void 0!==r.alias)if(Array.isArray(r.alias))r.alias.forEach(function(i){var a={path:i,children:r.children};R(t,e,n,a,o,c.path)});else{var l={path:r.alias,children:r.children};R(t,e,n,l,o,c.path)}e[c.path]||(t.push(c.path),e[c.path]=c),s&&(n[s]||(n[s]=c))}function D(t){var e=Ft(t);return e}function q(t,e){return t=t.replace(/\/$/,""),"/"===t[0]?t:null==e?t:_(e.path+"/"+t)}function F(t,e,n,r){var o="string"==typeof t?{path:t}:t;if(o.name||o._normalized)return o;if(!o.path&&o.params&&e){o=U({},o),o._normalized=!0;var a=U(U({},e.params),o.params);if(e.name)o.name=e.name,o.params=a;else if(e.matched){var s=e.matched[e.matched.length-1].path;o.path=I(s,a,"path "+e.path)}return o}var u=b(o.path||""),c=e&&e.path||"/",l=u.path?y(u.path,c,n||o.append):c,f=i(u.query,o.query,r&&r.options.parseQuery),p=o.hash||u.hash;return p&&"#"!==p.charAt(0)&&(p="#"+p),{_normalized:!0,path:l,query:f,hash:p}}function U(t,e){for(var n in e)t[n]=e[n];return t}function H(t,e){function n(t){M(t,c,l,f)}function r(t,n,r){var o=F(t,n,!1,e),i=o.name;if(i){var s=f[i],u=s.regex.keys.filter(function(t){return!t.optional}).map(function(t){return t.name});if("object"!=typeof o.params&&(o.params={}),n&&"object"==typeof n.params)for(var p in n.params)!(p in o.params)&&u.indexOf(p)>-1&&(o.params[p]=n.params[p]);if(s)return o.path=I(s.path,o.params,'named route "'+i+'"'),a(s,o,r)}else if(o.path){o.params={};for(var d=0;d<c.length;d++){var h=c[d],v=l[h];if(B(v.regex,o.path,o.params))return a(v,o,r)}}return a(null,o)}function o(t,n){var o=t.redirect,i="function"==typeof o?o(u(t,n,null,e)):o;if("string"==typeof i&&(i={path:i}),!i||"object"!=typeof i)return a(null,n);var s=i,c=s.name,l=s.path,p=n.query,d=n.hash,h=n.params;if(p=s.hasOwnProperty("query")?s.query:p,d=s.hasOwnProperty("hash")?s.hash:d,h=s.hasOwnProperty("params")?s.params:h,c){f[c];return r({_normalized:!0,name:c,query:p,hash:d,params:h},void 0,n)}if(l){var v=z(l,t);return r({_normalized:!0,path:I(v,h,'redirect route with path "'+v+'"'),query:p,hash:d},void 0,n)}return a(null,n)}function i(t,e,n){var o=I(n,e.params,'aliased route with path "'+n+'"'),i=r({_normalized:!0,path:o});if(i){var s=i.matched,u=s[s.length-1];return e.params=i.params,a(u,e)}return a(null,e)}function a(t,n,r){return t&&t.redirect?o(t,r||n):t&&t.matchAs?i(t,n,t.matchAs):u(t,n,r,e)}var s=M(t),c=s.pathList,l=s.pathMap,f=s.nameMap;return{match:r,addRoutes:n}}function B(t,e,n){var r=e.match(t);if(!r)return!1;if(!n)return!0;for(var o=1,i=r.length;o<i;++o){var a=t.keys[o-1],s="string"==typeof r[o]?decodeURIComponent(r[o]):r[o];a&&(n[a.name]=s)}return!0}function z(t,e){return y(t,e.parent?e.parent.path:"/",!0)}function V(){window.addEventListener("popstate",function(t){G(),t.state&&t.state.key&&et(t.state.key)})}function W(t,e,n,r){if(t.app){var o=t.options.scrollBehavior;o&&t.app.$nextTick(function(){var t=K(),i=o(e,n,r?t:null);if(i){var a="object"==typeof i;if(a&&"string"==typeof i.selector){var s=document.querySelector(i.selector);s?t=J(s):Z(i)&&(t=Y(i))}else a&&Z(i)&&(t=Y(i));t&&window.scrollTo(t.x,t.y)}})}}function G(){var t=tt();t&&(Gt[t]={x:window.pageXOffset,y:window.pageYOffset})}function K(){var t=tt();if(t)return Gt[t]}function J(t){var e=document.documentElement,n=e.getBoundingClientRect(),r=t.getBoundingClientRect();return{x:r.left-n.left,y:r.top-n.top}}function Z(t){return X(t.x)||X(t.y)}function Y(t){return{x:X(t.x)?t.x:window.pageXOffset,y:X(t.y)?t.y:window.pageYOffset}}function X(t){return"number"==typeof t}function Q(){return Jt.now().toFixed(3)}function tt(){return Zt}function et(t){Zt=t}function nt(t,e){G();var n=window.history;try{e?n.replaceState({key:Zt},"",t):(Zt=Q(),n.pushState({key:Zt},"",t))}catch(n){window.location[e?"replace":"assign"](t)}}function rt(t){nt(t,!0)}function ot(t,e,n){var r=function(o){o>=t.length?n():t[o]?e(t[o],function(){r(o+1)}):r(o+1)};r(0)}function it(t){if(!t)if(Dt){var e=document.querySelector("base");t=e&&e.getAttribute("href")||"/"}else t="/";return"/"!==t.charAt(0)&&(t="/"+t),t.replace(/\/$/,"")}function at(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n<r&&t[n]===e[n];n++);return{updated:e.slice(0,n),activated:e.slice(n),deactivated:t.slice(n)}}function st(t,e,n,r){var o=mt(t,function(t,r,o,i){var a=ut(t,e);if(a)return Array.isArray(a)?a.map(function(t){return n(t,r,o,i)}):n(a,r,o,i)});return gt(r?o.reverse():o)}function ut(t,e){return"function"!=typeof t&&(t=At.extend(t)),t.options[e]}function ct(t){return st(t,"beforeRouteLeave",ft,!0)}function lt(t){return st(t,"beforeRouteUpdate",ft)}function ft(t,e){if(e)return function(){return t.apply(e,arguments)}}function pt(t,e,n){return st(t,"beforeRouteEnter",function(t,r,o,i){return dt(t,o,i,e,n)})}function dt(t,e,n,r,o){return function(i,a,s){return t(i,a,function(t){s(t),"function"==typeof t&&r.push(function(){ht(t,e.instances,n,o)})})}}function ht(t,e,n,r){e[n]?t(e[n]):r()&&setTimeout(function(){ht(t,e,n,r)},16)}function vt(t){return function(e,n,r){var o=!1,i=0,a=null;mt(t,function(t,e,n,s){if("function"==typeof t&&void 0===t.cid){o=!0,i++;var u,c=yt(function(e){t.resolved="function"==typeof e?e:At.extend(e),n.components[s]=e,--i<=0&&r()}),l=yt(function(t){var e="Failed to resolve async component "+s+": "+t;a||(a=bt(t)?t:new Error(e),r(a))});try{u=t(c,l)}catch(t){l(t)}if(u)if("function"==typeof u.then)u.then(c,l);else{var f=u.component;f&&"function"==typeof f.then&&f.then(c,l)}}}),o||r()}}function mt(t,e){return gt(t.map(function(t){return Object.keys(t.components).map(function(n){return e(t.components[n],t.instances[n],t,n)})}))}function gt(t){return Array.prototype.concat.apply([],t)}function yt(t){var e=!1;return function(){if(!e)return e=!0,t.apply(this,arguments)}}function bt(t){return Object.prototype.toString.call(t).indexOf("Error")>-1}function _t(t){var e=window.location.pathname;return t&&0===e.indexOf(t)&&(e=e.slice(t.length)),(e||"/")+window.location.search+window.location.hash}function wt(t){var e=_t(t);if(!/^\/#/.test(e))return window.location.replace(_(t+"/#"+e)),!0}function xt(){var t=kt();return"/"===t.charAt(0)||(Ct("/"+t),!1)}function kt(){var t=window.location.href,e=t.indexOf("#");return-1===e?"":t.slice(e+1)}function $t(t){window.location.hash=t}function Ct(t){var e=window.location.href.indexOf("#");window.location.replace(window.location.href.slice(0,e>=0?e:0)+"#"+t)}function Ot(t,e){return t.push(e),function(){var n=t.indexOf(e);n>-1&&t.splice(n,1)}}function St(t,e,n){var r="hash"===n?"#"+e:e;return t?_(t+"/"+r):r}var At,jt={name:"router-view",functional:!0,props:{name:{type:String,default:"default"}},render:function(t,e){var n=e.props,r=e.children,i=e.parent,a=e.data;a.routerView=!0;for(var s=i.$createElement,u=n.name,c=i.$route,l=i._routerViewCache||(i._routerViewCache={}),f=0,p=!1;i;)i.$vnode&&i.$vnode.data.routerView&&f++,i._inactive&&(p=!0),i=i.$parent;if(a.routerViewDepth=f,p)return s(l[u],a,r);var d=c.matched[f];if(!d)return l[u]=null,s();var h=l[u]=d.components[u];return a.registerRouteInstance=function(t,e){var n=d.instances[u];(e&&n!==t||!e&&n===t)&&(d.instances[u]=e)},(a.hook||(a.hook={})).prepatch=function(t,e){d.instances[u]=e.componentInstance},a.props=o(c,d.props&&d.props[u]),s(h,a,r)}},Et=function(t){return"%"+t.charCodeAt(0).toString(16)},Tt=function(t){return encodeURIComponent(t).replace(/[!'()*]/g,Et).replace(/%2C/g,",")},Pt=decodeURIComponent,Lt=/\/?$/,Nt=u(null,{path:"/"}),It=[String,Object],Mt=[String,Array],Rt={name:"router-link",props:{to:{type:It,required:!0},tag:{type:String,default:"a"},exact:Boolean,append:Boolean,replace:Boolean,activeClass:String,exactActiveClass:String,event:{type:Mt,default:"click"}},render:function(t){var e=this,n=this.$router,r=this.$route,o=n.resolve(this.to,r,this.append),i=o.location,a=o.route,s=o.href,c={},l=n.options.linkActiveClass,p=n.options.linkExactActiveClass,h=null==l?"router-link-active":l,g=null==p?"router-link-exact-active":p,y=null==this.activeClass?h:this.activeClass,b=null==this.exactActiveClass?g:this.exactActiveClass,_=i.path?u(null,i,null,n):a;c[b]=f(r,_),c[y]=this.exact?c[b]:d(r,_);var w=function(t){v(t)&&(e.replace?n.replace(i):n.push(i))},x={click:v};Array.isArray(this.event)?this.event.forEach(function(t){x[t]=w}):x[this.event]=w;var k={class:c};if("a"===this.tag)k.on=x,k.attrs={href:s};else{var $=m(this.$slots.default);if($){$.isStatic=!1;var C=At.util.extend;($.data=C({},$.data)).on=x;($.data.attrs=C({},$.data.attrs)).href=s}else k.on=x}return t(this.tag,k,this.$slots.default)}},Dt="undefined"!=typeof window,qt=Array.isArray||function(t){return"[object Array]"==Object.prototype.toString.call(t)},Ft=N,Ut=w,Ht=x,Bt=C,zt=L,Vt=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");Ft.parse=Ut,Ft.compile=Ht,Ft.tokensToFunction=Bt,Ft.tokensToRegExp=zt;var Wt=Object.create(null),Gt=Object.create(null),Kt=Dt&&function(){var t=window.navigator.userAgent;return(-1===t.indexOf("Android 2.")&&-1===t.indexOf("Android 4.0")||-1===t.indexOf("Mobile Safari")||-1!==t.indexOf("Chrome")||-1!==t.indexOf("Windows Phone"))&&(window.history&&"pushState"in window.history)}(),Jt=Dt&&window.performance&&window.performance.now?window.performance:Date,Zt=Q(),Yt=function(t,e){this.router=t,this.base=it(e),this.current=Nt,this.pending=null,this.ready=!1,this.readyCbs=[],this.readyErrorCbs=[],this.errorCbs=[]};Yt.prototype.listen=function(t){this.cb=t},Yt.prototype.onReady=function(t,e){this.ready?t():(this.readyCbs.push(t),e&&this.readyErrorCbs.push(e))},Yt.prototype.onError=function(t){this.errorCbs.push(t)},Yt.prototype.transitionTo=function(t,e,n){var r=this,o=this.router.match(t,this.current);this.confirmTransition(o,function(){r.updateRoute(o),e&&e(o),r.ensureURL(),r.ready||(r.ready=!0,r.readyCbs.forEach(function(t){t(o)}))},function(t){n&&n(t),t&&!r.ready&&(r.ready=!0,r.readyErrorCbs.forEach(function(e){e(t)}))})},Yt.prototype.confirmTransition=function(t,e,n){var o=this,i=this.current,a=function(t){bt(t)&&(o.errorCbs.length?o.errorCbs.forEach(function(e){e(t)}):(r(!1,"uncaught error during route navigation:"),console.error(t))),n&&n(t)};if(f(t,i)&&t.matched.length===i.matched.length)return this.ensureURL(),a();var s=at(this.current.matched,t.matched),u=s.updated,c=s.deactivated,l=s.activated,p=[].concat(ct(c),this.router.beforeHooks,lt(u),l.map(function(t){return t.beforeEnter}),vt(l));this.pending=t;var d=function(e,n){if(o.pending!==t)return a();try{e(t,i,function(t){!1===t||bt(t)?(o.ensureURL(!0),a(t)):"string"==typeof t||"object"==typeof t&&("string"==typeof t.path||"string"==typeof t.name)?(a(),"object"==typeof t&&t.replace?o.replace(t):o.push(t)):n(t)})}catch(t){a(t)}};ot(p,d,function(){var n=[];ot(pt(l,n,function(){return o.current===t}).concat(o.router.resolveHooks),d,function(){if(o.pending!==t)return a();o.pending=null,e(t),o.router.app&&o.router.app.$nextTick(function(){n.forEach(function(t){t()})})})})},Yt.prototype.updateRoute=function(t){var e=this.current;this.current=t,this.cb&&this.cb(t),this.router.afterHooks.forEach(function(n){n&&n(t,e)})};var Xt=function(t){function e(e,n){var r=this;t.call(this,e,n);var o=e.options.scrollBehavior;o&&V(),window.addEventListener("popstate",function(t){r.transitionTo(_t(r.base),function(t){o&&W(e,t,r.current,!0)})})}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.go=function(t){window.history.go(t)},e.prototype.push=function(t,e,n){var r=this,o=this,i=o.current;this.transitionTo(t,function(t){nt(_(r.base+t.fullPath)),W(r.router,t,i,!1),e&&e(t)},n)},e.prototype.replace=function(t,e,n){var r=this,o=this,i=o.current;this.transitionTo(t,function(t){rt(_(r.base+t.fullPath)),W(r.router,t,i,!1),e&&e(t)},n)},e.prototype.ensureURL=function(t){if(_t(this.base)!==this.current.fullPath){var e=_(this.base+this.current.fullPath);t?nt(e):rt(e)}},e.prototype.getCurrentLocation=function(){return _t(this.base)},e}(Yt),Qt=function(t){function e(e,n,r){t.call(this,e,n),r&&wt(this.base)||xt()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setupListeners=function(){var t=this;window.addEventListener("hashchange",function(){xt()&&t.transitionTo(kt(),function(t){Ct(t.fullPath)})})},e.prototype.push=function(t,e,n){this.transitionTo(t,function(t){$t(t.fullPath),e&&e(t)},n)},e.prototype.replace=function(t,e,n){this.transitionTo(t,function(t){Ct(t.fullPath),e&&e(t)},n)},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;kt()!==e&&(t?$t(e):Ct(e))},e.prototype.getCurrentLocation=function(){return kt()},e}(Yt),te=function(t){function e(e,n){t.call(this,e,n),this.stack=[],this.index=-1}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.push=function(t,e,n){var r=this;this.transitionTo(t,function(t){r.stack=r.stack.slice(0,r.index+1).concat(t),r.index++,e&&e(t)},n)},e.prototype.replace=function(t,e,n){var r=this;this.transitionTo(t,function(t){r.stack=r.stack.slice(0,r.index).concat(t),e&&e(t)},n)},e.prototype.go=function(t){var e=this,n=this.index+t;if(!(n<0||n>=this.stack.length)){var r=this.stack[n];this.confirmTransition(r,function(){e.index=n,e.updateRoute(r)})}},e.prototype.getCurrentLocation=function(){var t=this.stack[this.stack.length-1];return t?t.fullPath:"/"},e.prototype.ensureURL=function(){},e}(Yt),ee=function(t){void 0===t&&(t={}),this.app=null,this.apps=[],this.options=t,this.beforeHooks=[],this.resolveHooks=[],this.afterHooks=[],this.matcher=H(t.routes||[],this);var e=t.mode||"hash";switch(this.fallback="history"===e&&!Kt,this.fallback&&(e="hash"),Dt||(e="abstract"),this.mode=e,e){case"history":this.history=new Xt(this,t.base);break;case"hash":this.history=new Qt(this,t.base,this.fallback);break;case"abstract":this.history=new te(this,t.base)}},ne={currentRoute:{}};ee.prototype.match=function(t,e,n){return this.matcher.match(t,e,n)},ne.currentRoute.get=function(){return this.history&&this.history.current},ee.prototype.init=function(t){var e=this;if(this.apps.push(t),!this.app){this.app=t;var n=this.history;if(n instanceof Xt)n.transitionTo(n.getCurrentLocation());else if(n instanceof Qt){var r=function(){n.setupListeners()};n.transitionTo(n.getCurrentLocation(),r,r)}n.listen(function(t){e.apps.forEach(function(e){e._route=t})})}},ee.prototype.beforeEach=function(t){return Ot(this.beforeHooks,t)},ee.prototype.beforeResolve=function(t){return Ot(this.resolveHooks,t)},ee.prototype.afterEach=function(t){return Ot(this.afterHooks,t)},ee.prototype.onReady=function(t,e){this.history.onReady(t,e)},ee.prototype.onError=function(t){this.history.onError(t)},ee.prototype.push=function(t,e,n){this.history.push(t,e,n)},ee.prototype.replace=function(t,e,n){this.history.replace(t,e,n)},ee.prototype.go=function(t){this.history.go(t)},ee.prototype.back=function(){this.go(-1)},ee.prototype.forward=function(){this.go(1)},ee.prototype.getMatchedComponents=function(t){var e=t?t.matched?t:this.resolve(t).route:this.currentRoute;return e?[].concat.apply([],e.matched.map(function(t){return Object.keys(t.components).map(function(e){return t.components[e]})})):[]},ee.prototype.resolve=function(t,e,n){var r=F(t,e||this.history.current,n,this),o=this.match(r,e),i=o.redirectedFrom||o.fullPath;return{location:r,route:o,href:St(this.history.base,i,this.mode),normalizedTo:r,resolved:o}},ee.prototype.addRoutes=function(t){this.matcher.addRoutes(t),this.history.current!==Nt&&this.history.transitionTo(this.history.getCurrentLocation())},Object.defineProperties(ee.prototype,ne),ee.install=g,ee.version="2.5.3",Dt&&window.Vue&&window.Vue.use(ee),e.a=ee},function(t,e){function n(t,e){var r={name:t.name,path:t.path,hash:t.hash,query:t.query,params:t.params,fullPath:t.fullPath,meta:t.meta};return e&&(r.from=n(e)),Object.freeze(r)}e.sync=function(t,e,r){var o=(r||{}).moduleName||"route";t.registerModule(o,{state:n(e.currentRoute),mutations:{"router/ROUTE_CHANGED":function(e,r){t.state[o]=n(r.to,r.from)}}});var i,a=!1;t.watch(function(t){return t[o]},function(t){t.fullPath!==i&&(a=!0,i=t.fullPath,e.push(t))},{sync:!0}),e.afterEach(function(e,n){if(a)return void(a=!1);i=e.fullPath,t.commit("router/ROUTE_CHANGED",{to:e,from:n})})}},function(t,e,n){if(!window.Promise){var r=n(80);window.Promise=r}Object.assign=n(19)},function(t,e,n){t.exports=n(25)}])});
+//# sourceMappingURL=docute.js.map \ No newline at end of file
diff --git a/assets/js/prism-bash.min.js b/assets/js/prism-bash.min.js
new file mode 100644
index 00000000..ff90e9d8
--- /dev/null
+++ b/assets/js/prism-bash.min.js
@@ -0,0 +1 @@
+!function(e){var t={variable:[{pattern:/\$?\(\([\w\W]+?\)\)/,inside:{variable:[{pattern:/(^\$\(\([\w\W]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b-?(?:0x[\dA-Fa-f]+|\d*\.?\d+(?:[Ee]-?\d+)?)\b/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\([^)]+\)|`[^`]+`/,inside:{variable:/^\$\(|^`|\)$|`$/}},/\$(?:[a-z0-9_#\?\*!@]+|\{[^}]+\})/i]};e.languages.bash={shebang:{pattern:/^#!\s*\/bin\/bash|^#!\s*\/bin\/sh/,alias:"important"},comment:{pattern:/(^|[^"{\\])#.*/,lookbehind:!0},string:[{pattern:/((?:^|[^<])<<\s*)(?:"|')?(\w+?)(?:"|')?\s*\r?\n(?:[\s\S])*?\r?\n\2/g,lookbehind:!0,greedy:!0,inside:t},{pattern:/(["'])(?:\\\\|\\?[^\\])*?\1/g,greedy:!0,inside:t}],variable:t.variable,"function":{pattern:/(^|\s|;|\||&)(?:alias|apropos|apt-get|aptitude|aspell|awk|basename|bash|bc|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chmod|chown|chroot|chkconfig|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|cut|date|dc|dd|ddrescue|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|ethtool|eval|exec|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|grep|groupadd|groupdel|groupmod|groups|gzip|hash|head|help|hg|history|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|jobs|join|kill|killall|less|link|ln|locate|logname|logout|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|make|man|mkdir|mkfifo|mkisofs|mknod|more|most|mount|mtools|mtr|mv|mmv|nano|netstat|nice|nl|nohup|notify-send|npm|nslookup|open|op|passwd|paste|pathchk|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|rename|renice|remsync|rev|rm|rmdir|rsync|screen|scp|sdiff|sed|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|sync|tail|tar|tee|test|time|timeout|times|touch|top|traceroute|trap|tr|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|uptime|useradd|userdel|usermod|users|uuencode|uudecode|v|vdir|vi|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yes|zip)(?=$|\s|;|\||&)/,lookbehind:!0},keyword:{pattern:/(^|\s|;|\||&)(?:let|:|\.|if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)(?=$|\s|;|\||&)/,lookbehind:!0},"boolean":{pattern:/(^|\s|;|\||&)(?:true|false)(?=$|\s|;|\||&)/,lookbehind:!0},operator:/&&?|\|\|?|==?|!=?|<<<?|>>|<=?|>=?|=~/,punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];]/};var a=t.variable[1].inside;a["function"]=e.languages.bash["function"],a.keyword=e.languages.bash.keyword,a.boolean=e.languages.bash.boolean,a.operator=e.languages.bash.operator,a.punctuation=e.languages.bash.punctuation}(Prism); \ No newline at end of file
diff --git a/assets/js/prism-c.min.js b/assets/js/prism-c.min.js
new file mode 100644
index 00000000..30740be2
--- /dev/null
+++ b/assets/js/prism-c.min.js
@@ -0,0 +1 @@
+Prism.languages.c=Prism.languages.extend("clike",{keyword:/\b(asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,operator:/\-[>-]?|\+\+?|!=?|<<?=?|>>?=?|==?|&&?|\|?\||[~^%?*\/]/,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)[ful]*\b/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+([^\r\n\\]|\\.|\\(?:\r\n?|\n))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(<.+?>|("|')(\\?.)+?\3)/,lookbehind:!0},directive:{pattern:/(#\s*)\b(define|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,lookbehind:!0,alias:"keyword"}}},constant:/\b(__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|stdin|stdout|stderr)\b/}),delete Prism.languages.c["class-name"],delete Prism.languages.c["boolean"]; \ No newline at end of file
diff --git a/assets/js/prism-lua.min.js b/assets/js/prism-lua.min.js
new file mode 100644
index 00000000..8bf9c828
--- /dev/null
+++ b/assets/js/prism-lua.min.js
@@ -0,0 +1 @@
+Prism.languages.lua={comment:/^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)/m,string:{pattern:/(["'])(?:(?!\1)[^\\\r\n]|\\z(?:\r\n|\s)|\\(?:\r\n|[\s\S]))*\1|\[(=*)\[[\s\S]*?\]\2\]/,greedy:!0},number:/\b0x[a-f\d]+\.?[a-f\d]*(?:p[+-]?\d+)?\b|\b\d+(?:\.\B|\.?\d*(?:e[+-]?\d+)?\b)|\B\.\d+(?:e[+-]?\d+)?\b/i,keyword:/\b(?:and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,"function":/(?!\d)\w+(?=\s*(?:[({]))/,operator:[/[-+*%^&|#]|\/\/?|<[<=]?|>[>=]?|[=~]=?/,{pattern:/(^|[^.])\.\.(?!\.)/,lookbehind:!0}],punctuation:/[\[\](){},;]|\.+|:+/}; \ No newline at end of file
diff --git a/baidu_verify_cuJ4VNoBuE.html b/baidu_verify_cuJ4VNoBuE.html
new file mode 100644
index 00000000..46cb113f
--- /dev/null
+++ b/baidu_verify_cuJ4VNoBuE.html
@@ -0,0 +1 @@
+cuJ4VNoBuE \ No newline at end of file
diff --git a/cn/index.html b/cn/index.html
new file mode 100644
index 00000000..4b0cd2de
--- /dev/null
+++ b/cn/index.html
@@ -0,0 +1,237 @@
+<!DOCTYPE html>
+<html lang="en-us">
+
+ <head>
+ <meta charset="UTF-8">
+ <title>xmake</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="theme-color" content="#157878">
+ <meta name="description" content="一个基于Lua的轻量级自动构建工具">
+ <meta name="keywords" content="make,makefile,构建工具,编译工具,lua,跨平台,跨平台开发,linux,交叉编译" />
+
+ <link rel="stylesheet" href="/assets/css/normalize.css">
+ <link rel='stylesheet' href="/assets/css/opensans.css" type='text/css'>
+ <link rel="stylesheet" href="/assets/css/cayman.css">
+
+ <!-- baidu stats -->
+ <script>
+ var _hmt = _hmt || [];
+ (function() {
+ var hm = document.createElement("script");
+ hm.src = "//hm.baidu.com/hm.js?eb3c91c672a001d78a113bfb8e42017a";
+ var s = document.getElementsByTagName("script")[0];
+ s.parentNode.insertBefore(hm, s);
+ })();
+ </script>
+</head>
+
+
+ <body>
+ <section class="page-header">
+ <h1 class="project-name">xmake</h1>
+ <h2 class="project-tagline">一个基于Lua的轻量级自动构建工具</h2>
+ <a href="/#/zh/" class="btn">开始使用</a>
+ <br><br>
+ <iframe src="https://ghbtns.com/github-btn.html?user=tboox&repo=xmake&type=star&count=true" frameborder="0" scrolling="0" width="110px" height="20px"></iframe>
+ <span class="donate" style="width: 86px">
+ <img src="/assets/img/patreon.png">
+ <a href="/cn/pages/donation.html#donate">支持我们</a>
+ </span>
+ <br><br>
+<ul id="translations">
+ <li><a href="/cn/" class="nav-link">中文</a></li>
+ <li class="delimiter">|</li>
+ <li><a href="/" class="nav-link">English</a></li>
+ </ul>
+</section>
+
+
+
+ <section class="main-content">
+
+ <h2 id="section">安装</h2>
+
+<h4 id="curl">使用curl</h4>
+
+<div class="language-bash highlighter-rouge"><pre class="highlight"><code>bash &lt;<span class="o">(</span>curl -fsSL https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh<span class="o">)</span>
+</code></pre>
+</div>
+
+<h4 id="wget">使用wget</h4>
+
+<div class="language-bash highlighter-rouge"><pre class="highlight"><code>bash &lt;<span class="o">(</span>wget https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh -O -<span class="o">)</span>
+</code></pre>
+</div>
+
+<h4 id="powershell">使用powershell</h4>
+
+<div class="language-bash highlighter-rouge"><pre class="highlight"><code>Invoke-Expression <span class="o">(</span>Invoke-Webrequest <span class="s1">'https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.ps1'</span> -UseBasicParsing<span class="o">)</span>.Content
+</code></pre>
+</div>
+
+<h2 id="section-1">简单的工程描述</h2>
+
+<div class="language-lua highlighter-rouge"><pre class="highlight"><code><span class="n">target</span><span class="p">(</span><span class="s2">"console"</span><span class="p">)</span>
+ <span class="n">set_kind</span><span class="p">(</span><span class="s2">"binary"</span><span class="p">)</span>
+ <span class="n">add_files</span><span class="p">(</span><span class="s2">"src/*.c"</span><span class="p">)</span>
+</code></pre>
+</div>
+
+<h2 id="section-2">构建工程</h2>
+
+<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>xmake
+</code></pre>
+</div>
+
+<h2 id="section-3">运行目标</h2>
+
+<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>xmake run console
+</code></pre>
+</div>
+
+<h2 id="section-4">调试程序</h2>
+
+<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>xmake run -d console
+</code></pre>
+</div>
+
+<h2 id="section-5">支持特性</h2>
+
+<ul>
+ <li>Tasks</li>
+ <li>Macros</li>
+ <li>Actions</li>
+ <li>Options</li>
+ <li>Plugins</li>
+ <li>Modules</li>
+ <li>Templates</li>
+</ul>
+
+<h2 id="section-6">支持平台</h2>
+
+<ul>
+ <li>Windows (x86, x64)</li>
+ <li>Macosx (i386, x86_64)</li>
+ <li>Linux (i386, x86_64, cross-toolchains …)</li>
+ <li>Android (armv5te, armv6, armv7-a, armv8-a, arm64-v8a)</li>
+ <li>iPhoneOS (armv7, armv7s, arm64, i386, x86_64)</li>
+ <li>WatchOS (armv7k, i386)</li>
+ <li>Mingw (i386, x86_64)</li>
+</ul>
+
+<h2 id="section-7">支持语言</h2>
+
+<ul>
+ <li>C/C++</li>
+ <li>Objc/Objc++</li>
+ <li>Swift</li>
+ <li>Assembly</li>
+ <li>Golang</li>
+ <li>Rust</li>
+ <li>Dlang</li>
+</ul>
+
+<h2 id="section-8">内置插件</h2>
+
+<ul>
+ <li>宏记录脚本和回放插件</li>
+ <li>加载自定义lua脚本插件</li>
+ <li>生成IDE工程文件插件(makefile, vs2002 - vs2017, …)</li>
+ <li>生成doxygen文档插件</li>
+</ul>
+
+<h2 id="section-9">更多插件</h2>
+
+<p>请到插件仓库进行下载安装: <a href="https://github.com/tboox/xmake-plugins">xmake-plugins</a>.</p>
+
+<h2 id="section-10">更多例子</h2>
+
+<p>Debug和Release模式:</p>
+
+<div class="language-lua highlighter-rouge"><pre class="highlight"><code><span class="k">if</span> <span class="n">is_mode</span><span class="p">(</span><span class="s2">"debug"</span><span class="p">)</span> <span class="k">then</span>
+ <span class="n">set_symbols</span><span class="p">(</span><span class="s2">"debug"</span><span class="p">)</span>
+ <span class="n">set_optimize</span><span class="p">(</span><span class="s2">"none"</span><span class="p">)</span>
+<span class="k">end</span>
+
+<span class="k">if</span> <span class="n">is_mode</span><span class="p">(</span><span class="s2">"release"</span><span class="p">)</span> <span class="k">then</span>
+ <span class="n">set_symbols</span><span class="p">(</span><span class="s2">"hidden"</span><span class="p">)</span>
+ <span class="n">set_optimize</span><span class="p">(</span><span class="s2">"fastest"</span><span class="p">)</span>
+ <span class="n">set_strip</span><span class="p">(</span><span class="s2">"all"</span><span class="p">)</span>
+<span class="k">end</span>
+
+<span class="n">target</span><span class="p">(</span><span class="s2">"console"</span><span class="p">)</span>
+ <span class="n">set_kind</span><span class="p">(</span><span class="s2">"binary"</span><span class="p">)</span>
+ <span class="n">add_files</span><span class="p">(</span><span class="s2">"src/*.c"</span><span class="p">)</span>
+</code></pre>
+</div>
+
+<p>自定义脚本:</p>
+
+<div class="language-lua highlighter-rouge"><pre class="highlight"><code><span class="n">target</span><span class="p">(</span><span class="s2">"test"</span><span class="p">)</span>
+ <span class="n">set_kind</span><span class="p">(</span><span class="s2">"static"</span><span class="p">)</span>
+ <span class="n">add_files</span><span class="p">(</span><span class="s2">"src/*.cpp"</span><span class="p">)</span>
+ <span class="n">after_build</span><span class="p">(</span><span class="k">function</span> <span class="p">(</span><span class="n">target</span><span class="p">)</span>
+ <span class="nb">print</span><span class="p">(</span><span class="s2">"build %s ok!"</span><span class="p">,</span> <span class="n">target</span><span class="p">:</span><span class="n">targetfile</span><span class="p">())</span>
+ <span class="k">end</span><span class="p">)</span>
+</code></pre>
+</div>
+
+<p>使用扩展模块:</p>
+
+<div class="language-lua highlighter-rouge"><pre class="highlight"><code><span class="n">target</span><span class="p">(</span><span class="s2">"test"</span><span class="p">)</span>
+ <span class="n">set_kind</span><span class="p">(</span><span class="s2">"shared"</span><span class="p">)</span>
+ <span class="n">add_files</span><span class="p">(</span><span class="s2">"src/*.c"</span><span class="p">)</span>
+ <span class="n">on_load</span><span class="p">(</span><span class="k">function</span> <span class="p">(</span><span class="n">target</span><span class="p">)</span>
+ <span class="n">import</span><span class="p">(</span><span class="s2">"lib.detect.find_package"</span><span class="p">)</span>
+ <span class="n">target</span><span class="p">:</span><span class="n">add</span><span class="p">(</span><span class="n">find_package</span><span class="p">(</span><span class="s2">"zlib"</span><span class="p">))</span>
+ <span class="k">end</span><span class="p">)</span>
+</code></pre>
+</div>
+
+<h2 id="section-11">项目例子</h2>
+
+<p>一些使用xmake的项目:</p>
+
+<ul>
+ <li><a href="https://github.com/tboox/tbox">tbox</a></li>
+ <li><a href="https://github.com/tboox/gbox">gbox</a></li>
+ <li><a href="https://github.com/tboox/vm86">vm86</a></li>
+ <li><a href="https://github.com/vm86/xmake/wiki/%E4%BD%BF%E7%94%A8xmake%E7%9A%84%E5%BC%80%E6%BA%90%E5%BA%93">更多</a></li>
+</ul>
+
+<h2 id="section-12">演示视频</h2>
+
+<p><a href="https://asciinema.org/a/133693"><img src="https://asciinema.org/a/133693.png" alt="asciicast" /></a></p>
+
+<h2 id="section-13">联系方式</h2>
+
+<ul>
+ <li>邮箱:<a href="mailto:waruqi@gmail.com">waruqi@gmail.com</a></li>
+ <li>主页:<a href="http://www.tboox.org/cn">tboox.org</a></li>
+ <li>社区:<a href="https://github.com/tboox/community/issues">TBOOX开源社区</a></li>
+ <li>聊天:<a href="https://gitter.im/tboox/tboox?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge"><img src="https://badges.gitter.im/tboox/tboox.svg" alt="Join the chat at https://gitter.im/tboox/tboox" /></a></li>
+ <li>源码:<a href="https://github.com/tboox/xmake">Github</a>, <a href="https://gitee.com/tboox/xmake">Gitee</a></li>
+ <li>QQ群:343118190</li>
+ <li>微信公众号:tboox-os</li>
+</ul>
+
+
+
+ <footer class="site-footer">
+ <span class="site-footer-owner">Copyright (c) 2015-2017 <a href="http://www.tboox.org">tboox.org</a>.</span>
+ <span class="site-footer-power">
+ <span>
+ <!--Site powered by <a href="https://jekyllrb.com/">Jekyll</a> & <a href="http://pages.coding.me">Coding Pages</a>.-->
+ Site powered by <a href="https://jekyllrb.com/">Jekyll</a> & <a href="https://pages.github.com/">Github Pages</a>.
+ </span>
+ <span>
+ Theme designed by <a href="https://github.com/pietromenna/jekyll-cayman-theme">cayman</a>.
+ </span>
+</span>
+</footer>
+
+
+ </section>
+
+ </body>
+</html>
diff --git a/cn/pages/donation.html b/cn/pages/donation.html
new file mode 100644
index 00000000..05ddca97
--- /dev/null
+++ b/cn/pages/donation.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<html lang="en-us">
+
+ <head>
+ <meta charset="UTF-8">
+ <title>xmake</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="theme-color" content="#157878">
+ <meta name="description" content="一个基于Lua的轻量级自动构建工具">
+ <meta name="keywords" content="make,makefile,构建工具,编译工具,lua,跨平台,跨平台开发,linux,交叉编译" />
+
+ <link rel="stylesheet" href="/assets/css/normalize.css">
+ <link rel='stylesheet' href="/assets/css/opensans.css" type='text/css'>
+ <link rel="stylesheet" href="/assets/css/cayman.css">
+
+ <!-- baidu stats -->
+ <script>
+ var _hmt = _hmt || [];
+ (function() {
+ var hm = document.createElement("script");
+ hm.src = "//hm.baidu.com/hm.js?eb3c91c672a001d78a113bfb8e42017a";
+ var s = document.getElementsByTagName("script")[0];
+ s.parentNode.insertBefore(hm, s);
+ })();
+ </script>
+</head>
+
+
+ <body>
+ <section class="page-header">
+ <h1 class="project-name">xmake</h1>
+ <h2 class="project-tagline">一个基于Lua的轻量级自动构建工具</h2>
+ <a href="/#/zh/" class="btn">开始使用</a>
+ <br><br>
+ <iframe src="https://ghbtns.com/github-btn.html?user=tboox&repo=xmake&type=star&count=true" frameborder="0" scrolling="0" width="110px" height="20px"></iframe>
+ <span class="donate" style="width: 86px">
+ <img src="/assets/img/patreon.png">
+ <a href="/cn/pages/donation.html#donate">支持我们</a>
+ </span>
+ <br><br>
+<ul id="translations">
+ <li><a href="/cn/" class="nav-link">中文</a></li>
+ <li class="delimiter">|</li>
+ <li><a href="/" class="nav-link">English</a></li>
+ </ul>
+</section>
+
+
+
+ <section class="main-content">
+
+ <div id="donate"></div>
+
+<p>xmake项目属于个人开源项目,它的发展需要您的帮助,如果您愿意支持xmake项目的开发,欢迎为其捐赠,支持它的发展。</p>
+
+<h2 id="section">支付宝</h2>
+
+<p><img src="/assets/img/alipay.png" alt="alipay" width="256" height="256" /></p>
+
+<p>账号:waruqi@gmail.com</p>
+
+<h2 id="section-1">微信</h2>
+
+<p><img src="/assets/img/weixin.png" alt="weixin" width="218" height="218" /></p>
+
+<h2 id="paypal">Paypal</h2>
+
+<p><a href="http://paypal.me/tboox/5"><img src="/assets/img/paypal.png" alt="Paypal Me" /></a></p>
+
+<h2 id="section-2">支持者</h2>
+
+<p><a href="https://opencollective.com/xmake#backers" target="_blank"><img src="https://opencollective.com/xmake/backers.svg?width=890" /></a></p>
+
+<table>
+ <tbody>
+ <tr>
+ <td>2016.11.10</td>
+ <td><a href="https://github.com/lc-soft">lc-soft</a></td>
+ <td>oschina</td>
+ <td>¥10</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="section-3">赞助者</h2>
+
+<p>通过赞助支持此项目,您的logo和网站链接将显示在这里。[<a href="https://opencollective.com/xmake#sponsor">赞助此项目</a>]</p>
+
+<p><a href="https://opencollective.com/xmake/sponsor/0/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/0/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/1/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/1/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/2/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/2/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/3/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/3/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/4/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/4/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/5/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/5/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/6/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/6/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/7/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/7/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/8/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/8/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/9/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/9/avatar.svg" /></a></p>
+
+
+
+ <footer class="site-footer">
+ <span class="site-footer-owner">Copyright (c) 2015-2017 <a href="http://www.tboox.org">tboox.org</a>.</span>
+ <span class="site-footer-power">
+ <span>
+ <!--Site powered by <a href="https://jekyllrb.com/">Jekyll</a> & <a href="http://pages.coding.me">Coding Pages</a>.-->
+ Site powered by <a href="https://jekyllrb.com/">Jekyll</a> & <a href="https://pages.github.com/">Github Pages</a>.
+ </span>
+ <span>
+ Theme designed by <a href="https://github.com/pietromenna/jekyll-cayman-theme">cayman</a>.
+ </span>
+</span>
+</footer>
+
+
+ </section>
+
+ </body>
+</html>
diff --git a/config.js b/config.js
new file mode 100644
index 00000000..23330040
--- /dev/null
+++ b/config.js
@@ -0,0 +1,76 @@
+const langs = [
+ {title: 'English', path: '/home'},
+ {title: '中文', path: '/zh/'},
+]
+
+docute.init({
+ landing: true,
+ repo: 'tboox/xmake',
+ twitter: 'waruqi',
+ url: 'http://xmake.io',
+ 'edit-link': 'https://github.com/tboox/xmake-docs/blob/master/docs',
+ announcement(route) {
+ const info = { type: 'success' }
+ if (/\/zh/.test(route.path)) {
+ info.html = '<a style="margin-right:10px;" class="docute-button docute-button-mini docute-button-success" href="/cn/pages/donation.html#donate" target="_blank">捐赠!</a> 通过成为赞助商或者一次性捐赠支持xmake的开发和文档更新。'
+ } else {
+ info.html = '<a style="margin-right:10px;" class="docute-button docute-button-mini docute-button-success" href="/pages/donation.html#donate" target="_blank">Donate!</a> Support xmake development and documentation updates by becoming a sponsor or one-time donation.'
+ }
+ return info
+ },
+ nav: {
+ default: [
+ {
+ title: 'Home', path: '/home'
+ },
+ {
+ title: 'Plugins', path: '/plugins'
+ },
+ {
+ title: 'Manual', path: '/manual'
+ },
+ {
+ title: 'Articles', path: 'http://www.tboox.org/category/#xmake'
+ },
+ {
+ title: 'Feedback', path: 'https://github.com/tboox/xmake/issues'
+ },
+ {
+ title: 'Community', path: 'https://github.com/tboox/community/issues'
+ },
+ {
+ title: 'English', type: 'dropdown', items: langs, exact: true
+ }
+ ],
+ 'zh': [
+ {
+ title: '首页', path: '/zh/'
+ },
+ {
+ title: '插件', path: '/zh/plugins'
+ },
+ {
+ title: '手册', path: '/zh/manual'
+ },
+ {
+ title: '文章', path: 'http://www.tboox.org/cn/category/#xmake'
+ },
+ {
+ title: '反馈', path: 'https://github.com/tboox/xmake/issues'
+ },
+ {
+ title: '社区', path: 'https://github.com/tboox/community/issues'
+ },
+ {
+ title: '中文', type: 'dropdown', items: langs, exact: true
+ }
+ ]
+ },
+ plugins: [
+ docsearch({
+ apiKey: 'fbba61eefc60a833d8caf1fa72bd8ef8',
+ indexName: 'xmake',
+ tags: ['en', 'zh']
+ })
+ ]
+})
diff --git a/favicon.ico b/favicon.ico
new file mode 100644
index 00000000..52c8ef38
--- /dev/null
+++ b/favicon.ico
Binary files differ
diff --git a/index.html b/index.html
new file mode 100644
index 00000000..9d1c5b46
--- /dev/null
+++ b/index.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
+ <title>xmake</title>
+ <link rel="stylesheet" href="/assets/css/docute.css">
+</head>
+<body>
+ <!-- don't remove this part start -->
+ <div id="app"></div>
+ <script src="/assets/js/docsearch.js"></script>
+ <script src="/assets/js/docute.js"></script>
+ <script src="./config.js"></script>
+ <!-- don't remove this part end -->
+ <script src="/assets/js/prism-c.min.js"></script>
+ <script src="/assets/js/prism-lua.min.js"></script>
+ <script src="/assets/js/prism-bash.min.js"></script>
+ <!-- baidu stats -->
+ <script>
+ var _hmt = _hmt || [];
+ (function() {
+ var hm = document.createElement("script");
+ hm.src = "//hm.baidu.com/hm.js?eb3c91c672a001d78a113bfb8e42017a";
+ var s = document.getElementsByTagName("script")[0];
+ s.parentNode.insertBefore(hm, s);
+ })();
+ </script>
+</body>
+</html>
diff --git a/landing.html b/landing.html
new file mode 100644
index 00000000..79cb86df
--- /dev/null
+++ b/landing.html
@@ -0,0 +1,234 @@
+<!DOCTYPE html>
+<html lang="en-us">
+
+ <head>
+ <meta charset="UTF-8">
+ <title>xmake</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="theme-color" content="#157878">
+ <meta name="description" content="A cross-platform build utility based on Lua">
+ <meta name="keywords" content="make,makefile,build,lua,cross-compile,linux" />
+
+ <link rel="stylesheet" href="/assets/css/normalize.css">
+ <link rel='stylesheet' href="/assets/css/opensans.css" type='text/css'>
+ <link rel="stylesheet" href="/assets/css/cayman.css">
+
+ <!-- baidu stats -->
+ <script>
+ var _hmt = _hmt || [];
+ (function() {
+ var hm = document.createElement("script");
+ hm.src = "//hm.baidu.com/hm.js?eb3c91c672a001d78a113bfb8e42017a";
+ var s = document.getElementsByTagName("script")[0];
+ s.parentNode.insertBefore(hm, s);
+ })();
+ </script>
+</head>
+
+
+ <body>
+ <section class="page-header">
+ <h1 class="project-name">xmake</h1>
+ <h2 class="project-tagline">A cross-platform build utility based on Lua</h2>
+ <a href="/#/home" class="btn">GET STARTED</a>
+ <br><br>
+ <iframe src="https://ghbtns.com/github-btn.html?user=tboox&repo=xmake&type=star&count=true" frameborder="0" scrolling="0" width="110px" height="20px"></iframe>
+ <span class="donate" style="width: 100px">
+ <img src="/assets/img/patreon.png">
+ <a href="/pages/donation.html#donate">Support us</a>
+ </span>
+ <br><br>
+ <ul id="translations">
+ <li><a href="/cn/" class="nav-link">中文</a></li>
+ <li class="delimiter">|</li>
+ <li><a href="/" class="nav-link">English</a></li>
+ </ul>
+</section>
+
+
+
+ <section class="main-content">
+
+ <h2 id="installation">Installation</h2>
+
+<h4 id="via-curl">via curl</h4>
+
+<div class="language-bash highlighter-rouge"><pre class="highlight"><code>bash &lt;<span class="o">(</span>curl -fsSL https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh<span class="o">)</span>
+</code></pre>
+</div>
+
+<h4 id="via-wget">via wget</h4>
+
+<div class="language-bash highlighter-rouge"><pre class="highlight"><code>bash &lt;<span class="o">(</span>wget https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh -O -<span class="o">)</span>
+</code></pre>
+</div>
+
+<h4 id="via-powershell">via powershell</h4>
+
+<div class="language-bash highlighter-rouge"><pre class="highlight"><code>Invoke-Expression <span class="o">(</span>Invoke-Webrequest <span class="s1">'https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.ps1'</span> -UseBasicParsing<span class="o">)</span>.Content
+</code></pre>
+</div>
+
+<h2 id="simple-description">Simple description</h2>
+
+<div class="language-lua highlighter-rouge"><pre class="highlight"><code><span class="n">target</span><span class="p">(</span><span class="s2">"console"</span><span class="p">)</span>
+ <span class="n">set_kind</span><span class="p">(</span><span class="s2">"binary"</span><span class="p">)</span>
+ <span class="n">add_files</span><span class="p">(</span><span class="s2">"src/*.c"</span><span class="p">)</span>
+</code></pre>
+</div>
+
+<h2 id="build-project">Build project</h2>
+
+<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>xmake
+</code></pre>
+</div>
+
+<h2 id="run-target">Run target</h2>
+
+<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>xmake run console
+</code></pre>
+</div>
+
+<h2 id="debug-target">Debug target</h2>
+
+<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>xmake run -d console
+</code></pre>
+</div>
+
+<h2 id="support-features">Support features</h2>
+
+<ul>
+ <li>Tasks</li>
+ <li>Macros</li>
+ <li>Actions</li>
+ <li>Options</li>
+ <li>Plugins</li>
+ <li>Modules</li>
+ <li>Templates</li>
+</ul>
+
+<h2 id="support-platforms">Support platforms</h2>
+
+<ul>
+ <li>Windows (x86, x64)</li>
+ <li>Macosx (i386, x86_64)</li>
+ <li>Linux (i386, x86_64, cross-toolchains …)</li>
+ <li>Android (armv5te, armv6, armv7-a, armv8-a, arm64-v8a)</li>
+ <li>iPhoneOS (armv7, armv7s, arm64, i386, x86_64)</li>
+ <li>WatchOS (armv7k, i386)</li>
+ <li>Mingw (i386, x86_64)</li>
+</ul>
+
+<h2 id="support-languages">Support Languages</h2>
+
+<ul>
+ <li>C/C++</li>
+ <li>Objc/Objc++</li>
+ <li>Swift</li>
+ <li>Assembly</li>
+ <li>Golang</li>
+ <li>Rust</li>
+ <li>Dlang</li>
+</ul>
+
+<h2 id="builtin-plugins">Builtin Plugins</h2>
+
+<ul>
+ <li>Macros script plugin</li>
+ <li>Run the custom lua script plugin</li>
+ <li>Generate IDE project file plugin(makefile, vs2002 - vs2017 .. )</li>
+ <li>Generate doxygen document plugin</li>
+</ul>
+
+<h2 id="more-plugins">More Plugins</h2>
+
+<p>Please download and install from the plugins repository <a href="https://github.com/tboox/xmake-plugins">xmake-plugins</a>.</p>
+
+<h2 id="more-examples">More Examples</h2>
+
+<p>Debug and release modes:</p>
+
+<div class="language-lua highlighter-rouge"><pre class="highlight"><code><span class="k">if</span> <span class="n">is_mode</span><span class="p">(</span><span class="s2">"debug"</span><span class="p">)</span> <span class="k">then</span>
+ <span class="n">set_symbols</span><span class="p">(</span><span class="s2">"debug"</span><span class="p">)</span>
+ <span class="n">set_optimize</span><span class="p">(</span><span class="s2">"none"</span><span class="p">)</span>
+<span class="k">end</span>
+
+<span class="k">if</span> <span class="n">is_mode</span><span class="p">(</span><span class="s2">"release"</span><span class="p">)</span> <span class="k">then</span>
+ <span class="n">set_symbols</span><span class="p">(</span><span class="s2">"hidden"</span><span class="p">)</span>
+ <span class="n">set_optimize</span><span class="p">(</span><span class="s2">"fastest"</span><span class="p">)</span>
+ <span class="n">set_strip</span><span class="p">(</span><span class="s2">"all"</span><span class="p">)</span>
+<span class="k">end</span>
+
+<span class="n">target</span><span class="p">(</span><span class="s2">"console"</span><span class="p">)</span>
+ <span class="n">set_kind</span><span class="p">(</span><span class="s2">"binary"</span><span class="p">)</span>
+ <span class="n">add_files</span><span class="p">(</span><span class="s2">"src/*.c"</span><span class="p">)</span>
+</code></pre>
+</div>
+
+<p>Custom script:</p>
+
+<div class="language-lua highlighter-rouge"><pre class="highlight"><code><span class="n">target</span><span class="p">(</span><span class="s2">"test"</span><span class="p">)</span>
+ <span class="n">set_kind</span><span class="p">(</span><span class="s2">"static"</span><span class="p">)</span>
+ <span class="n">add_files</span><span class="p">(</span><span class="s2">"src/*.cpp"</span><span class="p">)</span>
+ <span class="n">after_build</span><span class="p">(</span><span class="k">function</span> <span class="p">(</span><span class="n">target</span><span class="p">)</span>
+ <span class="nb">print</span><span class="p">(</span><span class="s2">"build %s ok!"</span><span class="p">,</span> <span class="n">target</span><span class="p">:</span><span class="n">targetfile</span><span class="p">())</span>
+ <span class="k">end</span><span class="p">)</span>
+</code></pre>
+</div>
+
+<p>Extension Modules:</p>
+
+<div class="language-lua highlighter-rouge"><pre class="highlight"><code><span class="n">target</span><span class="p">(</span><span class="s2">"test"</span><span class="p">)</span>
+ <span class="n">set_kind</span><span class="p">(</span><span class="s2">"shared"</span><span class="p">)</span>
+ <span class="n">add_files</span><span class="p">(</span><span class="s2">"src/*.c"</span><span class="p">)</span>
+ <span class="n">on_load</span><span class="p">(</span><span class="k">function</span> <span class="p">(</span><span class="n">target</span><span class="p">)</span>
+ <span class="n">import</span><span class="p">(</span><span class="s2">"lib.detect.find_package"</span><span class="p">)</span>
+ <span class="n">target</span><span class="p">:</span><span class="n">add</span><span class="p">(</span><span class="n">find_package</span><span class="p">(</span><span class="s2">"zlib"</span><span class="p">))</span>
+ <span class="k">end</span><span class="p">)</span>
+</code></pre>
+</div>
+
+<h2 id="project-examples">Project Examples</h2>
+
+<p>Some projects using xmake:</p>
+
+<ul>
+ <li><a href="https://github.com/tboox/tbox">tbox</a></li>
+ <li><a href="https://github.com/tboox/gbox">gbox</a></li>
+ <li><a href="https://github.com/tboox/vm86">vm86</a></li>
+ <li><a href="https://github.com/tboox/xmake/wiki/xmake-projects">more</a></li>
+</ul>
+
+<h2 id="example-video">Example Video</h2>
+
+<p><a href="https://asciinema.org/a/133693"><img src="https://asciinema.org/a/133693.png" alt="asciicast" /></a></p>
+
+<h2 id="contacts">Contacts</h2>
+
+<ul>
+ <li>Email:<a href="mailto:waruqi@gmail.com">waruqi@gmail.com</a></li>
+ <li>Homepage:<a href="http://www.tboox.org">tboox.org</a></li>
+ <li>Community:<a href="https://github.com/tboox/community/issues">tboox@community</a></li>
+ <li>ChatRoom:<a href="https://gitter.im/tboox/tboox?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge"><img src="https://badges.gitter.im/tboox/tboox.svg" alt="Join the chat at https://gitter.im/tboox/tboox" /></a></li>
+ <li>Source Code:<a href="https://github.com/tboox/xmake">Github</a>, <a href="https://gitee.com/tboox/xmake">Gitee</a></li>
+</ul>
+
+
+ <footer class="site-footer">
+ <span class="site-footer-owner">Copyright (c) 2015-2017 <a href="http://www.tboox.org">tboox.org</a>.</span>
+ <span class="site-footer-power">
+ <span>
+ <!--Site powered by <a href="https://jekyllrb.com/">Jekyll</a> & <a href="http://pages.coding.me">Coding Pages</a>.-->
+ Site powered by <a href="https://jekyllrb.com/">Jekyll</a> & <a href="https://pages.github.com/">Github Pages</a>.
+ </span>
+ <span>
+ Theme designed by <a href="https://github.com/pietromenna/jekyll-cayman-theme">cayman</a>.
+ </span>
+</span>
+</footer>
+
+
+ </section>
+
+ </body>
+</html>
diff --git a/landing/README.md b/landing/README.md
new file mode 100644
index 00000000..228eebfb
--- /dev/null
+++ b/landing/README.md
@@ -0,0 +1,21 @@
+# xmake.io
+
+This is a [Jekyll][1] theme for [@jasonlong][2]'s [Cayman theme][4] on [GitHub Pages][3].
+
+# Developing
+
+Start a local server at localhost:4000:
+
+```
+$ jekyll serve
+```
+
+# Publishing site
+
+```
+$ ./build
+```
+
+For more details read about [Jekyll][1] on its web page.
+
+
diff --git a/landing/_config.yml b/landing/_config.yml
new file mode 100644
index 00000000..4c46dd42
--- /dev/null
+++ b/landing/_config.yml
@@ -0,0 +1,21 @@
+# Setup
+title: xmake
+tagline: A make-like build utility based on Lua
+tagline-cn: 一个基于Lua的轻量级自动构建工具
+keywords: make,makefile,build,lua,cross-compile,linux
+keywords-cn: make,makefile,构建工具,编译工具,lua,跨平台,跨平台开发,linux,交叉编译
+baseurl: ""
+paginate: 1
+
+# About/contact
+author:
+ name: waruqi
+ url: http://www.tboox.org
+
+#Others
+markdown: kramdown
+
+# multiple-languages
+gems: ['jekyll-paginate', 'jekyll-multiple-languages']
+languages: ['en', 'cn']
+language_default: 'en'
diff --git a/landing/_includes/head.cn.html b/landing/_includes/head.cn.html
new file mode 100644
index 00000000..c99dc89e
--- /dev/null
+++ b/landing/_includes/head.cn.html
@@ -0,0 +1,23 @@
+<head>
+ <meta charset="UTF-8">
+ <title>{{ site.title }}</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="theme-color" content="#157878">
+ <meta name="description" content="{{site.tagline-cn}}">
+ <meta name="keywords" content="{{site.keywords-cn}}" />
+
+ <link rel="stylesheet" href="{{ site.baseurl }}/assets/css/normalize.css">
+ <link rel='stylesheet' href="{{ site.baseurl }}/assets/css/opensans.css" type='text/css'>
+ <link rel="stylesheet" href="{{ site.baseurl }}/assets/css/cayman.css">
+
+ <!-- baidu stats -->
+ <script>
+ var _hmt = _hmt || [];
+ (function() {
+ var hm = document.createElement("script");
+ hm.src = "//hm.baidu.com/hm.js?eb3c91c672a001d78a113bfb8e42017a";
+ var s = document.getElementsByTagName("script")[0];
+ s.parentNode.insertBefore(hm, s);
+ })();
+ </script>
+</head>
diff --git a/landing/_includes/head.html b/landing/_includes/head.html
new file mode 100644
index 00000000..77eaa8d4
--- /dev/null
+++ b/landing/_includes/head.html
@@ -0,0 +1,23 @@
+<head>
+ <meta charset="UTF-8">
+ <title>{{ site.title }}</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="theme-color" content="#157878">
+ <meta name="description" content="{{site.tagline}}">
+ <meta name="keywords" content="{{site.keywords}}" />
+
+ <link rel="stylesheet" href="{{ site.baseurl }}/assets/css/normalize.css">
+ <link rel='stylesheet' href="{{ site.baseurl }}/assets/css/opensans.css" type='text/css'>
+ <link rel="stylesheet" href="{{ site.baseurl }}/assets/css/cayman.css">
+
+ <!-- baidu stats -->
+ <script>
+ var _hmt = _hmt || [];
+ (function() {
+ var hm = document.createElement("script");
+ hm.src = "//hm.baidu.com/hm.js?eb3c91c672a001d78a113bfb8e42017a";
+ var s = document.getElementsByTagName("script")[0];
+ s.parentNode.insertBefore(hm, s);
+ })();
+ </script>
+</head>
diff --git a/landing/_includes/page-footer.html b/landing/_includes/page-footer.html
new file mode 100644
index 00000000..bb306a49
--- /dev/null
+++ b/landing/_includes/page-footer.html
@@ -0,0 +1,12 @@
+<footer class="site-footer">
+ <span class="site-footer-owner">Copyright (c) 2015-2017 <a href="{{ site.author.url }}">tboox.org</a>.</span>
+ <span class="site-footer-power">
+ <span>
+ <!--Site powered by <a href="https://jekyllrb.com/">Jekyll</a> & <a href="http://pages.coding.me">Coding Pages</a>.-->
+ Site powered by <a href="https://jekyllrb.com/">Jekyll</a> & <a href="https://pages.github.com/">Github Pages</a>.
+ </span>
+ <span>
+ Theme designed by <a href="https://github.com/pietromenna/jekyll-cayman-theme">cayman</a>.
+ </span>
+</span>
+</footer>
diff --git a/landing/_includes/page-header.cn.html b/landing/_includes/page-header.cn.html
new file mode 100644
index 00000000..e58830f0
--- /dev/null
+++ b/landing/_includes/page-header.cn.html
@@ -0,0 +1,18 @@
+<section class="page-header">
+ <h1 class="project-name">{{ site.title }}</h1>
+ <h2 class="project-tagline">{{ site.tagline-cn }}</h2>
+ <a href="/#/zh/" class="btn">开始使用</a>
+ <br><br>
+ <iframe src="https://ghbtns.com/github-btn.html?user=tboox&repo=xmake&type=star&count=true" frameborder="0" scrolling="0" width="110px" height="20px"></iframe>
+ <span class="donate" style="width: 86px">
+ <img src="{{site.baseurl}}/assets/img/patreon.png">
+ <a href="{{site.baseurl}}/cn/pages/donation.html#donate">支持我们</a>
+ </span>
+ <br><br>
+<ul id="translations">
+ <li><a href="{{site.baseurl}}/cn/" class="nav-link">中文</a></li>
+ <li class="delimiter">|</li>
+ <li><a href="{{site.baseurl}}/" class="nav-link">English</a></li>
+ </ul>
+</section>
+
diff --git a/landing/_includes/page-header.html b/landing/_includes/page-header.html
new file mode 100644
index 00000000..8ebabfb7
--- /dev/null
+++ b/landing/_includes/page-header.html
@@ -0,0 +1,18 @@
+<section class="page-header">
+ <h1 class="project-name">{{ site.title }}</h1>
+ <h2 class="project-tagline">{{ site.tagline }}</h2>
+ <a href="/#/home" class="btn">GET STARTED</a>
+ <br><br>
+ <iframe src="https://ghbtns.com/github-btn.html?user=tboox&repo=xmake&type=star&count=true" frameborder="0" scrolling="0" width="110px" height="20px"></iframe>
+ <span class="donate" style="width: 100px">
+ <img src="{{site.baseurl}}/assets/img/patreon.png">
+ <a href="{{site.baseurl}}/pages/donation.html#donate">Support us</a>
+ </span>
+ <br><br>
+ <ul id="translations">
+ <li><a href="{{site.baseurl}}/cn/" class="nav-link">中文</a></li>
+ <li class="delimiter">|</li>
+ <li><a href="{{site.baseurl}}/" class="nav-link">English</a></li>
+ </ul>
+</section>
+
diff --git a/landing/_layouts/default.cn.html b/landing/_layouts/default.cn.html
new file mode 100644
index 00000000..82da5f6c
--- /dev/null
+++ b/landing/_layouts/default.cn.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en-us">
+
+ {% include head.cn.html %}
+
+ <body>
+ {% include page-header.cn.html %}
+
+ <section class="main-content">
+
+ {{ content }}
+
+ {% include page-footer.html %}
+
+ </section>
+
+ </body>
+</html>
diff --git a/landing/_layouts/default.html b/landing/_layouts/default.html
new file mode 100644
index 00000000..8a21bd71
--- /dev/null
+++ b/landing/_layouts/default.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en-us">
+
+ {% include head.html %}
+
+ <body>
+ {% include page-header.html %}
+
+ <section class="main-content">
+
+ {{ content }}
+
+ {% include page-footer.html %}
+
+ </section>
+
+ </body>
+</html>
diff --git a/landing/_layouts/post.html b/landing/_layouts/post.html
new file mode 100644
index 00000000..5b12153c
--- /dev/null
+++ b/landing/_layouts/post.html
@@ -0,0 +1,7 @@
+---
+layout: default
+---
+<h2>{{ page.title }}</h2>
+<p class="meta">{{ page.date | date_to_string }}</p>
+
+{{ content }} \ No newline at end of file
diff --git a/landing/_posts/donation.md b/landing/_posts/donation.md
new file mode 100644
index 00000000..c17f1d89
--- /dev/null
+++ b/landing/_posts/donation.md
@@ -0,0 +1,6 @@
+---
+layout: default
+title: {{ site.name }}
+---
+
+oasdad
diff --git a/landing/assets/css/cayman.css b/landing/assets/css/cayman.css
new file mode 100644
index 00000000..b67d1e8f
--- /dev/null
+++ b/landing/assets/css/cayman.css
@@ -0,0 +1,320 @@
+* {
+ box-sizing: border-box; }
+
+body {
+ padding: 0;
+ margin: 0;
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 16px;
+ line-height: 1.5;
+ color: #606c71; }
+
+a {
+ color: #1e6bb8;
+ text-decoration: none; }
+ a:hover {
+ text-decoration: underline; }
+
+.btn {
+ display: inline-block;
+ margin-bottom: 1rem;
+ color: rgba(255, 255, 255, 0.7);
+ background-color: rgba(255, 255, 255, 0.08);
+ border-color: rgba(255, 255, 255, 0.2);
+ border-style: solid;
+ border-width: 1px;
+ border-radius: 0.3rem;
+ transition: color 0.2s, background-color 0.2s, border-color 0.2s; }
+ .btn:hover {
+ color: rgba(255, 255, 255, 0.8);
+ text-decoration: none;
+ background-color: rgba(255, 255, 255, 0.2);
+ border-color: rgba(255, 255, 255, 0.3); }
+ .btn + .btn {
+ margin-left: 1rem; }
+ @media screen and (min-width: 64em) {
+ .btn {
+ padding: 0.75rem 1rem; } }
+ @media screen and (min-width: 42em) and (max-width: 64em) {
+ .btn {
+ padding: 0.6rem 0.9rem;
+ font-size: 0.9rem; } }
+ @media screen and (max-width: 42em) {
+ .btn {
+ display: block;
+ width: 100%;
+ padding: 0.75rem;
+ font-size: 0.9rem; }
+ .btn + .btn {
+ margin-top: 1rem;
+ margin-left: 0; } }
+
+.page-header {
+ color: #fff;
+ text-align: center;
+ background-color: #159957;
+ background-image: linear-gradient(120deg, #155799, #159957); }
+ @media screen and (min-width: 64em) {
+ .page-header {
+ padding: 5rem 6rem; } }
+ @media screen and (min-width: 42em) and (max-width: 64em) {
+ .page-header {
+ padding: 3rem 4rem; } }
+ @media screen and (max-width: 42em) {
+ .page-header {
+ padding: 2rem 1rem; } }
+
+.project-name {
+ margin-top: 0;
+ margin-bottom: 0.1rem; }
+ @media screen and (min-width: 64em) {
+ .project-name {
+ font-size: 3.25rem; } }
+ @media screen and (min-width: 42em) and (max-width: 64em) {
+ .project-name {
+ font-size: 2.25rem; } }
+ @media screen and (max-width: 42em) {
+ .project-name {
+ font-size: 1.75rem; } }
+
+.project-tagline {
+ margin-bottom: 2rem;
+ font-weight: normal;
+ opacity: 0.7; }
+ @media screen and (min-width: 64em) {
+ .project-tagline {
+ font-size: 1.25rem; } }
+ @media screen and (min-width: 42em) and (max-width: 64em) {
+ .project-tagline {
+ font-size: 1.15rem; } }
+ @media screen and (max-width: 42em) {
+ .project-tagline {
+ font-size: 1rem; } }
+
+.main-content {
+ word-wrap: break-word; }
+ .main-content :first-child {
+ margin-top: 0; }
+ @media screen and (min-width: 64em) {
+ .main-content {
+ max-width: 64rem;
+ padding: 2rem 6rem;
+ margin: 0 auto;
+ font-size: 1.1rem; } }
+ @media screen and (min-width: 42em) and (max-width: 64em) {
+ .main-content {
+ padding: 2rem 4rem;
+ font-size: 1.1rem; } }
+ @media screen and (max-width: 42em) {
+ .main-content {
+ padding: 2rem 1rem;
+ font-size: 1rem; } }
+ .main-content img {
+ max-width: 100%; }
+ .main-content h1,
+ .main-content h2,
+ .main-content h3,
+ .main-content h4,
+ .main-content h5,
+ .main-content h6 {
+ margin-top: 2rem;
+ margin-bottom: 1rem;
+ font-weight: normal;
+ color: #159957; }
+ .main-content p {
+ margin-bottom: 1em; }
+ .main-content code {
+ padding: 2px 4px;
+ font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
+ font-size: 0.9rem;
+ color: #567482;
+ background-color: #f3f6fa;
+ border-radius: 0.3rem; }
+ .main-content pre {
+ padding: 0.8rem;
+ margin-top: 0;
+ margin-bottom: 1rem;
+ font: 1rem Consolas, "Liberation Mono", Menlo, Courier, monospace;
+ color: #567482;
+ word-wrap: normal;
+ background-color: #f3f6fa;
+ border: solid 1px #dce6f0;
+ border-radius: 0.3rem; }
+ .main-content pre > code {
+ padding: 0;
+ margin: 0;
+ font-size: 0.9rem;
+ color: #567482;
+ word-break: normal;
+ white-space: pre;
+ background: transparent;
+ border: 0; }
+ .main-content .highlight {
+ margin-bottom: 1rem; }
+ .main-content .highlight pre {
+ margin-bottom: 0;
+ word-break: normal; }
+ .main-content .highlight pre,
+ .main-content pre {
+ padding: 0.8rem;
+ overflow: auto;
+ font-size: 0.9rem;
+ line-height: 1.45;
+ border-radius: 0.3rem;
+ -webkit-overflow-scrolling: touch; }
+ .main-content pre code,
+ .main-content pre tt {
+ display: inline;
+ max-width: initial;
+ padding: 0;
+ margin: 0;
+ overflow: initial;
+ line-height: inherit;
+ word-wrap: normal;
+ background-color: transparent;
+ border: 0; }
+ .main-content pre code:before, .main-content pre code:after,
+ .main-content pre tt:before,
+ .main-content pre tt:after {
+ content: normal; }
+ .main-content ul,
+ .main-content ol {
+ margin-top: 0; }
+ .main-content blockquote {
+ padding: 0 1rem;
+ margin-left: 0;
+ color: #819198;
+ border-left: 0.3rem solid #dce6f0; }
+ .main-content blockquote > :first-child {
+ margin-top: 0; }
+ .main-content blockquote > :last-child {
+ margin-bottom: 0; }
+ .main-content table {
+ display: block;
+ width: 100%;
+ overflow: auto;
+ word-break: normal;
+ word-break: keep-all;
+ -webkit-overflow-scrolling: touch; }
+ .main-content table th {
+ font-weight: bold; }
+ .main-content table th,
+ .main-content table td {
+ padding: 0.5rem 1rem;
+ border: 1px solid #e9ebec; }
+ .main-content dl {
+ padding: 0; }
+ .main-content dl dt {
+ padding: 0;
+ margin-top: 1rem;
+ font-size: 1rem;
+ font-weight: bold; }
+ .main-content dl dd {
+ padding: 0;
+ margin-bottom: 1rem; }
+ .main-content hr {
+ height: 2px;
+ padding: 0;
+ margin: 1rem 0;
+ background-color: #eff0f1;
+ border: 0; }
+
+.site-footer {
+ padding-top: 2rem;
+ margin-top: 2rem;
+ border-top: solid 1px #eff0f1; }
+ @media screen and (min-width: 64em) {
+ .site-footer {
+ font-size: 1rem; } }
+ @media screen and (min-width: 42em) and (max-width: 64em) {
+ .site-footer {
+ font-size: 1rem; } }
+ @media screen and (max-width: 42em) {
+ .site-footer {
+ font-size: 0.9rem; } }
+
+.site-footer-owner {
+ display: block;
+ text-align:center;
+ font-weight: bold; }
+
+.site-footer-power {
+ display: block;
+ font-size: 0.6rem;
+ text-align:center;}
+
+.site-footer-credits {
+ color: #819198; }
+
+.donate {
+ vertical-align: top;
+ height: 20px;
+ border: 1px solid #d4d4d4;
+ display: inline-block;
+ box-sizing: border-box;
+ line-height: 16px;
+ border-radius: 3px;
+ cursor: pointer;
+ background-image: linear-gradient(to bottom, #fcfcfc 0, #eee 100%);
+ position: relative;
+ width: 72px;
+}
+.donate:hover {
+ border-color: #ccc;
+ background-image: linear-gradient(to bottom, #eee 0, #ddd 100%);
+}
+.donate img {
+ width: 14px;
+ height: 14px;
+ position: absolute;
+ top: 2px;
+ left: 5px;
+}
+.donate a {
+ font: 700 11px/14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ color: #333;
+ text-shadow: 0 1px 0 #fff;
+ position: absolute;
+ top: 2px;
+ left: 24px;
+}
+
+#nav,
+#translations {
+ list-style-type: none;
+ text-align: center;
+ padding: 0;
+ margin: 0;
+}
+#nav li,
+#translations li {
+ display: inline-block;
+ position: relative;
+ line-height: 40px;
+}
+#nav li:last-child .nav-link,
+#translations li:last-child .nav-link {
+ margin-right: 0;
+}
+#translations {
+ margin-bottom: 0em;
+}
+#translations .delimiter {
+ color: #7f8c8d;
+ margin: 0 5px;
+}
+#translations .nav-link {
+ margin: 0;
+}
+.nav-link {
+ color: #7f8c8d;
+ padding-bottom: 3px;
+ margin: 0 1.5em;
+}
+.nav-link:first-child {
+ margin-left: 0;
+}
+.nav-link:hover,
+.nav-link.current {
+ border-bottom: 3px solid #42b983;
+}
diff --git a/landing/assets/css/normalize.css b/landing/assets/css/normalize.css
new file mode 100644
index 00000000..30366a6e
--- /dev/null
+++ b/landing/assets/css/normalize.css
@@ -0,0 +1,424 @@
+/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
+
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS text size adjust after orientation change, without disabling
+ * user zoom.
+ */
+
+html {
+ font-family: sans-serif; /* 1 */
+ -ms-text-size-adjust: 100%; /* 2 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+ * Remove default margin.
+ */
+
+body {
+ margin: 0;
+}
+
+/* HTML5 display definitions
+ ========================================================================== */
+
+/**
+ * Correct `block` display not defined for any HTML5 element in IE 8/9.
+ * Correct `block` display not defined for `details` or `summary` in IE 10/11
+ * and Firefox.
+ * Correct `block` display not defined for `main` in IE 11.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+ */
+
+audio,
+canvas,
+progress,
+video {
+ display: inline-block; /* 1 */
+ vertical-align: baseline; /* 2 */
+}
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+/**
+ * Address `[hidden]` styling not present in IE 8/9/10.
+ * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
+ */
+
+[hidden],
+template {
+ display: none;
+}
+
+/* Links
+ ========================================================================== */
+
+/**
+ * Remove the gray background color from active links in IE 10.
+ */
+
+a {
+ background-color: transparent;
+}
+
+/**
+ * Improve readability when focused and also mouse hovered in all browsers.
+ */
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+ */
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+ */
+
+b,
+strong {
+ font-weight: bold;
+}
+
+/**
+ * Address styling not present in Safari and Chrome.
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari, and Chrome.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Remove border when inside `a` element in IE 8/9/10.
+ */
+
+img {
+ border: 0;
+}
+
+/**
+ * Correct overflow not hidden in IE 9/10/11.
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * Address margin not present in IE 8/9 and Safari.
+ */
+
+figure {
+ margin: 1em 40px;
+}
+
+/**
+ * Address differences between Firefox and other browsers.
+ */
+
+hr {
+ box-sizing: content-box;
+ height: 0;
+}
+
+/**
+ * Contain overflow in all browsers.
+ */
+
+pre {
+ overflow: auto;
+}
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
+ */
+
+/**
+ * 1. Correct color not being inherited.
+ * Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit; /* 1 */
+ font: inherit; /* 2 */
+ margin: 0; /* 3 */
+}
+
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10/11.
+ */
+
+button {
+ overflow: visible;
+}
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+ * Correct `select` style inheritance in Firefox.
+ */
+
+button,
+select {
+ text-transform: none;
+}
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button; /* 2 */
+ cursor: pointer; /* 3 */
+}
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+
+/**
+ * Remove inner padding and border in Firefox 4+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+
+input {
+ line-height: normal;
+}
+
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
+ * (include `-moz` to future-proof).
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */ /* 2 */
+ box-sizing: content-box;
+}
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct `color` not being inherited in IE 8/9/10/11.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+
+legend {
+ border: 0; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Remove default vertical scrollbar in IE 8/9/10/11.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+
+optgroup {
+ font-weight: bold;
+}
+
+/* Tables
+ ========================================================================== */
+
+/**
+ * Remove most spacing between table cells.
+ */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+td,
+th {
+ padding: 0;
+}
diff --git a/landing/assets/css/opensans.css b/landing/assets/css/opensans.css
new file mode 100644
index 00000000..ebac7ce8
--- /dev/null
+++ b/landing/assets/css/opensans.css
@@ -0,0 +1,112 @@
+/* cyrillic-ext */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/K88pR3goAWT7BTt32Z01m4X0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
+ unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
+}
+/* cyrillic */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/RjgO7rYTmqiVp7vzi-Q5UYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
+ unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/LWCjsQkB6EMdfHrEVqA1KYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
+ unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/xozscpT2726on7jbcb_pAoX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
+ unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/59ZRklaO5bWGqF5A9baEEYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
+ unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/u-WUoqrET9fUeobQW7jkRYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
+ unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3ZBw1xU1rKptJj_0jans920.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
+}
+/* cyrillic-ext */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzA7aC6SjiAOpAWOKfJDfVRY.woff2) format('woff2');
+ unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
+}
+/* cyrillic */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzBdwxCXfZpKo5kWAx_74bHs.woff2) format('woff2');
+ unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzJ6vnaPZw6nYDxM4SVEMFKg.woff2) format('woff2');
+ unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzPy1_HTwRwgtl1cPga3Fy3Y.woff2) format('woff2');
+ unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzPgrLsWo7Jk1KvZser0olKY.woff2) format('woff2');
+ unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzIjoYw3YTyktCCer_ilOlhE.woff2) format('woff2');
+ unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzBampu5_7CjHW5spxoeN3Vs.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
+}
diff --git a/landing/assets/img/alipay.png b/landing/assets/img/alipay.png
new file mode 100644
index 00000000..bc1088d0
--- /dev/null
+++ b/landing/assets/img/alipay.png
Binary files differ
diff --git a/landing/assets/img/donate.gif b/landing/assets/img/donate.gif
new file mode 100644
index 00000000..d6df5107
--- /dev/null
+++ b/landing/assets/img/donate.gif
Binary files differ
diff --git a/landing/assets/img/patreon.png b/landing/assets/img/patreon.png
new file mode 100644
index 00000000..aa0e4aee
--- /dev/null
+++ b/landing/assets/img/patreon.png
Binary files differ
diff --git a/landing/assets/img/paypal.png b/landing/assets/img/paypal.png
new file mode 100644
index 00000000..780c84f6
--- /dev/null
+++ b/landing/assets/img/paypal.png
Binary files differ
diff --git a/landing/assets/img/weixin.png b/landing/assets/img/weixin.png
new file mode 100644
index 00000000..1b1880b9
--- /dev/null
+++ b/landing/assets/img/weixin.png
Binary files differ
diff --git a/landing/favicon.ico b/landing/favicon.ico
new file mode 100644
index 00000000..937a26ff
--- /dev/null
+++ b/landing/favicon.ico
Binary files differ
diff --git a/landing/index.cn.md b/landing/index.cn.md
new file mode 100644
index 00000000..86c9ad98
--- /dev/null
+++ b/landing/index.cn.md
@@ -0,0 +1,159 @@
+---
+layout: default.cn
+title: {{ site.name }}
+---
+
+## 安装
+
+#### 使用curl
+
+```bash
+bash <(curl -fsSL https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh)
+```
+
+#### 使用wget
+
+```bash
+bash <(wget https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh -O -)
+```
+
+#### 使用powershell
+
+```bash
+Invoke-Expression (Invoke-Webrequest 'https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.ps1' -UseBasicParsing).Content
+```
+
+## 简单的工程描述
+
+```lua
+target("console")
+ set_kind("binary")
+ add_files("src/*.c")
+```
+
+## 构建工程
+
+```bash
+$ xmake
+```
+
+## 运行目标
+
+```bash
+$ xmake run console
+```
+
+## 调试程序
+
+```bash
+$ xmake run -d console
+```
+
+## 支持特性
+
+* Tasks
+* Macros
+* Actions
+* Options
+* Plugins
+* Modules
+* Templates
+
+## 支持平台
+
+* Windows (x86, x64)
+* Macosx (i386, x86_64)
+* Linux (i386, x86_64, cross-toolchains ...)
+* Android (armv5te, armv6, armv7-a, armv8-a, arm64-v8a)
+* iPhoneOS (armv7, armv7s, arm64, i386, x86_64)
+* WatchOS (armv7k, i386)
+* Mingw (i386, x86_64)
+
+## 支持语言
+
+* C/C++
+* Objc/Objc++
+* Swift
+* Assembly
+* Golang
+* Rust
+* Dlang
+
+## 内置插件
+
+* 宏记录脚本和回放插件
+* 加载自定义lua脚本插件
+* 生成IDE工程文件插件(makefile, vs2002 - vs2017, ...)
+* 生成doxygen文档插件
+
+## 更多插件
+
+请到插件仓库进行下载安装: [xmake-plugins](https://github.com/tboox/xmake-plugins).
+
+## 更多例子
+
+Debug和Release模式:
+
+```lua
+if is_mode("debug") then
+ set_symbols("debug")
+ set_optimize("none")
+end
+
+if is_mode("release") then
+ set_symbols("hidden")
+ set_optimize("fastest")
+ set_strip("all")
+end
+
+target("console")
+ set_kind("binary")
+ add_files("src/*.c")
+```
+
+自定义脚本:
+
+```lua
+target("test")
+ set_kind("static")
+ add_files("src/*.cpp")
+ after_build(function (target)
+ print("build %s ok!", target:targetfile())
+ end)
+```
+
+使用扩展模块:
+
+```lua
+target("test")
+ set_kind("shared")
+ add_files("src/*.c")
+ on_load(function (target)
+ import("lib.detect.find_package")
+ target:add(find_package("zlib"))
+ end)
+```
+
+## 项目例子
+
+一些使用xmake的项目:
+
+* [tbox](https://github.com/tboox/tbox)
+* [gbox](https://github.com/tboox/gbox)
+* [vm86](https://github.com/tboox/vm86)
+* [更多](https://github.com/vm86/xmake/wiki/%E4%BD%BF%E7%94%A8xmake%E7%9A%84%E5%BC%80%E6%BA%90%E5%BA%93)
+
+## 演示视频
+
+[![asciicast](https://asciinema.org/a/133693.png)](https://asciinema.org/a/133693)
+
+## 联系方式
+
+* 邮箱:[waruqi@gmail.com](mailto:waruqi@gmail.com)
+* 主页:[tboox.org](http://www.tboox.org/cn)
+* 社区:[TBOOX开源社区](https://github.com/tboox/community/issues)
+* 聊天:[![Join the chat at https://gitter.im/tboox/tboox](https://badges.gitter.im/tboox/tboox.svg)](https://gitter.im/tboox/tboox?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+* 源码:[Github](https://github.com/tboox/xmake), [Gitee](https://gitee.com/tboox/xmake)
+* QQ群:343118190
+* 微信公众号:tboox-os
+
diff --git a/landing/index.md b/landing/index.md
new file mode 100644
index 00000000..3c55aa14
--- /dev/null
+++ b/landing/index.md
@@ -0,0 +1,156 @@
+---
+layout: default
+title: {{ site.name }}
+---
+
+## Installation
+
+#### via curl
+
+```bash
+bash <(curl -fsSL https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh)
+```
+
+#### via wget
+
+```bash
+bash <(wget https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh -O -)
+```
+
+#### via powershell
+
+```bash
+Invoke-Expression (Invoke-Webrequest 'https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.ps1' -UseBasicParsing).Content
+```
+
+## Simple description
+
+```lua
+target("console")
+ set_kind("binary")
+ add_files("src/*.c")
+```
+
+## Build project
+
+```bash
+$ xmake
+```
+
+## Run target
+
+```bash
+$ xmake run console
+```
+
+## Debug target
+
+```bash
+$ xmake run -d console
+```
+
+## Support features
+
+* Tasks
+* Macros
+* Actions
+* Options
+* Plugins
+* Modules
+* Templates
+
+## Support platforms
+
+* Windows (x86, x64)
+* Macosx (i386, x86_64)
+* Linux (i386, x86_64, cross-toolchains ...)
+* Android (armv5te, armv6, armv7-a, armv8-a, arm64-v8a)
+* iPhoneOS (armv7, armv7s, arm64, i386, x86_64)
+* WatchOS (armv7k, i386)
+* Mingw (i386, x86_64)
+
+## Support Languages
+
+* C/C++
+* Objc/Objc++
+* Swift
+* Assembly
+* Golang
+* Rust
+* Dlang
+
+## Builtin Plugins
+
+* Macros script plugin
+* Run the custom lua script plugin
+* Generate IDE project file plugin(makefile, vs2002 - vs2017 .. )
+* Generate doxygen document plugin
+
+## More Plugins
+
+Please download and install from the plugins repository [xmake-plugins](https://github.com/tboox/xmake-plugins).
+
+## More Examples
+
+Debug and release modes:
+
+```lua
+if is_mode("debug") then
+ set_symbols("debug")
+ set_optimize("none")
+end
+
+if is_mode("release") then
+ set_symbols("hidden")
+ set_optimize("fastest")
+ set_strip("all")
+end
+
+target("console")
+ set_kind("binary")
+ add_files("src/*.c")
+```
+
+Custom script:
+
+```lua
+target("test")
+ set_kind("static")
+ add_files("src/*.cpp")
+ after_build(function (target)
+ print("build %s ok!", target:targetfile())
+ end)
+```
+
+Extension Modules:
+
+```lua
+target("test")
+ set_kind("shared")
+ add_files("src/*.c")
+ on_load(function (target)
+ import("lib.detect.find_package")
+ target:add(find_package("zlib"))
+ end)
+```
+
+## Project Examples
+
+Some projects using xmake:
+
+* [tbox](https://github.com/tboox/tbox)
+* [gbox](https://github.com/tboox/gbox)
+* [vm86](https://github.com/tboox/vm86)
+* [more](https://github.com/tboox/xmake/wiki/xmake-projects)
+
+## Example Video
+
+[![asciicast](https://asciinema.org/a/133693.png)](https://asciinema.org/a/133693)
+
+## Contacts
+
+* Email:[waruqi@gmail.com](mailto:waruqi@gmail.com)
+* Homepage:[tboox.org](http://www.tboox.org)
+* Community:[tboox@community](https://github.com/tboox/community/issues)
+* ChatRoom:[![Join the chat at https://gitter.im/tboox/tboox](https://badges.gitter.im/tboox/tboox.svg)](https://gitter.im/tboox/tboox?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+* Source Code:[Github](https://github.com/tboox/xmake), [Gitee](https://gitee.com/tboox/xmake)
diff --git a/landing/pages/donation.cn.md b/landing/pages/donation.cn.md
new file mode 100644
index 00000000..ceca8369
--- /dev/null
+++ b/landing/pages/donation.cn.md
@@ -0,0 +1,46 @@
+---
+layout: default.cn
+title: {{ site.name }}
+---
+
+<div id="donate"></div>
+
+xmake项目属于个人开源项目,它的发展需要您的帮助,如果您愿意支持xmake项目的开发,欢迎为其捐赠,支持它的发展。
+
+## 支付宝
+
+<img src="{{site.baseurl}}/assets/img/alipay.png" alt="alipay" width="256" height="256">
+
+账号:waruqi@gmail.com
+
+## 微信
+
+<img src="{{site.baseurl}}/assets/img/weixin.png" alt="weixin" width="218" height="218">
+
+## Paypal
+
+[![Paypal Me](/assets/img/paypal.png)](http://paypal.me/tboox/5)
+
+## 支持者
+
+<a href="https://opencollective.com/xmake#backers" target="_blank"><img src="https://opencollective.com/xmake/backers.svg?width=890"></a>
+
+| 2016.11.10 | [lc-soft](https://github.com/lc-soft) | oschina | ¥10 |
+
+## 赞助者
+
+通过赞助支持此项目,您的logo和网站链接将显示在这里。[[赞助此项目](https://opencollective.com/xmake#sponsor)]
+
+<a href="https://opencollective.com/xmake/sponsor/0/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/0/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/1/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/1/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/2/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/2/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/3/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/3/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/4/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/4/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/5/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/5/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/6/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/6/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/7/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/7/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/8/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/8/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/9/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/9/avatar.svg"></a>
+
+
+
diff --git a/landing/pages/donation.md b/landing/pages/donation.md
new file mode 100644
index 00000000..9290741d
--- /dev/null
+++ b/landing/pages/donation.md
@@ -0,0 +1,48 @@
+---
+layout: default
+title: {{ site.name }}
+---
+
+<div id="donate"></div>
+
+The xmake projects is a personal open source projects, their development need your help.
+
+If you would like to support the development of xmake, welcome to donate to us.
+
+## Paypal
+
+[![Paypal Me](/assets/img/paypal.png)](http://paypal.me/tboox/5)
+
+## Backers
+
+<a href="https://opencollective.com/xmake#backers" target="_blank"><img src="https://opencollective.com/xmake/backers.svg?width=890"></a>
+
+| 2016.11.10 | [lc-soft](https://github.com/lc-soft) | oschina | ¥10 |
+
+## Sponsors
+
+Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/xmake#sponsor)]
+
+<a href="https://opencollective.com/xmake/sponsor/0/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/0/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/1/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/1/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/2/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/2/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/3/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/3/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/4/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/4/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/5/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/5/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/6/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/6/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/7/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/7/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/8/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/8/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/9/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/9/avatar.svg"></a>
+
+## Alipay
+
+<img src="{{site.baseurl}}/assets/img/alipay.png" alt="alipay" width="256" height="256">
+
+## Weixin
+
+<img src="{{site.baseurl}}/assets/img/weixin.png" alt="weixin" width="218" height="218">
+
+
+
+
+
diff --git a/manual.md b/manual.md
new file mode 100644
index 00000000..aae03de8
--- /dev/null
+++ b/manual.md
@@ -0,0 +1,6818 @@
+---
+search: en
+---
+
+## Specification
+
+#### Naming conventions
+
+The interface is named according to some of the predefined specifications, which is more convenient to understand and easy to use.
+
+It's according to the following rules:
+
+| Interfaces | Description |
+| --------------------- | ----------------------------------------------------------------- |
+| `is_` + xxx | Condition interfaces |
+| `set_` + xxx | Set and override the previous settings |
+| `add_` + xxx | Set and append settings |
+| `s` + xxx | Support multi-parameters, .e.g:`add_files("*.c", "test.cpp")` |
+| `on_` + xxx | Set and override builtin script |
+| `before_` + xxx | Set and run this script before running builtin-script |
+| `after_` + xxx | Set and run this script after running builtin-script |
+| `scope("name")` | Define a description scope, .e.g `target("xxx")`, `option("xxx")` |
+| scope/settings | Indentation with spaces |
+
+## Documentation
+
+#### Conditions
+
+Conditions are generally used to handle some special compilation platforms.
+
+| 接口 | 描述 | 支持版本 |
+| ------------------------- | ---------------------------------------- | -------- |
+| [is_os](#is_os) | Is the current compilation target system? | >= 2.0.1 |
+| [is_arch](#is_arch) | Is the current compilation architecture? | >= 2.0.1 |
+| [is_plat](#is_plat) | Is the current compilation platform? | >= 2.0.1 |
+| [is_host](#is_host) | Is the current compilation host system? | >= 2.1.4 |
+| [is_mode](#is_mode) | Is the current compilation mode? | >= 2.0.1 |
+| [is_kind](#is_kind) | Is the current target kind? | >= 2.0.1 |
+| [is_option](#is_option) | Is the given options enabled? | >= 2.0.1 |
+
+##### is_os
+
+###### Is the current compilation target system
+
+```lua
+if is_os("ios") then
+ add_files("src/xxx/*.m")
+end
+```
+
+Support operation systems:
+
+* windows
+* linux
+* android
+* macosx
+* ios
+
+##### is_arch
+
+###### Is the current compilation architecture
+
+You can this api to check the configuration command: `xmake f -a armv7`
+
+```lua
+-- if the current architecture is x86_64 or i386
+if is_arch("x86_64", "i386") then
+ add_files("src/xxx/*.c")
+end
+
+-- if the current architecture is armv7 or arm64 or armv7s or armv7-a
+if is_arch("armv7", "arm64", "armv7s", "armv7-a") then
+ -- ...
+end
+```
+
+And you can also use the wildchard: `*` to check all matched architectures.
+
+```lua
+-- if the current architecture is arm which contains armv7, arm64, armv7s and armv7-a ...
+if is_arch("arm*") then
+ -- ...
+end
+```
+
+##### is_plat
+
+###### Is the current compilation platform
+
+You can this api to check the configuration command: `xmake f -p iphoneos`
+
+```lua
+-- if the current platform is android
+if is_plat("android") then
+ add_files("src/xxx/*.c")
+end
+
+-- if the current platform is macosx or iphoneos
+if is_plat("macosx", "iphoneos") then
+ add_mxflags("-framework Foundation")
+ add_ldflags("-framework Foundation")
+end
+```
+
+Support platforms:
+
+* windows
+* linux
+* macosx
+* android
+* iphoneos
+* watchos
+
+##### is_host
+
+###### Is the current compilation host system
+
+Some compilation platforms can be built on multiple different operating systems, for example: android ndk (on linux, macOS and windows).
+
+So, we can use this api to determine the current host operating system.
+
+```lua
+if is_host("windows") then
+ add_includes("C:\\includes")
+else
+ add_includes("/usr/includess")
+end
+```
+
+Support hosts:
+
+* windows
+* linux
+* macosx
+
+We can also get it from [$(host)](#var-host) or [os.host](#os-host).
+
+##### is_mode
+
+###### Is the current compilation mode
+
+You can this api to check the configuration command: `xmake f -m debug`
+
+The compilation mode is not builtin mode for xmake, so you can set the mode value by yourself.
+
+We often use these configuration values: `debug`, `release`, `profile`, etc.
+
+```lua
+-- if the current compilation mode is debug?
+if is_mode("debug") then
+
+ -- add macro: DEBUG
+ add_defines("DEBUG")
+
+ -- enable debug symbols
+ set_symbols("debug")
+
+ -- 禁用优化
+ set_optimize("none")
+
+end
+
+-- if the current compilation mode is release or profile?
+if is_mode("release", "profile") then
+
+ if is_mode("release") then
+
+ -- mark symbols visibility as hidden
+ set_symbols("hidden")
+
+ -- strip all symbols
+ set_strip("all")
+
+ -- fomit frame pointer
+ add_cxflags("-fomit-frame-pointer")
+ add_mxflags("-fomit-frame-pointer")
+
+ else
+
+ -- enable debug symbols
+ set_symbols("debug")
+
+ end
+
+ -- add vectorexts
+ add_vectorexts("sse2", "sse3", "ssse3", "mmx")
+end
+```
+
+##### is_kind
+
+###### Is the current target kind
+
+You can this api to check the configuration command: `xmake f -k [static|shared]`
+
+```lua
+target("test")
+
+ -- set target kind from the configuration command
+ set_kind("$(kind)")
+ add_files("src/*c")
+
+ -- compile target for static?
+ if is_kind("static") then
+ add_files("src/xxx.c")
+ end
+```
+
+You can switch the target kind by configuration command.
+
+```bash
+# compile the static library
+$ xmake f -k static
+$ xmake
+```
+
+```bash
+# compile the shared library
+$ xmake f -k shared
+$ xmake
+```
+
+##### is_option
+
+###### Is the given options enabled
+
+You can this api to check the custom option configuration command:`xmake f --xxxx=y`
+
+For example, We want to enable the custom option: `xmake f --demo=y` and check it from `xmake.lua`.
+
+```lua
+if is_option("demo") then
+ add_subdirs("src/demo")
+end
+```
+
+#### Global Interfaces
+
+The global interface affects the whole project description scope and all sub-project files.
+
+| Interfaces | Description | Version |
+| ------------------------------------- | ------------------------------------- | -------- |
+| [includes](#includes) | Add sub-project files and directories | >= 2.1.5 |
+| [set_modes](#set_modes) | Set project compilation modes | >= 2.1.2 |
+| [set_project](#set_project) | Set project name | >= 2.0.1 |
+| [set_version](#set_version) | Set project version | >= 2.0.1 |
+| [set_xmakever](#set_xmakever) | Set minimal xmake version | >= 2.1.1 |
+| [add_subdirs](#add_subdirs) | Add sub-project directories | >= 1.0.1 |
+| [add_subfiles](#add_subfiles) | Add sub-project files | >= 1.0.1 |
+| [add_moduledirs](#add_moduledirs) | Add module directories | >= 2.1.5 |
+| [add_plugindirs](#add_plugindirs) | Add plugin directories | >= 2.0.1 |
+| [add_packagedirs](#add_packagedirs) | Add package directories | >= 2.0.1 |
+
+##### includes
+
+###### Add sub-project files and directories
+
+It is used to replace [add_subdirs](#add_subdirs) and [add_subfiles](#add_subfiles).
+
+##### set_modes
+
+###### Set project compilation modes
+
+This is an optional api, just to make it easy for the plugin to get mode configuration information now.
+
+```lua
+set_modes("debug", "release")
+```
+
+If you set this configuration, you need not set them manually when generating vs201x project.
+
+```bash
+$ xmake project -k vs2017
+```
+
+Otherwise, you need to run:
+
+```bash
+$ xmake project -k vs2017 -m "debug,release"
+```
+
+<p class="tip">
+If you do not set this configuration, [is_mode](#is_mode) can also be used normally.
+</p>
+
+##### set_project
+
+###### Set project name
+
+Set the whole project name, we can set it at the beginning of `xmake.lua`.
+
+```lua
+-- set project name
+set_project("tbox")
+
+-- set project version
+set_version("1.5.1")
+```
+
+##### set_version
+
+###### Set project version
+
+Set the whole project version, we can set it at the beginning of `xmake.lua`.
+
+```lua
+set_version("1.5.1")
+```
+
+It will add project version info to this file automatically if we call [set_config_header](#targetset_config_header) to set `config.h`.`
+
+For example:
+
+```c
+// version
+#define TB_CONFIG_VERSION "1.5.1"
+#define TB_CONFIG_VERSION_MAJOR 1
+#define TB_CONFIG_VERSION_MINOR 5
+#define TB_CONFIG_VERSION_ALTER 1
+#define TB_CONFIG_VERSION_BUILD 201510220917
+```
+
+We can set build version in v2.1.7 version:
+
+```lua
+set_version("1.5.1", {build = "%Y%m%d%H%M"})
+```
+
+##### set_xmakever
+
+###### Set minimal xmake version
+
+If the current xmake version less than the required version, it will prompt an error.
+
+```lua
+-- the current xmake version must be larger than 2.1.0
+set_xmakever("2.1.0")
+```
+
+##### add_subdirs
+
+###### Add sub-project directories
+
+This interface will add an sub-project directories to the current `xmake.lua`, it will load the `xmake.lua` file of the sub-directories.
+
+For example, we have a following project directory tree:
+
+```
+./tbox
+├── src
+│ ├── demo
+│ │ └── xmake.lua
+│ └── tbox
+│ └── xmake.lua
+└── xmake.lua
+````
+
+We can add sub-project `tbox` and `demo` directories to the root `xmake.lua`.
+
+```lua
+add_subdirs("src/tbox")
+if is_option("demo") then
+ add_subdirs("src/demo")
+end
+```
+
+By default, xmake will compile all the targets, if you only want to compile the specified target, you can do:
+
+```bash
+# only build `tbox` target
+$ xmake build tbox
+```
+
+##### add_subfiles
+
+###### Add sub-project files
+
+`add_subfiles` is simular to [add_subdirs](#add_subdirs).
+
+The only difference is that this interface specifies the path where the 'xmake.lua' file directly, rather than a directory.
+
+for example:
+
+```lua
+add_subfiles("src/tbox/xmake.lua")
+```
+
+##### add_moduledirs
+
+###### Add module directories
+
+The builtin modules are placed in the 'xmake/modules' directory, but for some user-defined modules for a specific project, you can configure additional module directory is specified in the 'xmake.lua`.
+
+```lua
+add_moduledirs("$(projectdir)/modules")
+```
+xmake will load the given module in the given directory when calling `import`.
+
+##### add_plugindirs
+
+###### Add plugin directories
+
+The builtin plugins are placed in the 'xmake/plugins' directory, but for some user-defined plugins for a specific project, you can configure additional plugin directory is specified in the 'xmake.lua`.
+
+```lua
+add_plugindirs("$(projectdir)/plugins")
+```
+xmake will load all plugins in the given directory.
+
+##### add_packagedirs
+
+###### Add package directories
+
+By setting up a dependency package directory, you can easily integrate some third-party dependent libraries,
+taking the tbox project as an example, and its package directory is as follows:
+
+
+```
+tbox.pkg
+- base.pkg
+- zlib.pkg
+- polarssl.pkg
+- openssl.pkg
+- mysql.pkg
+- pcre.pkg
+- ...
+```
+
+If you want the current project to load these packages, first specify the package directory path, for example:
+
+```lua
+add_packagedirs("pkg")
+```
+
+Then, please add these packages to the given target by [add_packages](#add_packages):
+
+```lua
+target("tbox")
+ add_packages("zlib", "polarssl", "pcre", "mysql")
+```
+
+xmake will check these packages automatically and link them if exists, and we can disable them manually.
+
+```bash
+$ xmake f --openssl=n
+```
+
+#### Project Target
+
+<p class="warning">
+Translating ..., help me please! [Edit this page](https://github.com/tboox/xmake/blob/master/docs/manual.md)
+</p>
+
+定义和设置子工程模块,每个`target`对应一个子工程,最后会生成一个目标程序,有可能是可执行程序,也有可能是库模块。
+
+<p class="tip">
+target的接口,都是可以放置在target外面的全局作用域中的,如果在全局中设置,那么会影响所有子工程target。
+</p>
+
+例如:
+
+```lua
+-- 会同时影响test和test2目标
+add_defines("DEBUG")
+
+target("test")
+ add_files("*.c")
+
+target("test2")
+ add_files("*.c")
+```
+
+<p class="tip">
+`target`域是可以重复进入来实现分离设置的。
+</p>
+
+
+| 接口 | 描述 | 支持版本 |
+| --------------------------------------------- | ------------------------------------ | -------- |
+| [target](#target) | 定义工程目标 | >= 1.0.1 |
+| [target_end](#target_end) | 结束定义工程目标 | >= 2.1.1 |
+| [set_kind](#targetset_kind) | 设置目标编译类型 | >= 1.0.1 |
+| [set_strip](#targetset_strip) | 设置是否strip信息 | >= 1.0.1 |
+| [set_default](#targetset_default) | 设置是否为默认构建安装目标 | >= 2.1.3 |
+| [set_options](#targetset_options) | 设置关联选项 | >= 1.0.1 |
+| [set_symbols](#targetset_symbols) | 设置符号信息 | >= 1.0.1 |
+| [set_basename](#targetset_basename) | 设置目标文件名 | >= 2.1.2 |
+| [set_warnings](#targetset_warnings) | 设置警告级别 | >= 1.0.1 |
+| [set_optimize](#targetset_optimize) | 设置优化级别 | >= 1.0.1 |
+| [set_languages](#targetset_languages) | 设置代码语言标准 | >= 1.0.1 |
+| [set_headerdir](#targetset_headerdir) | 设置头文件安装目录 | >= 1.0.1 |
+| [set_targetdir](#targetset_targetdir) | 设置生成目标文件目录 | >= 1.0.1 |
+| [set_objectdir](#targetset_objectdir) | 设置对象文件生成目录 | >= 1.0.1 |
+| [on_load](#targeton_load) | 自定义目标加载脚本 | >= 2.1.5 |
+| [on_build](#targeton_build) | 自定义编译脚本 | >= 2.0.1 |
+| [on_clean](#targeton_clean) | 自定义清理脚本 | >= 2.0.1 |
+| [on_package](#targeton_package) | 自定义打包脚本 | >= 2.0.1 |
+| [on_install](#targeton_install) | 自定义安装脚本 | >= 2.0.1 |
+| [on_uninstall](#targeton_uninstall) | 自定义卸载脚本 | >= 2.0.1 |
+| [on_run](#targeton_run) | 自定义运行脚本 | >= 2.0.1 |
+| [before_build](#targetbefore_build) | 在构建之前执行一些自定义脚本 | >= 2.0.1 |
+| [before_clean](#targetbefore_clean) | 在清除之前执行一些自定义脚本 | >= 2.0.1 |
+| [before_package](#targetbefore_package) | 在打包之前执行一些自定义脚本 | >= 2.0.1 |
+| [before_install](#targetbefore_install) | 在安装之前执行一些自定义脚本 | >= 2.0.1 |
+| [before_uninstall](#targetbefore_uninstall) | 在卸载之前执行一些自定义脚本 | >= 2.0.1 |
+| [before_run](#targetbefore_run) | 在运行之前执行一些自定义脚本 | >= 2.0.1 |
+| [after_build](#targetafter_build) | 在构建之后执行一些自定义脚本 | >= 2.0.1 |
+| [after_clean](#targetafter_clean) | 在清除之后执行一些自定义脚本 | >= 2.0.1 |
+| [after_package](#targetafter_package) | 在打包之后执行一些自定义脚本 | >= 2.0.1 |
+| [after_install](#targetafter_install) | 在安装之后执行一些自定义脚本 | >= 2.0.1 |
+| [after_uninstall](#targetafter_uninstall) | 在卸载之后执行一些自定义脚本 | >= 2.0.1 |
+| [after_run](#targetafter_run) | 在运行之后执行一些自定义脚本 | >= 2.0.1 |
+| [set_config_h](#targetset_config_h) | 设置自动生成的配置头文件路径 | >= 1.0.1 < 2.1.5 已废弃 |
+| [set_config_h_prefix](#targetset_config_h) | 设置自动生成的头文件中宏定义命名前缀 | >= 1.0.1 < 2.1.5 已废弃 |
+| [set_config_header](#targetset_config_header) | 设置自动生成的配置头文件路径和前缀 | >= 2.1.5 |
+| [set_pcheader](#targetset_pcheader) | 设置c预编译头文件 | >= 2.1.5 |
+| [set_pcxxheader](#targetset_pcxxheader) | 设置c++预编译头文件 | >= 2.1.5 |
+| [add_deps](#targetadd_deps) | 添加子工程目标依赖 | >= 1.0.1 |
+| [add_links](#targetadd_links) | 添加链接库名 | >= 1.0.1 |
+| [add_files](#targetadd_files) | 添加源代码文件 | >= 1.0.1 |
+| [add_headers](#targetadd_headers) | 添加安装的头文件 | >= 1.0.1 |
+| [add_linkdirs](#targetadd_linkdirs) | 添加链接库搜索目录 | >= 1.0.1 |
+| [add_rpathdirs](#targetadd_rpathdirs) | 添加运行时候动态链接库搜索目录 | >= 2.1.3 |
+| [add_includedirs](#targetadd_includedirs) | 添加头文件搜索目录 | >= 1.0.1 |
+| [add_defines](#targetadd_defines) | 添加宏定义 | >= 1.0.1 |
+| [add_undefines](#targetadd_undefines) | 取消宏定义 | >= 1.0.1 |
+| [add_defines_h](#targetadd_defines_h) | 添加宏定义到头文件 | >= 1.0.1 |
+| [add_undefines_h](#targetadd_undefines_h) | 取消宏定义到头文件 | >= 1.0.1 |
+| [add_cflags](#targetadd_cflags) | 添加c编译选项 | >= 1.0.1 |
+| [add_cxflags](#targetadd_cxflags) | 添加c/c++编译选项 | >= 1.0.1 |
+| [add_cxxflags](#targetadd_cxxflags) | 添加c++编译选项 | >= 1.0.1 |
+| [add_mflags](#targetadd_mflags) | 添加objc编译选项 | >= 1.0.1 |
+| [add_mxflags](#targetadd_mxflags) | 添加objc/objc++编译选项 | >= 1.0.1 |
+| [add_mxxflags](#targetadd_mxxflags) | 添加objc++编译选项 | >= 1.0.1 |
+| [add_scflags](#targetadd_scflags) | 添加swift编译选项 | >= 2.0.1 |
+| [add_asflags](#targetadd_asflags) | 添加汇编编译选项 | >= 2.0.1 |
+| [add_gcflags](#targetadd_gcflags) | 添加go编译选项 | >= 2.1.1 |
+| [add_ldflags](#targetadd_ldflags) | 添加链接选项 | >= 1.0.1 |
+| [add_arflags](#targetadd_arflags) | 添加静态库归档选项 | >= 1.0.1 |
+| [add_shflags](#targetadd_shflags) | 添加动态库链接选项 | >= 1.0.1 |
+| [add_cfunc](#targetadd_cfunc) | 添加单个c库函数检测 | >= 2.0.1 |
+| [add_cxxfunc](#targetadd_cxxfunc) | 添加单个c++库函数检测 | >= 2.0.1 |
+| [add_cfuncs](#targetadd_cfuncs) | 添加c库函数检测 | >= 2.0.1 |
+| [add_cxxfuncs](#targetadd_cxxfuncs) | 添加c++库函数接口 | >= 2.0.1 |
+| [add_packages](#targetadd_packages) | 添加包依赖 | >= 2.0.1 |
+| [add_options](#targetadd_options) | 添加关联选项 | >= 2.0.1 |
+| [add_languages](#targetadd_languages) | 添加语言标准 | >= 1.0.1 |
+| [add_vectorexts](#targetadd_vectorexts) | 添加向量扩展指令 | >= 1.0.1 |
+| [add_frameworks](#targetadd_frameworks) | 添加链接框架 | >= 2.1.1 |
+| [add_frameworkdirs](#targetadd_frameworkdirs) | 添加链接框架的搜索目录 | >= 2.1.5 |
+
+##### target
+
+###### 定义工程目标
+
+定义一个新的控制台工程目标,工程名为`test`,最后生成的目标名也是`test`。
+
+```lua
+target("test")
+ set_kind("binary")
+ add_files("src/*.c")
+```
+
+可以重复调用这个api,进入target域修改设置
+
+```lua
+-- 定义目标demo,并进入demo设置模式
+target("demo")
+ set_kind("binary")
+ add_files("src/demo.c")
+
+-- 定义和设置其他目标
+target("other")
+ ...
+
+-- 重新进入demo目标域,添加test.c文件
+target("demo")
+ add_files("src/test.c")
+```
+
+<p class="tip">
+所有根域的设置,会全局影响所有target目标,但是不会影响option的定义。
+</p>
+
+```lua
+-- 在根域对所有target添加-DDEBUG的宏定义,影响所有target(demo和test都会加上此宏定义)
+add_defines("DEBUG")
+
+target("demo")
+ set_kind("binary")
+ add_files("src/demo.c")
+
+target("test")
+ set_kind("binary")
+ add_files("src/test.c")
+```
+
+##### target_end
+
+###### 结束定义工程目标
+
+这是一个可选的api,如果不调用,那么`target("xxx")`之后的所有设置都是针对这个target进行的,除非进入其他`target`, `option`, `task`域。
+
+如果想设置完当前`target`后,显示离开`target`域,进入根域设置,那么可以通过这个api才操作,例如:
+
+```lua
+target("test")
+ set_kind("static")
+ add_files("src/*.c")
+target_end()
+
+-- 此处已在根域
+-- ...
+```
+
+如果不调用这个api的话:
+
+```lua
+target("test")
+ set_kind("static")
+ add_files("src/*.c")
+
+-- 此处还在上面target域中,之后的设置还是针对test进行的设置
+-- ...
+
+-- 这个时候才离开test,进入另外一个target域中
+target("test2")
+ ...
+```
+
+##### target:set_kind
+
+###### 设置目标编译类型
+
+设置目标类型,目前支持的类型有:
+
+| 值 | 描述 |
+| ------ | -----------|
+| binary | 二进制程序 |
+| static | 静态库程序 |
+| shared | 动态库程序 |
+
+```lua
+target("demo")
+ set_kind("binary")
+```
+
+##### target:set_strip
+
+###### 设置是否strip信息
+
+设置当前目标的strip模式,目前支持一下模式:
+
+| 值 | 描述 |
+| ------ | ----------------------------------------- |
+| debug | 链接的时候,strip掉调试符号 |
+| all | 链接的时候,strip掉所有符号,包括调试符号 |
+
+这个api一般在release模式下使用,可以生成更小的二进制程序。。
+
+```lua
+target("xxxx")
+ set_strip("all")
+```
+
+<p class="tip">
+这个api不一定非得在target之后使用,如果没有target指定,那么将会设置到全局模式。。
+</p>
+
+##### target:set_default
+
+###### 设置是否为默认构建安装目标
+
+这个接口用于设置给定工程目标是否作为默认构建,如果没有调用此接口进行设置,那么这个目标就是默认被构建的,例如:
+
+```lua
+target("test1")
+ set_default(false)
+
+target("test2")
+ set_default(true)
+
+target("test3")
+ ...
+```
+
+上述代码的三个目标,在执行`xmake`, `xmake install`, `xmake package`, `xmake run`等命令的时候,如果不指定目标名,那么:
+
+| 目标名 | 行为 |
+| ------ | -------------------------------- |
+| test1 | 不会被默认构建、安装、打包和运行 |
+| test2 | 默认构建、安装、打包和运行 |
+| test3 | 默认构建、安装、打包和运行 |
+
+通过上面的例子,可以看到默认目标可以设置多个,运行的时候也会依次运行。
+
+<p class="tip">
+ 需要注意的是,`xmake uninstall`和`xmake clean`命令不受此接口设置影响,因为用户大部分情况下都是喜欢清除和卸载所有。
+</p>
+
+如果不想使用默认的目标,那么可以手动指定需要构建安装的目标:
+
+```bash
+$ xmake build targetname
+$ xmake install targetname
+```
+
+如果要强制构建安装所有目标,可以传入`[-a|--all]`参数:
+
+```bash
+$ xmake build [-a|--all]
+$ xmake install [-a|--all]
+```
+
+##### target:set_options
+
+###### 设置关联选项
+
+添加选项依赖,如果通过[option](#option)接口自定义了一些选项,那么只有在指定`target`目标域下,添加此选项,才能进行关联生效。
+
+```lua
+-- 定义一个hello选项
+option("hello")
+ set_default(false)
+ set_showmenu(true)
+ add_defines("HELLO_ENABLE")
+
+target("test")
+ -- 如果hello选项被启用了,这个时候就会将-DHELLO_ENABLE宏应用到test目标上去
+ set_options("hello")
+```
+
+<p class="warning">
+只有调用`set_options`进行关联生效后,[option](#option) 中定义的一些设置才会影响到此`target`目标,例如:宏定义、链接库、编译选项等等
+</p>
+
+##### target:set_symbols
+
+###### 设置符号信息
+
+设置目标的符号模式,如果当前没有定义target,那么将会设置到全局状态中,影响所有后续的目标。
+
+目前主要支持一下几个级别:
+
+| 值 | 描述 |
+| ------ | ---------------------- |
+| debug | 添加调试符号 |
+| hidden | 设置符号不可见 |
+
+这两个值也可以同时被设置,例如:
+
+```lua
+-- 添加调试符号, 设置符号不可见
+set_symbols("debug", "hidden")
+```
+
+如果没有调用这个api,默认是禁用调试符号的。。
+
+##### target:set_basename
+
+###### 设置目标文件名
+
+默认情况下,生成的目标文件名基于`target("name")`中配置的值,例如:
+
+```lua
+-- 目标文件名为:libxxx.a
+target("xxx")
+ set_kind("static")
+
+-- 目标文件名为:libxxx2.so
+target("xxx2")
+ set_kind("shared")
+```
+
+默认的命名方式,基本上可以满足大部分情况下的需求,但是如果有时候想要更加定制化目标文件名
+
+例如,按编译模式和架构区分目标名,这个时候可以使用这个接口,来设置:
+
+```lua
+target("xxx")
+ set_kind("static")
+ set_basename("xxx_$(mode)_$(arch)")
+```
+
+如果这个时候,编译配置为:`xmake f -m debug -a armv7`,那么生成的文件名为:`libxxx_debug_armv7.a`
+
+如果还想进一步定制目标文件的目录名,可参考:[set_targetdir](#targetset_targetdir)。
+
+或者通过编写自定义脚本,实现更高级的逻辑,具体见:[after_build](#targetafter_build)和[os.mv](#os-mv)。
+
+##### target:set_warnings
+
+###### 设置警告级别
+
+设置当前目标的编译的警告级别,一般支持一下几个级别:
+
+| 值 | 描述 |
+| ----- | ---------------------- |
+| none | 禁用所有警告 |
+| less | 启用较少的警告 |
+| more | 启用较多的警告 |
+| all | 启用所有警告 |
+| error | 将所有警告作为编译错误 |
+
+这个api的参数是可以混合添加的,例如:
+
+```lua
+-- 启用所有警告,并且作为编译错误处理
+set_warnings("all", "error")
+```
+
+如果当前没有目标,调用这个api将会设置到全局模式。。
+
+##### target:set_optimize
+
+###### 设置优化级别
+
+设置目标的编译优化等级,如果当前没有设置目标,那么将会设置到全局状态中,影响所有后续的目标。
+
+目前主要支持一下几个级别:
+
+| 值 | 描述 |
+| ---------- | ---------------------- |
+| none | 禁用优化 |
+| fast | 快速优化 |
+| faster | 更快的优化 |
+| fastest | 最快运行速度的优化 |
+| smallest | 最小化代码优化 |
+| aggressive | 过度优化 |
+
+例如:
+
+```lua
+-- 最快运行速度的优化
+set_optimize("fastest")
+```
+
+##### target:set_languages
+
+###### 设置代码语言标准
+
+设置目标代码编译的语言标准,如果当前没有目标存在,将会设置到全局模式中。。。
+
+支持的语言标准目前主要有以下几个:
+
+| 值 | 描述 |
+| ---------- | ---------------------- |
+| ansi | c语言标准: ansi |
+| c89 | c语言标准: c89 |
+| gnu89 | c语言标准: gnu89 |
+| c99 | c语言标准: c99 |
+| gnu99 | c语言标准: gnu99 |
+| cxx98 | c++语言标准: `c++98` |
+| gnuxx98 | c++语言标准: `gnu++98` |
+| cxx11 | c++语言标准: `c++11` |
+| gnuxx11 | c++语言标准: `gnu++11` |
+| cxx14 | c++语言标准: `c++14` |
+| gnuxx14 | c++语言标准: `gnu++14` |
+| cxx1z | c++语言标准: `c++1z` |
+| gnuxx1z | c++语言标准: `gnu++1z` |
+| cxx17 | c++语言标准: `c++17` |
+| gnuxx17 | c++语言标准: `gnu++17` |
+
+c标准和c++标准可同时进行设置,例如:
+
+```lua
+-- 设置c代码标准:c99, c++代码标准:c++11
+set_languages("c99", "cxx11")
+```
+
+<p class="warning">
+并不是设置了指定的标准,编译器就一定会按这个标准来编译,毕竟每个编译器支持的力度不一样,但是xmake会尽最大可能的去适配当前编译工具的支持标准。。。
+<br><br>
+例如:
+<br>
+windows下vs的编译器并不支持按c99的标准来编译c代码,只能支持到c89,但是xmake为了尽可能的支持它,所以在设置c99的标准后,xmake会强制按c++代码模式去编译c代码,从一定程度上解决了windows下编译c99的c代码问题。。
+用户不需要去额外做任何修改。。
+</p>
+
+##### target:set_headerdir
+
+###### 设置头文件安装目录
+
+设置头文件的输出目录,默认输出到build目录中。
+
+```lua
+target("test")
+ set_headerdir("$(buildir)/include")
+```
+
+对于需要安装哪些头文件,可参考[add_headers](#targetadd_headers)接口。
+
+##### target:set_targetdir
+
+###### 设置生成目标文件目录
+
+设置目标程序文件的输出目录,一般情况下,不需要设置,默认会输出在build目录下
+
+而build的目录可以在工程配置的时候,手动修改:
+
+```bash
+xmake f -o /tmp/build
+```
+
+修改成`/tmp/build`后,目标文件默认输出到`/tmp/build`下面。
+
+而如果用这个接口去设置,就不需要每次敲命令修改了,例如:
+
+```lua
+target("test")
+ set_targetdir("/tmp/build")
+```
+
+<p class="tip">
+如果显示设置了`set_targetdir`, 那么优先选择`set_targetdir`指定的目录为目标文件的输出目录。
+</p>
+
+##### target:set_objectdir
+
+###### 设置对象文件生成目录
+
+设置目标target的对象文件(`*.o/obj`)的输出目录,例如:
+
+```lua
+target("test")
+ set_objectdir("$(buildir)/.objs")
+```
+
+##### target:on_load
+
+###### 自定义目标加载脚本
+
+在target初始化加载的时候,将会执行此脚本,在里面可以做一些动态的目标配置,实现更灵活的目标描述定义,例如:
+
+```lua
+target("test")
+ on_load(function (target)
+ target:add("defines", "DEBUG", "TEST=\"hello\"")
+ target:add("linkdirs", "/usr/lib", "/usr/local/lib")
+ target:add({includedirs = "/usr/include", "links" = "pthread"})
+ end)
+```
+
+可以在`on_load`里面,通过`target:set`, `target:add` 来动态添加各种target属性。
+
+##### target:on_build
+
+###### 自定义编译脚本
+
+覆盖target目标默认的构建行为,实现自定义的编译过程,一般情况下,并不需要这么做,除非确实需要做一些xmake默认没有提供的编译操作。
+
+你可以通过下面的方式覆盖它,来自定义编译操作:
+
+```lua
+target("test")
+
+ -- 设置自定义编译脚本
+ on_build(function (target)
+ print("build it")
+ end)
+```
+
+注:2.1.5版本之后,所有target的自定义脚本都可以针对不同平台和架构,分别处理,例如:
+
+```lua
+target("test")
+ on_build("iphoneos|arm*", function (target)
+ print("build for iphoneos and arm")
+ end)
+```
+
+其中如果第一个参数为字符串,那么就是指定这个脚本需要在哪个`平台|架构`下,才会被执行,并且支持模式匹配,例如`arm*`匹配所有arm架构。
+
+当然也可以只设置平台,不设置架构,这样就是匹配指定平台下,执行脚本:
+
+```lua
+target("test")
+ on_build("windows", function (target)
+ print("build for windows")
+ end)
+```
+
+<p class="tip">
+一旦对这个target目标设置了自己的build过程,那么xmake默认的构建过程将不再被执行。
+</p>
+
+##### target:on_clean
+
+###### 自定义清理脚本
+
+覆盖target目标的`xmake [c|clean}`的清理操作,实现自定义清理过程。
+
+```lua
+target("test")
+
+ -- 设置自定义清理脚本
+ on_clean(function (target)
+
+ -- 仅删掉目标文件
+ os.rm(target:targetfile())
+ end)
+```
+
+一些target接口描述如下:
+
+| target接口 | 描述 |
+| ----------------------------------- | ---------------------------------------------------------------- |
+| target:name() | 获取目标名 |
+| target:targetfile() | 获取目标文件路径 |
+| target:get("kind") | 获取目标的构建类型 |
+| target:get("defines") | 获取目标的宏定义 |
+| target:get("xxx") | 其他通过 `set_/add_`接口设置的target信息,都可以通过此接口来获取 |
+| target:add("links", "pthread") | 添加目标设置 |
+| target:set("links", "pthread", "z") | 覆写目标设置 |
+| target:deps() | 获取目标的所有依赖目标 |
+| target:dep("depname") | 获取指定的依赖目标 |
+| target:sourcebatches() | 获取目标的所有源文件列表 |
+
+##### target:on_package
+
+###### 自定义打包脚本
+
+覆盖target目标的`xmake [p|package}`的打包操作,实现自定义打包过程,如果你想对指定target打包成自己想要的格式,可以通过这个接口自定义它。
+
+这个接口还是挺实用的,例如,编译玩jni后,将生成的so,打包进apk包中。
+
+```lua
+-- 定义一个android app的测试demo
+target("demo")
+
+ -- 生成动态库:libdemo.so
+ set_kind("shared")
+
+ -- 设置对象的输出目录,可选
+ set_objectdir("$(buildir)/.objs")
+
+ -- 每次编译完的libdemo.so的生成目录,设置为app/libs/armeabi
+ set_targetdir("libs/armeabi")
+
+ -- 添加jni的代码文件
+ add_files("jni/*.c")
+
+ -- 设置自定义打包脚本,在使用xmake编译完libdemo.so后,执行xmake p进行打包
+ -- 会自动使用ant将app编译成apk文件
+ --
+ on_package(function (target)
+
+ -- 使用ant编译app成apk文件,输出信息重定向到日志文件
+ os.run("ant debug")
+ end)
+```
+
+##### target:on_install
+
+###### 自定义安装脚本
+
+覆盖target目标的`xmake [i|install}`的安装操作,实现自定义安装过程。
+
+例如,将生成的apk包,进行安装。
+
+```lua
+target("test")
+
+ -- 设置自定义安装脚本,自动安装apk文件
+ on_install(function (target)
+
+ -- 使用adb安装打包生成的apk文件
+ os.run("adb install -r ./bin/Demo-debug.apk")
+ end)
+```
+
+##### target:on_uninstall
+
+###### 自定义卸载脚本
+
+覆盖target目标的`xmake [u|uninstall}`的卸载操作,实现自定义卸载过程。
+
+```lua
+target("test")
+ on_uninstall(function (target)
+ ...
+ end)
+```
+
+##### target:on_run
+
+###### 自定义运行脚本
+
+覆盖target目标的`xmake [r|run}`的运行操作,实现自定义运行过程。
+
+例如,运行安装好的apk程序:
+
+```lua
+target("test")
+
+ -- 设置自定义运行脚本,自动运行安装好的app程序,并且自动获取设备输出信息
+ on_run(function (target)
+
+ os.run("adb shell am start -n com.demo/com.demo.DemoTest")
+ os.run("adb logcat")
+ end)
+```
+
+##### target:before_build
+
+###### 在构建之前执行一些自定义脚本
+
+并不会覆盖默认的构建操作,只是在构建之前增加一些自定义的操作。
+
+```lua
+target("test")
+ before_build(function (target)
+ print("")
+ end)
+```
+
+##### target:before_clean
+
+###### 在清理之前执行一些自定义脚本
+
+并不会覆盖默认的清理操作,只是在清理之前增加一些自定义的操作。
+
+```lua
+target("test")
+ before_clean(function (target)
+ print("")
+ end)
+```
+
+##### target:before_package
+
+###### 在打包之前执行一些自定义脚本
+
+并不会覆盖默认的打包操作,只是在打包之前增加一些自定义的操作。
+
+```lua
+target("test")
+ before_package(function (target)
+ print("")
+ end)
+```
+
+##### target:before_install
+
+###### 在安装之前执行一些自定义脚本
+
+并不会覆盖默认的安装操作,只是在安装之前增加一些自定义的操作。
+
+```lua
+target("test")
+ before_install(function (target)
+ print("")
+ end)
+```
+
+##### target:before_uninstall
+
+###### 在卸载之前执行一些自定义脚本
+
+并不会覆盖默认的卸载操作,只是在卸载之前增加一些自定义的操作。
+
+```lua
+target("test")
+ before_uninstall(function (target)
+ print("")
+ end)
+```
+
+##### target:before_run
+
+###### 在运行之前执行一些自定义脚本
+
+并不会覆盖默认的运行操作,只是在运行之前增加一些自定义的操作。
+
+```lua
+target("test")
+ before_run(function (target)
+ print("")
+ end)
+```
+
+##### target:after_build
+
+###### 在构建之后执行一些自定义脚本
+
+并不会覆盖默认的构建操作,只是在构建之后增加一些自定义的操作。
+
+例如,对于ios的越狱开发,构建完程序后,需要用`ldid`进行签名操作
+
+```lua
+target("test")
+ after_build(function (target)
+ os.run("ldid -S %s", target:targetfile())
+ end)
+```
+
+##### target:after_clean
+
+###### 在清理之后执行一些自定义脚本
+
+并不会覆盖默认的清理操作,只是在清理之后增加一些自定义的操作。
+
+一般可用于清理编译某target自动生成的一些额外的临时文件,这些文件xmake默认的清理规则可能没有清理到,例如:
+
+```lua
+target("test")
+ after_clean(function (target)
+ os.rm("$(buildir)/otherfiles")
+ end)
+```
+
+##### target:after_package
+
+###### 在打包之后执行一些自定义脚本
+
+并不会覆盖默认的打包操作,只是在打包之后增加一些自定义的操作。
+
+```lua
+target("test")
+ after_package(function (target)
+ print("")
+ end)
+```
+
+##### target:after_install
+
+###### 在安装之后执行一些自定义脚本
+
+并不会覆盖默认的安装操作,只是在安装之后增加一些自定义的操作。
+
+```lua
+target("test")
+ after_install(function (target)
+ print("")
+ end)
+```
+##### target:after_uninstall
+
+###### 在卸载之后执行一些自定义脚本
+
+并不会覆盖默认的卸载操作,只是在卸载之后增加一些自定义的操作。
+
+```lua
+target("test")
+ after_uninstall(function (target)
+ print("")
+ end)
+```
+
+##### target:after_run
+
+###### 在运行之后执行一些自定义脚本
+
+并不会覆盖默认的运行操作,只是在运行之后增加一些自定义的操作。
+
+```lua
+target("test")
+ after_run(function (target)
+ print("")
+ end)
+```
+
+
+##### target:set_config_h
+
+###### 设置自动生成的配置头文件路径
+
+<p class="warning">
+2.1.5版本之后,此接口已废弃,请使用[set_config_header](#targetset_config_header)。
+</p>
+
+如果你想在xmake配置项目成功后,或者自动检测某个选项通过后,把检测的结果写入配置头文件,那么需要调用这个接口来启用自动生成`config.h`文件。
+
+使用方式例如:
+
+```lua
+target("test")
+
+ -- 启用并设置需要自动生成的config.h文件路径
+ set_config_h("$(buildir)/config.h")
+
+ -- 设置自动检测生成的宏开关的名字前缀
+ set_config_h_prefix("TB_CONFIG")
+```
+
+当这个target中通过下面的这些接口,对这个target添加了相关的选项依赖、包依赖、接口依赖后,如果某依赖被启用,那么对应的一些宏定义配置,会自动写入被设置的`config.h`文件中去。
+
+* [add_options](#targetadd_options)
+* [add_packages](#targetadd_packages)
+* [add_cfuncs](#targetadd_cfuncs)
+* [add_cxxfuncs](#targetadd_cxxfuncs)
+
+这些接口,其实底层都用到了[option](#option)选项中的一些检测设置,例如:
+
+```lua
+option("wchar")
+
+ -- 添加对wchar_t类型的检测
+ add_ctypes("wchar_t")
+
+ -- 如果检测通过,自动生成 TB_CONFIG_TYPE_HAVE_WCHAR的宏开关到config.h
+ add_defines_h("$(prefix)_TYPE_HAVE_WCHAR")
+
+target("test")
+
+ -- 启用头文件自动生成
+ set_config_h("$(buildir)/config.h")
+ set_config_h_prefix("TB_CONFIG")
+
+ -- 添加对wchar选项的依赖关联,只有加上这个关联,wchar选项的检测结果才会写入指定的config.h中去
+ add_options("wchar")
+```
+
+##### target:set_config_h_prefix
+
+###### 设置自动生成的头文件中宏定义命名前缀
+
+<p class="warning">
+2.1.5版本之后,此接口已废弃,请使用[set_config_header](#targetset_config_header)。
+</p>
+
+具体使用见:[set_config_h](#targetset_config_h)
+
+如果设置了:
+
+```lua
+target("test")
+ set_config_h_prefix("TB_CONFIG")
+```
+
+那么,选项中`add_defines_h("$(prefix)_TYPE_HAVE_WCHAR")`的$(prefix)会自动被替换成新的前缀值。
+
+##### target:set_config_header
+
+###### 设置自动生成的配置头文件路径和前缀
+
+此接口是[set_config_h](#targetset_config_h)和[set_config_h_prefix](#targetset_config_h_prefix)的升级版本,2.1.5之后支持。
+
+如果你想在xmake配置项目成功后,或者自动检测某个选项通过后,把检测的结果写入配置头文件,那么需要调用这个接口来启用自动生成`config.h`文件。
+
+使用方式例如:
+
+```lua
+target("test")
+ set_config_header("$(buildir)/config.h", {prefix = "TB_CONFIG"})
+```
+
+上面的代码,启用并设置需要自动生成的config.h文件路径,并且设置自动检测生成的宏开关的名字前缀:`TB_CONFIG`, 当然这个前缀的设置是可选的。
+
+```lua
+target("test")
+ set_config_header("$(buildir)/config.h")
+```
+
+如果不设置前缀,将会自动根据target名生成一个唯一字串。
+
+当这个target中通过下面的这些接口,对这个target添加了相关的选项依赖、包依赖、接口依赖后,如果某依赖被启用,那么对应的一些宏定义配置,会自动写入被设置的`config.h`文件中去。
+
+* [add_options](#targetadd_options)
+* [add_packages](#targetadd_packages)
+* [add_cfuncs](#targetadd_cfuncs)
+* [add_cxxfuncs](#targetadd_cxxfuncs)
+
+这些接口,其实底层都用到了[option](#option)选项中的一些检测设置,例如:
+
+```lua
+option("wchar")
+
+ -- 添加对wchar_t类型的检测
+ add_ctypes("wchar_t")
+
+ -- 如果检测通过,自动生成 TB_CONFIG_TYPE_HAVE_WCHAR的宏开关到config.h
+ add_defines_h_if_ok("$(prefix)_TYPE_HAVE_WCHAR")
+
+target("test")
+
+ -- 启用头文件自动生成
+ set_config_header("$(buildir)/config.h", {prefix = "TB_CONFIG"})
+
+ -- 添加对wchar选项的依赖关联,只有加上这个关联,wchar选项的检测结果才会写入指定的config.h中去
+ add_options("wchar")
+```
+
+
+##### target:set_pcheader
+
+###### 设置c预编译头文件
+
+xmake支持通过预编译头文件去加速c程序编译,目前支持的编译器有:gcc, clang和msvc。
+
+使用方式如下:
+
+```lua
+target("test")
+ set_pcheader("header.h")
+```
+
+##### target:set_pcxxheader
+
+###### 设置c++预编译头文件
+
+xmake支持通过预编译头文件去加速c++程序编译,目前支持的编译器有:gcc, clang和msvc。
+
+使用方式如下:
+
+```lua
+target("test")
+ set_pcxxheader("header.h")
+```
+
+##### target:add_deps
+
+###### 添加子工程目标依赖
+
+添加当前目标的依赖目标,编译的时候,会去优先编译依赖的目标,然后再编译当前目标。。。
+
+```lua
+target("test1")
+ set_kind("static")
+ set_files("*.c")
+
+target("test2")
+ set_kind("static")
+ set_files("*.c")
+
+target("demo")
+
+ -- 添加依赖目标:test1, test2
+ add_deps("test1", "test2")
+
+ -- 链接libtest1.a,libtest2.a
+ add_links("test1", "test2")
+```
+
+上面的例子,在编译目标demo的时候,需要先编译test1, test2目标,因为demo会去用到他们
+
+<p class="tip">
+2.1.5版本后,target会自动继承依赖目标中的配置和属性,不再需要额外调用`add_links`, `add_includedirs`和`add_linkdirs`等接口去关联依赖目标了。
+</p>
+
+2.1.5版本之后,上述代码可简化为:
+
+```lua
+target("test1")
+ set_kind("static")
+ set_files("*.c")
+
+target("test2")
+ set_kind("static")
+ set_files("*.c")
+
+target("demo")
+ add_deps("test1", "test2") -- 会自动链接依赖目标
+```
+
+并且继承关系是支持级联的,例如:
+
+```lua
+target("library1")
+ set_kind("static")
+ add_files("*.c")
+ add_headers("inc1/*.h")
+
+target("library2")
+ set_kind("static")
+ add_deps("library1")
+ add_files("*.c")
+ add_headers("inc2/*.h")
+
+target("test")
+ set_kind("binary")
+ add_deps("library2")
+```
+
+如果我们还是想以前那样,并不想继承依赖target的任何配置,如何操作呢?这个在2.1.6版本中也对其进行了支持,通过:
+
+```lua
+add_deps("dep1", "dep2", {inherit = false})
+```
+
+通过显示设置inherit配置,来告诉xmake,这两个依赖的配置是否需要被继承,如果不设置,默认就是启用继承的。
+
+##### target:add_links
+
+###### 添加链接库名
+
+为当前目标添加链接库,一般这个要与[add_linkdirs](#targetadd_linkdirs)配对使用。
+
+```lua
+target("demo")
+
+ -- 添加对libtest.a的链接,相当于 -ltest
+ add_links("test")
+
+ -- 添加链接搜索目录
+ add_linkdirs("$(buildir)/lib")
+```
+
+##### target:add_files
+
+###### 添加源代码文件
+
+用于添加目标工程的源文件,甚至库文件,目前支持的一些文件类型:
+
+| 支持的源文件类型 | 描述 |
+| ------------------ | ---------------------------------- |
+| .c/.cpp/.cc/.cxx | c++文件 |
+| .s/.S/.asm | 汇编文件 |
+| .m/.mm | objc文件 |
+| .swift | swift文件 |
+| .go | golang文件 |
+| .o/.obj | 对象文件 |
+| .a/.lib | 静态库文件,会自动合并库到目标程序 |
+| .rc | msvc的资源文件 |
+
+其中通配符`*`表示匹配当前目录下文件,而`**`则匹配多级目录下的文件。
+
+例如:
+
+```lua
+add_files("src/test_*.c")
+add_files("src/xxx/**.cpp")
+add_files("src/asm/*.S", "src/objc/**/hello.m")
+```
+
+`add_files`的使用其实是相当灵活方便的,其匹配模式借鉴了premake的风格,但是又对其进行了改善和增强。
+
+使得不仅可以匹配文件,还有可以在添加文件同时,过滤排除指定模式的一批文件。
+
+例如:
+
+```lua
+-- 递归添加src下的所有c文件,但是不包括src/impl/下的所有c文件
+add_files("src/**.c|impl/*.c")
+
+-- 添加src下的所有cpp文件,但是不包括src/test.cpp、src/hello.cpp以及src下所有带xx_前缀的cpp文件
+add_files("src/*.cpp|test.cpp|hello.cpp|xx_*.cpp")
+```
+
+其中分隔符`|`之后的都是需要排除的文件,这些文件也同样支持匹配模式,并且可以同时添加多个过滤模式,只要中间用`|`分割就行了。。
+
+添加文件的时候支持过滤一些文件的一个好处就是,可以为后续根据不同开关逻辑添加文件提供基础。
+
+<p class="tip">
+为了使得描述上更加的精简,`|`之后的过滤描述都是基于起一个模式:`src/*.cpp` 中`*`之前的目录为基础的。
+所以上面的例子后面过滤的都是在src下的文件,这个是要注意的。
+</p>
+
+2.1.6版本之后,对`add_files`进行了改进,支持基于files更细粒度的编译选项控制,例如:
+
+```lua
+target("test")
+ add_defines("TEST1")
+ add_files("src/*.c")
+ add_files("test/*.c", "test2/test2.c", {defines = "TEST2", languages = "c99", includedirs = ".", cflags = "-O0"})
+```
+
+可以在`add_files`的最后一个参数,传入一个配置table,去控制指定files的编译选项,里面的配置参数跟target的一致,并且这些文件还会继承target的通用配置`-DTEST1`
+
+##### target:add_headers
+
+###### 添加安装的头文件
+
+安装指定的头文件到build目录,如果设置了[set_headerdir](#targetset_headerdir), 则输出到指定目录。
+
+安装规则的语法跟[add_files](#targetadd_files)类似,例如:
+
+```lua
+ -- 安装tbox目录下所有的头文件(忽略impl目录下的文件),并且按()指定部分作为相对路径,进行安装
+ add_headers("../(tbox/**.h)|**/impl/**.h")
+```
+
+##### target:add_linkdirs
+
+###### 添加链接库搜索目录
+
+设置链接库的搜索目录,这个接口的使用方式如下:
+
+```lua
+target("test")
+ add_linkdirs("$(buildir)/lib")
+```
+
+此接口相当于gcc的`-Lxxx`链接选项。
+
+一般他是与[add_links](#targetadd_links)配合使用的,当然也可以直接通过[add_ldflags](#targetadd_ldflags)或者[add_shflags](#targetadd_shflags)接口来添加,也是可以的。
+
+<p class="tip">
+如果不想在工程中写死,可以通过:`xmake f --linkdirs=xxx`或者`xmake f --ldflags="-L/xxx"`的方式来设置,当然这种手动设置的目录搜索优先级更高。
+</p>
+
+##### target:add_rpathdirs
+
+###### 添加程序运行时动态库的加载搜索目录
+
+通过[add_linkdirs](#targetadd_linkdirs)设置动态库的链接搜索目录后,程序被正常链接,但是在linux平台想要正常运行编译后的程序,会报加载动态库失败。
+
+因为没找到动态库的加载目录,想要正常运行依赖动态库的程序,需要设置`LD_LIBRARY_PATH`环境变量,指定需要加载的动态库目录。
+
+但是这种方式是全局的,影响太广,更好的方式是通过`-rpath=xxx`的链接器选项,在链接程序的时候设置好需要加载的动态库搜索路径,而xmake对其进行了封装,通过`add_rpathdirs`更好的处理跨平台问题。
+
+具体使用如下:
+
+```lua
+target("test")
+ set_kind("binary")
+ add_linkdirs("$(buildir)/lib")
+ add_rpathdirs("$(buildir)/lib")
+```
+
+只需要在链接的时候,在设置下rpath目录就好了,虽然也可以通过`add_ldflags("-Wl,-rpath=xxx")`达到相同的目的,但是这个接口更加通用。
+
+内部会对不同平台进行处理,像在macOS下,是不需要`-rpath`设置的,也是可以正常加载运行程序,因此针对这个平台,xmake内部会直接忽略器设置,避免链接报错。
+
+而在为dlang程序进行动态库链接时,xmake会自动处理成`-L-rpath=xxx`来传入dlang的链接器,这样就避免了直接使用`add_ldflags`需要自己判断和处理不同平台和编译器问题。
+
+2.1.7版本对这个接口进行了改进,支持:`@loader_path`, `@executable_path` 和 `$ORIGIN`的内置变量,来指定程序的加载目录,它们的效果基本上是一样的,主要是为了同时兼容macho, elf。
+
+例如:
+
+```lua
+target("test")
+ set_kind("binary")
+ add_linkdirs("$(buildir)/lib")
+ add_rpathdirs("@loader_path/lib")
+```
+
+指定test程序加载当前执行目录下`lib/*.[so|dylib]`的动态库文件,这将有助于提升程序的可移植性,不用写死绝对路径和相对路径,导致程序和目录切换引起程序加载动态库失败。
+
+##### target:add_includedirs
+
+###### 添加头文件搜索目录
+
+设置头文件的搜索目录,这个接口的使用方式如下:
+
+```lua
+target("test")
+ add_includedirs("$(buildir)/include")
+```
+
+当然也可以直接通过[add_cxflags](#targetadd_cxflags)或者[add_mxflags](#targetadd_mxflags)等接口来设置,也是可以的。
+
+<p class="tip">
+如果不想在工程中写死,可以通过:`xmake f --includedirs=xxx`或者`xmake f --cxflags="-I/xxx"`的方式来设置,当然这种手动设置的目录搜索优先级更高。
+</p>
+
+##### target:add_defines
+
+###### 添加宏定义
+
+```lua
+add_defines("DEBUG", "TEST=0", "TEST2=\"hello\"")
+```
+
+相当于设置了编译选项:
+
+```
+-DDEBUG -DTEST=0 -DTEST2=\"hello\"
+```
+
+##### target:add_undefines
+
+###### 取消宏定义
+
+```lua
+add_undefines("DEBUG")
+```
+
+相当于设置了编译选项:`-UDEBUG`
+
+在代码中相当于:`#undef DEBUG`
+
+##### target:add_defines_h
+
+###### 添加宏定义到头文件
+
+添加宏定义到`config.h`配置文件,`config.h`的设置,可参考[set_config_h](#targetset_config_h)接口。
+
+##### target:add_undefines_h
+
+###### 取消宏定义到头文件
+
+在`config.h`配置文件中通过`undef`禁用宏定义,`config.h`的设置,可参考[set_config_h](#targetset_config_h)接口。
+
+##### target:add_cflags
+
+###### 添加c编译选项
+
+仅对c代码添加编译选项
+
+```lua
+add_cflags("-g", "-O2", "-DDEBUG")
+```
+
+<p class="warning">
+所有选项值都基于gcc的定义为标准,如果其他编译器不兼容(例如:vc),xmake会自动内部将其转换成对应编译器支持的选项值。
+用户无需操心其兼容性,如果其他编译器没有对应的匹配值,那么xmake会自动忽略器设置。
+</p>
+
+##### target:add_cxflags
+
+###### 添加c/c++编译选项
+
+同时对c/c++代码添加编译选项
+
+##### target:add_cxxflags
+
+###### 添加c++编译选项
+
+仅对c++代码添加编译选项
+
+##### target:add_mflags
+
+###### 添加objcc编译选项
+
+仅对objc代码添加编译选项
+
+```lua
+add_mflags("-g", "-O2", "-DDEBUG")
+```
+
+##### target:add_mxflags
+
+###### 添加objc/objc++编译选项
+
+同时对objc/objc++代码添加编译选项
+
+```lua
+add_mxflags("-framework CoreFoundation")
+```
+
+##### target:add_mxxflags
+
+###### 添加objc++编译选项
+
+仅对objc++代码添加编译选项
+
+```lua
+add_mxxflags("-framework CoreFoundation")
+```
+
+##### target:add_scflags
+
+###### 添加swift编译选项
+
+对swift代码添加编译选项
+
+```lua
+add_scflags("xxx")
+```
+
+##### target:add_asflags
+
+###### 添加汇编编译选项
+
+对汇编代码添加编译选项
+
+```lua
+add_asflags("xxx")
+```
+
+##### target:add_gcflags
+
+###### 添加go编译选项
+
+对golang代码添加编译选项
+
+```lua
+add_gcflags("xxx")
+```
+
+##### target:add_dcflags
+
+###### 添加dlang编译选项
+
+对dlang代码添加编译选项
+
+```lua
+add_dcflags("xxx")
+```
+
+##### target:add_rcflags
+
+###### 添加rust编译选项
+
+对rust代码添加编译选项
+
+```lua
+add_rcflags("xxx")
+```
+
+##### target:add_ldflags
+
+###### 添加链接选项
+
+添加静态链接库选项
+
+```lua
+add_ldflags("-L/xxx", "-lxxx")
+```
+
+##### target:add_arflags
+
+###### 添加静态库归档选项
+
+影响对静态库的生成
+
+```lua
+add_arflags("xxx")
+```
+##### target:add_shflags
+
+###### 添加动态库链接选项
+
+影响对动态库的生成
+
+```lua
+add_shflags("xxx")
+```
+
+##### target:add_cfunc
+
+###### 添加单个c库函数检测
+
+与[add_cfuncs](#targetadd_cfuncs)类似,只是仅对单个函数接口进行设置,并且仅对`target`域生效,`option`中不存在此接口。
+
+此接口的目的主要是为了在`config.h`中更加高度定制化的生成宏开关,例如:
+
+```lua
+target("demo")
+
+ -- 设置和启用config.h
+ set_config_h("$(buildir)/config.h")
+ set_config_h_prefix("TEST")
+
+ -- 仅通过参数一设置模块名前缀
+ add_cfunc("libc", nil, nil, {"sys/select.h"}, "select")
+
+ -- 通过参数三,设置同时检测链接库:libpthread.a
+ add_cfunc("pthread", nil, "pthread", "pthread.h", "pthread_create")
+
+ -- 通过参数二设置接口别名
+ add_cfunc(nil, "PTHREAD", nil, "pthread.h", "pthread_create")
+```
+
+生成的结果如下:
+
+```c
+#ifndef TEST_H
+#define TEST_H
+
+// 宏命名规则:$(prefix)前缀 _ 模块名(如果非nil)_ HAVE _ 接口名或者别名 (大写)
+#define TEST_LIBC_HAVE_SELECT 1
+#define TEST_PTHREAD_HAVE_PTHREAD_CREATE 1
+#define TEST_HAVE_PTHREAD 1
+
+#endif
+```
+
+如果要更加灵活的函数检测,可以通过[lib.detect.has_cfuncs](#detect-has_cfuncs)在自定义脚本中实现。
+
+##### target:add_cxxfunc
+
+###### 添加单个c++库函数检测
+
+与[add_cfunc](#targetadd_cfunc)类似,只是检测的函数接口是c++函数。
+
+##### target:add_cfuncs
+
+###### 添加c库函数检测
+
+<p class="warning">
+此接口是`target`和`option`共用的接口,但是接口行为稍有不同。
+</p>
+
+| 接口域 | 描述 | 例子 |
+| ------ | ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
+| target | 头文件、链接库和函数接口同时指定 | `add_cfuncs("libc", nil, {"signal.h", "setjmp.h"}, "signal", "setjmp", "sigsetjmp{sigjmp_buf buf; sigsetjmp(buf, 0);}", "kill")` |
+| option | 仅指定函数接口,头文件依赖[add_cincludes](#targetadd_cincludes)等独立接口 | `add_cincludes("setjmp.h")` `add_cfuncs("sigsetjmp")` |
+
+对于`option`,这个接口的使用很简单,跟[add_cincludes](#targetadd_cincludes)类似,例如:
+
+```lua
+option("setjmp")
+ set_default(false)
+ add_cincludes("setjmp.h")
+ add_cfuncs("sigsetjmp", "setjmp")
+ add_defines("HAVE_SETJMP")
+
+target("test")
+ add_options("setjmp")
+```
+
+此选项检测是否存在`setjmp`的一些接口,如果检测通过那么`test`目标程序将会加上`HAVE_SETJMP`的宏定义。
+
+<p class="warning">
+需要注意的是,在`option`中使用此接口检测依赖函数,需要同时使用独立的[add_cincludes](#targetadd_cincludes)增加头文件搜索路径,指定[add_links](#targetadd_links)链接库(可选),否则检测不到指定函数。
+<br><br>
+并且某些头文件接口是通过宏开关分别定义的,那么检测的时候最好通过[add_defines](#targetadd_defines)带上依赖的宏开关。
+</p>
+
+对于`target`,此接口可以同时设置:依赖的头文件、依赖的链接模块、依赖的函数接口,保证检测环境的完整性,例如:
+
+```lua
+target("test")
+
+ -- 添加libc库接口相关检测
+ -- 第一个参数:模块名,用于最后的宏定义前缀生成
+ -- 第二个参数:链接库
+ -- 第三个参数:头文件
+ -- 之后的都是函数接口列表
+ add_cfuncs("libc", nil, {"signal.h", "setjmp.h"}, "signal", "setjmp", "sigsetjmp{sigjmp_buf buf; sigsetjmp(buf, 0);}", "kill")
+
+ -- 添加pthread库接口相关检测,同时指定需要检测`libpthread.a`链接库是否存在
+ add_cfuncs("posix", "pthread", "pthread.h", "pthread_mutex_init",
+ "pthread_create",
+ "pthread_setspecific",
+ "pthread_getspecific",
+ "pthread_key_create",
+ "pthread_key_delete")
+```
+
+设置`test`目标,依赖这些接口,构建时会预先检测他们,并且如果通过[set_config_h](#targetset_config_h)接口设置的自动生成头文件:`config.h`
+
+那么,检测结果会自动加到对应的`config.h`上去,这也是`option`没有的功能,例如:
+
+```c
+#define TB_CONFIG_LIBC_HAVE_SIGNAL 1
+#define TB_CONFIG_LIBC_HAVE_SETJMP 1
+#define TB_CONFIG_LIBC_HAVE_SIGSETJMP 1
+#define TB_CONFIG_LIBC_HAVE_KILL 1
+
+#define TB_CONFIG_POSIX_HAVE_PTHREAD_MUTEX_INIT 1
+#define TB_CONFIG_POSIX_HAVE_PTHREAD_CREATE 1
+#define TB_CONFIG_POSIX_HAVE_PTHREAD_SETSPECIFIC 1
+#define TB_CONFIG_POSIX_HAVE_PTHREAD_GETSPECIFIC 1
+#define TB_CONFIG_POSIX_HAVE_PTHREAD_KEY_CREATE 1
+#define TB_CONFIG_POSIX_HAVE_PTHREAD_KEY_DELETE 1
+```
+
+由于,不同头文件中,函数的定义方式不完全相同,例如:宏函数、静态内联函数、extern函数等。
+
+要想完全检测成功,检测语法上需要一定程度的灵活性,下面是一些语法规则:
+
+| 检测语法 | 例子 |
+| ------------- | ----------------------------------------------- |
+| 纯函数名 | `sigsetjmp` |
+| 单行调用 | `sigsetjmp((void*)0, 0)` |
+| 函数块调用 | `sigsetjmp{sigsetjmp((void*)0, 0);}` |
+| 函数块 + 变量 | `sigsetjmp{int a = 0; sigsetjmp((void*)a, a);}` |
+
+##### target:add_cxxfuncs
+
+###### 添加c++库函数检测
+
+与[add_cfuncs](#targetadd_cfuncs)类似,只是检测的函数接口是c++函数。
+
+##### target:add_options
+
+###### 添加关联选项
+
+这个接口跟[set_options](#targetset_options)类似,唯一的区别就是,此处是追加选项,而[set_options](#targetset_options)每次设置会覆盖先前的设置。
+
+##### target:add_packages
+
+###### 添加包依赖
+
+在target作用域中,添加集成包依赖,例如:
+
+```lua
+target("test")
+ add_packages("zlib", "polarssl", "pcre", "mysql")
+```
+
+这样,在编译test目标时,如果这个包存在的,将会自动追加包里面的宏定义、头文件搜索路径、链接库目录,也会自动链接包中所有库。
+
+用户不再需要自己单独调用[add_links](#targetadd_links),[add_includedirs](#targetadd_includedirs), [add_ldflags](#targetadd_ldflags)等接口,来配置依赖库链接了。
+
+对于如何设置包搜索目录,可参考:[add_packagedirs](#targetadd_packagedirs) 接口
+
+##### target:add_languages
+
+###### 添加语言标准
+
+与[set_languages](#targetset_languages)类似,唯一区别是这个接口不会覆盖掉之前的设置,而是追加设置。
+
+##### target:add_vectorexts
+
+###### 添加向量扩展指令
+
+添加扩展指令优化选项,目前支持以下几种扩展指令集:
+
+```lua
+add_vectorexts("mmx")
+add_vectorexts("neon")
+add_vectorexts("avx", "avx2")
+add_vectorexts("sse", "sse2", "sse3", "ssse3")
+```
+
+<p class="tip">
+如果当前设置的指令集编译器不支持,xmake会自动忽略掉,所以不需要用户手动去判断维护,只需要将你需要的指令集全部设置上就行了。
+</p>
+
+##### target:add_frameworks
+
+###### 添加链接框架
+
+目前主要用于`ios`和`macosx`平台的`objc`和`swift`程序,例如:
+
+```lua
+target("test")
+ add_frameworks("Foundation", "CoreFoundation")
+```
+
+当然也可以使用[add_mxflags](#targetadd_mxflags)和[add_ldflags](#targetadd_ldflags)来设置,不过比较繁琐,不建议这样设置。
+
+```lua
+target("test")
+ add_mxflags("-framework Foundation", "-framework CoreFoundation")
+ add_ldflags("-framework Foundation", "-framework CoreFoundation")
+```
+
+如果不是这两个平台,这些设置将会被忽略。
+
+##### target:add_frameworkdirs
+
+###### 添加链接框架搜索目录
+
+对于一些第三方framework,那么仅仅通过[add_frameworks](#targetadd_frameworks)是没法找到的,还需要通过这个接口来添加搜索目录。
+
+```lua
+target("test")
+ add_frameworks("MyFramework")
+ add_frameworkdirs("/tmp/frameworkdir", "/tmp/frameworkdir2")
+```
+
+#### Configuration Option
+
+定义和设置选项开关,每个`option`对应一个选项,可用于自定义编译配置选项、开关设置。
+
+<p class="tip">
+除了`target`以外的所有域接口,例如`option`,`task`等的接口,默认不能放置在外面的全局作用域中的(除非部分跟target共用的接口除外)。
+如果要设置值影响所有`option`,`task`等选项,可以通过匿名全局域来设置。
+</p>
+
+例如:
+
+```lua
+-- 进入option的匿名全局域,里面的设置会同时影响test和test2选项
+option()
+ add_defines("DEBUG")
+
+option("test")
+ -- ...
+ -- 尽量保持缩进,因为这个之后的所有设置,都是针对test选项的
+
+option("test2")
+ -- ...
+```
+
+<p class="tip">
+`option`域是可以重复进入来实现分离设置的,如果要显示离开当前选项的作用域设置,可以手动调用[option_end](#option_end)接口。
+</p>
+
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------------- | -------------------------------------------- | -------- |
+| [option](#option) | 定义选项 | >= 2.0.1 |
+| [option_end](#option_end) | 结束定义选项 | >= 2.1.1 |
+| [add_deps](#optionadd_deps) | 添加选项依赖 | >= 2.1.5 |
+| [before_check](#optionbefore_check) | 选项检测之前执行此脚本 | >= 2.1.5 |
+| [on_check](#optionon_check) | 自定义选项检测脚本 | >= 2.1.5 |
+| [after_check](#optionafter_check) | 选项检测之后执行此脚本 | >= 2.1.5 |
+| [set_default](#optionset_default) | 设置默认值 | >= 2.0.1 |
+| [set_showmenu](#optionset_showmenu) | 设置是否启用菜单显示 | >= 1.0.1 |
+| [set_category](#optionset_category) | 设置选项分类,仅用于菜单显示 | >= 1.0.1 |
+| [set_description](#optionset_description) | 设置菜单显示描述 | >= 1.0.1 |
+| [add_links](#optionadd_links) | 添加链接库检测 | >= 1.0.1 |
+| [add_linkdirs](#optionadd_linkdirs) | 添加链接库检测需要的搜索目录 | >= 1.0.1 |
+| [add_rpathdirs](#optionadd_rpathdirs) | 添加运行时候动态链接库搜索目录 | >= 2.1.3 |
+| [add_cincludes](#optionadd_cincludes) | 添加c头文件检测 | >= 1.0.1 |
+| [add_cxxincludes](#optionadd_cxxincludes) | 添加c++头文件检测 | >= 1.0.1 |
+| [add_ctypes](#optionadd_ctypes) | 添加c类型检测 | >= 1.0.1 |
+| [add_cxxtypes](#optionadd_cxxtypes) | 添加c++类型检测 | >= 1.0.1 |
+| [add_csnippet](#optionadd_csnippet) | 添加c代码片段检测 | >= 2.1.5 |
+| [add_cxxsnippet](#optionadd_cxxsnippet) | 添加c++代码片段检测 | >= 2.1.5 |
+| [set_warnings](#targetset_warnings) | 设置警告级别 | >= 1.0.1 |
+| [set_optimize](#targetset_optimize) | 设置优化级别 | >= 1.0.1 |
+| [set_languages](#targetset_languages) | 设置代码语言标准 | >= 1.0.1 |
+| [add_includedirs](#targetadd_includedirs) | 添加头文件搜索目录 | >= 1.0.1 |
+| [add_defines](#targetadd_defines) | 添加宏定义 | >= 1.0.1 |
+| [add_undefines](#targetadd_undefines) | 取消宏定义 | >= 1.0.1 |
+| [add_defines_h](#targetadd_defines_h) | 添加宏定义到头文件 | >= 1.0.1 |
+| [add_undefines_h](#targetadd_undefines_h) | 取消宏定义到头文件 | >= 1.0.1 |
+| [add_cflags](#targetadd_cflags) | 添加c编译选项 | >= 1.0.1 |
+| [add_cxflags](#targetadd_cxflags) | 添加c/c++编译选项 | >= 1.0.1 |
+| [add_cxxflags](#targetadd_cxxflags) | 添加c++编译选项 | >= 1.0.1 |
+| [add_mflags](#targetadd_mflags) | 添加objc编译选项 | >= 2.0.1 |
+| [add_mxflags](#targetadd_mxflags) | 添加objc/objc++编译选项 | >= 2.0.1 |
+| [add_mxxflags](#targetadd_mxxflags) | 添加objc++编译选项 | >= 2.0.1 |
+| [add_scflags](#targetadd_scflags) | 添加swift编译选项 | >= 2.1.1 |
+| [add_asflags](#targetadd_asflags) | 添加汇编编译选项 | >= 2.1.1 |
+| [add_gcflags](#targetadd_gcflags) | 添加go编译选项 | >= 2.1.1 |
+| [add_dcflags](#targetadd_dcflags) | 添加dlang编译选项 | >= 2.1.1 |
+| [add_rcflags](#targetadd_rcflags) | 添加rust编译选项 | >= 2.1.1 |
+| [add_ldflags](#targetadd_ldflags) | 添加链接选项 | >= 2.1.1 |
+| [add_arflags](#targetadd_arflags) | 添加静态库归档选项 | >= 2.1.1 |
+| [add_shflags](#targetadd_shflags) | 添加动态库链接选项 | >= 2.0.1 |
+| [add_cfuncs](#targetadd_cfuncs) | 添加c库函数检测 | >= 1.0.1 |
+| [add_cxxfuncs](#targetadd_cxxfuncs) | 添加c++库函数接口 | >= 1.0.1 |
+| [add_languages](#targetadd_languages) | 添加语言标准 | >= 2.0.1 |
+| [add_vectorexts](#targetadd_vectorexts) | 添加向量扩展指令 | >= 2.0.1 |
+| [add_frameworks](#targetadd_frameworks) | 添加链接框架 | >= 2.1.1 |
+| [add_frameworkdirs](#targetadd_frameworkdirs) | 添加链接框架 | >= 2.1.5 |
+
+| 废弃接口 | 描述 | 支持版本 |
+| ----------------------------------------------------- | -------------------------------------------- | ---------------- |
+| [add_bindings](#optionadd_bindings) | 添加正向关联选项,同步启用和禁用 | >= 2.0.1 < 2.1.5 |
+| [add_rbindings](#optionadd_rbindings) | 添加逆向关联选项,同步启用和禁用 | >= 2.0.1 < 2.1.5 |
+| [add_defines_if_ok](#optionadd_defines_if_ok) | 如果检测选项通过,则添加宏定义 | >= 1.0.1 < 2.1.5 |
+| [add_defines_h_if_ok](#optionadd_defines_h_if_ok) | 如果检测选项通过,则添加宏定义到配置头文件 | >= 1.0.1 < 2.1.5 |
+| [add_undefines_if_ok](#optionadd_undefines_if_ok) | 如果检测选项通过,则取消宏定义 | >= 1.0.1 < 2.1.5 |
+| [add_undefines_h_if_ok](#optionadd_undefines_h_if_ok) | 如果检测选项通过,则在配置头文件中取消宏定义 | >= 1.0.1 < 2.1.5 |
+
+##### option
+
+###### 定义选项
+
+定义和设置选项开关,可用于自定义编译配置选项、开关设置。
+
+例如,定义一个是否启用test的选项:
+
+```lua
+option("test")
+ set_default(false)
+ set_showmenu(true)
+ add_defines("-DTEST")
+```
+
+然后关联到指定的target中去:
+
+```lua
+target("demo")
+ add_options("test")
+```
+
+这样,一个选项就算定义好了,如果这个选项被启用,那么编译这个target的时候,就会自动加上`-DTEST`的宏定义。
+
+```lua
+# 手动启用这个选项
+$ xmake f --test=y
+$ xmake
+```
+
+##### option_end
+
+###### 结束定义选项
+
+这是一个可选api,显示离开选项作用域,用法和[target_end](#target_end)类似。
+
+##### option:add_deps
+
+###### 添加选项依赖
+
+通过设置依赖,可以调整选项的检测顺序,一般用于[on_check](#optionon_check)等检测脚本的调用时机。
+
+```lua
+option("small")
+ set_default(true)
+ on_check(function (option)
+ -- ...
+ end)
+
+option("test")
+ add_deps("small")
+ set_default(true)
+ on_check(function (option)
+ if option:dep("small"):enabled() then
+ option:enable(false)
+ end
+ end)
+```
+
+当依赖的small选项检测完成后,通过判断small选项的状态,来控制test的选项状态。
+
+##### option:before_check
+
+###### 选项检测之前执行此脚本
+
+例如:在检测之前,通过[find_package](#detect-find_package)来查找包,将`links`, `includedirs`和`linkdirs`等信息添加到option中去,
+然后开始选项检测,通过后就会自动链接到target上。
+
+```lua
+option("zlib")
+ before_check(function (option)
+ import("lib.detect.find_package")
+ option:add(find_package("zlib"))
+ end)
+```
+
+##### option:on_check
+
+###### 自定义选项检测脚本
+
+此脚本会覆盖内置的选项检测逻辑。
+
+```lua
+option("test")
+ add_deps("small")
+ set_default(true)
+ on_check(function (option)
+ if option:dep("small"):enabled() then
+ option:enable(false)
+ end
+ end)
+```
+
+如果test依赖的选项通过,则禁用test选项。
+
+##### option:after_check
+
+###### 选项检测之后执行此脚本
+
+在选项检测完成后,执行此脚本做一些后期处理,也可以在此时重新禁用选项:
+
+```lua
+option("test")
+ add_deps("small")
+ add_links("pthread")
+ after_check(function (option)
+ option:enable(false)
+ end)
+```
+
+##### option:set_default
+
+###### 设置选项默认值
+
+在没有通过`xmake f --option=[y|n}`等命令修改选项值的时候,这个选项本身也是有个默认值的,可以通过这个接口来设置:
+
+```lua
+option("test")
+ -- 默认禁用这个选项
+ set_default(false)
+```
+
+选项的值不仅支持boolean类型,也可以是字符串类型,例如:
+
+```lua
+option("test")
+ set_default("value")
+```
+
+| 值类型 | 描述 | 配置 |
+| ------ | -------------------------------------- | -----------------------------------------------|
+| boolean | 一般用作参数开关,值范围:`true/false` | `xmake f --optionname=[y/n/yes/no/true/false]` |
+| string | 可以是任意字符串,一般用于模式判断 | `xmake f --optionname=value` |
+
+如果是`boolean`值的选项,可以通过[is_option](#is_option)来进行判断,选项是否被启用。
+
+如果是`string`类型的选项,可以在内建变量中直接使用,例如:
+
+```lua
+-- 定义一个路径配置选项,默认使用临时目录
+option("rootdir")
+ set_default("$(tmpdir)")
+ set_showmenu(true)
+
+target("test")
+ -- 添加指定选项目录中的源文件
+ add_files("$(rootdir)/*.c")
+```
+
+其中,`$(rootdir)` 就是自定义的选项内建变量,通过手动配置,可以动态修改它的值:
+
+```bash
+$ xmake f --rootdir=~/projectdir/src
+$ xmake
+```
+
+给这个`rootdir`选项指定一个其他的源码目录路径,然后编译。
+
+选项的检测行为:
+
+| default值 | 检测行为 |
+| ---------- | --------------------------------------------------------------------------------------------- |
+| 没有设置 | 优先手动配置修改,默认禁用,否则自动检测,可根据手动传入的值类型,自动切换boolean和string类型 |
+| false | 开关选项,不自动检测,默认禁用,可手动配置修改 |
+| true | 开关选项,不自动检测,默认启用,可手动配置修改 |
+| string类型 | 无开关状态,不自动检测,可手动配置修改,一般用于配置变量传递 |
+
+##### option:set_showmenu
+
+###### 设置是否启用菜单显示
+
+如果设置为`true`,那么在`xmake f --help`里面就会出现这个选项,也就能通过`xmake f --optionname=xxx`进行配置,否则只能在`xmake.lua`内部使用,无法手动配置修改。
+
+```lua
+option("test")
+ set_showmenu(true)
+```
+
+设置为启用菜单后,执行`xmake f --help`可以看到,帮助菜单里面多了一项:
+
+```
+Options:
+ ...
+
+ --test=TEST
+```
+
+##### option:set_category
+
+###### 设置选项分类,仅用于菜单显示
+
+这个是个可选配置,仅用于在帮助菜单中,进行分类显示选项,同一类别的选项,会在同一个分组里面显示,这样菜单看起来更加的美观。
+
+例如:
+
+```lua
+option("test1")
+ set_showmenu(true)
+ set_category("test")
+
+option("test2")
+ set_showmenu(true)
+ set_category("test")
+
+option("demo1")
+ set_showmenu(true)
+ set_category("demo")
+
+option("demo2")
+ set_showmenu(true)
+ set_category("demo")
+```
+
+这里四个选项分别归类于两个分组:`test`和`demo`,那么显示的布局类似这样:
+
+```bash
+Options:
+ ...
+
+ --test1=TEST1
+ --test2=TEST2
+
+ --demo1=DEMO1
+ --demo2=DEMO2
+```
+
+这个接口,仅仅是为了调整显示布局,更加美观而已,没其他用途。
+
+##### option:set_description
+
+###### 设置菜单显示描述
+
+设置选项菜单显示时,右边的描述信息,用于帮助用户更加清楚的知道这个选项的用途,例如:
+
+```lua
+option("test")
+ set_default(false)
+ set_showmenu(true)
+ set_description("Enable or disable test")
+```
+
+生成的菜单内容如下:
+
+```
+Options:
+ ...
+
+ --test=TEST Enable or disable test (default: false)
+```
+
+这个接口也支持多行显示,输出更加详细的描述信息,例如:
+
+```lua
+option("mode")
+ set_default("debug")
+ set_showmenu(true)
+ set_description("Set build mode"
+ " - debug"
+ " - release"
+ " - profile")
+```
+
+生成的菜单内容如下:
+
+```
+Options:
+ ...
+
+ --mode=MODE Set build mode (default: debug)
+ - debug
+ - release
+ - profile
+```
+
+看到这个菜单,用户就能清楚地知道,定义的这个`mode`选项的具体用处,以及如何使用了:
+
+```bash
+$ xmake f --mode=release
+```
+
+##### option:add_bindings
+
+###### 添加正向关联选项,同步启用和禁用
+
+<p class="tip">
+2.1.5版本之后已废弃,请用[add_deps](#optionadd_deps), [on_check](#optionon_check), [after_check](#optionafter_check)等接口代替。
+</p>
+
+绑定关联选项,例如我想在命令行中配置一个`smallest`的参数:`xmake f --smallest=y`
+
+这个时候,需要同时禁用多个其他的选项开关,来禁止编译多个模块,就是这个需求,相当于一个选项 与其他 多个选项之间 是有联动效应的。
+
+而这个接口就是用来设置需要正向绑定的一些关联选项,例如:
+
+```lua
+-- 定义选项开关: --smallest=y|n
+option("smallest")
+
+ -- 添加正向绑定,如果smallest被启用,下面的所有选项开关也会同步被启用
+ add_bindings("nozip", "noxml", "nojson")
+```
+
+##### option:add_rbindings
+
+###### 添加逆向关联选项,同步启用和禁用
+
+<p class="tip">
+2.1.5版本之后已废弃,请用[add_deps](#optionadd_deps), [on_check](#optionon_check), [after_check](#optionafter_check)等接口代替。
+</p>
+
+逆向绑定关联选项,被关联选项的开关状态是相反的。
+
+```lua
+-- 定义选项开关: --smallest=y|n
+option("smallest")
+
+ -- 添加反向绑定,如果smallest被启用,下面的所有模块全部禁用
+ add_rbindings("xml", "zip", "asio", "regex", "object", "thread", "network", "charset", "database")
+ add_rbindings("zlib", "mysql", "sqlite3", "openssl", "polarssl", "pcre2", "pcre", "base")
+```
+
+<p class="warning">
+需要注意的是,命令行配置是有顺序的,你可以先通过启用smallest禁用所有模块,然后添加其他选项,逐一启用。
+</p>
+
+例如:
+
+```bash
+-- 禁用所有模块,然后仅仅启用xml和zip模块
+$ xmake f --smallest=y --xml=y --zip=y
+```
+
+##### option:add_links
+
+###### 添加链接库检测
+
+如果指定的链接库检测通过,此选项将被启用,并且对应关联的target会自动加上此链接,例如:
+
+```lua
+option("pthread")
+ set_default(false)
+ add_links("pthread")
+ add_linkdirs("/usr/local/lib")
+
+target("test")
+ add_options("pthread")
+```
+
+如果检测通过,`test`目标编译的时候就会自动加上:`-L/usr/local/lib -lpthread` 编译选项
+
+
+##### option:add_linkdirs
+
+###### 添加链接库检测时候需要的搜索目录
+
+这个是可选的,一般系统库不需要加这个,也能检测通过,如果确实没找到,可以自己追加搜索目录,提高检测通过率。具体使用见:[add_links](#optionadd_links)
+
+##### option:add_rpathdirs
+
+###### 添加程序运行时动态库的加载搜索目录
+
+在选项通过检测后,会自动添加到对应的target上去,具体使用见:[target.add_rpathdirs](#targetadd_rpathdirs)。
+
+##### option:add_cincludes
+
+###### 添加c头文件检测
+
+如果c头文件检测通过,此选项将被启用,例如:
+
+```lua
+option("pthread")
+ set_default(false)
+ add_cincludes("pthread.h")
+ add_defines("ENABLE_PTHREAD")
+
+target("test")
+ add_options("pthread")
+```
+
+此选项检测是否存在`pthread.h`的头文件,如果检测通过那么`test`目标程序将会加上`ENABLE_PTHREAD`的宏定义。
+
+如果想要更加灵活的检测,可以通过[lib.detect.has_cincludes](#detect-has_cincludes)在[option.on_check](#optionon_check)中去实现。
+
+##### option:add_cxxincludes
+
+###### 添加c++头文件检测
+
+与[add_cincludes](#optionadd_cincludes)类似,只是检测的头文件类型是c++头文件。
+
+##### option:add_ctypes
+
+###### 添加c类型检测
+
+如果c类型检测通过,此选项将被启用,例如:
+
+```lua
+option("wchar")
+ set_default(false)
+ add_cincludes("wchar_t")
+ add_defines("HAVE_WCHAR")
+
+target("test")
+ add_options("wchar")
+```
+
+此选项检测是否存在`wchar_t`的类型,如果检测通过那么`test`目标程序将会加上`HAVE_WCHAR`的宏定义。
+
+如果想要更加灵活的检测,可以通过[lib.detect.has_ctypes](#detect-has_ctypes)在[option.on_check](#optionon_check)中去实现。
+
+##### option:add_cxxtypes
+
+###### 添加c++类型检测
+
+与[add_ctypes](#optionadd_ctypes)类似,只是检测的类型是c++类型。
+
+##### option:add_csnippet
+
+###### 添加c代码片段检测
+
+如果现有的[add_ctypes](#optionadd_ctypes), [add_cfuncs](#optionadd_cfuncs)等不能满足当前的检测需求,
+可以用这个接口实现更加定制化检测一些编译器特性检测,具体见: [add_cxxsnippet](#optionadd_cxxsnippet)。
+
+##### option:add_cxxsnippet
+
+###### 添加c++代码片段检测
+
+可以用这个接口实现更加定制化检测一些编译器特性检测,尤其是c++的各种特性的检测支持,例如:
+
+```lua
+option("constexpr")
+ add_cxxsnippet("constexpr int f(int x) { int sum=0; for (int i=0; i<=x; ++i) sum += i; return sum; } constexpr int x = f(5); static_assert(x == 15);")
+```
+
+上述代码,实现对c++的constexpr特性的检测,如果检测通过,则启用constexpr选项,当然这里只是个例子。
+
+对于编译器特性的检测,有更加方便高效的检测模块,提供更强大的检测支持,具体见:[compiler.has_features](#compiler-has_features)和[detect.check_cxsnippets](#detect-check_cxsnippets)
+
+如果想要更加灵活的检测,可以通过[lib.detect.check_cxsnippets](#detect-check_cxsnippets)在[option.on_check](#optionon_check)中去实现。
+
+##### option:add_defines_if_ok
+
+###### 如果检测选项通过,则添加宏定义
+
+<p class="tip">
+2.1.5版本之后已废弃,请用[add_defines](#targetadd_defines)接口代替。
+</p>
+
+检测选项通过后才会被设置,具体使用见[add_cincludes](#optionadd_cincludes)中的例子。
+
+##### option:add_defines_h_if_ok
+
+###### 如果检测选项通过,则添加宏定义到配置头文件
+
+<p class="tip">
+2.1.5版本之后已废弃,请用[add_defines_h](#targetadd_defines_h)接口代替。
+</p>
+
+跟[add_defines_if_ok](#optionadd_defines_if_ok)类似,只是检测通过后,会在`config.h`头文件中自动加上被设置的宏定义。
+
+例如:
+
+```lua
+option("pthread")
+ set_default(false)
+ add_cincludes("pthread.h")
+ add_defines_h_if_ok("ENABLE_PTHREAD")
+
+target("test")
+ add_options("pthread")
+```
+
+通过后,会在`config.h`中加上:
+
+```c
+#define ENABLE_PTHREAD 1
+```
+
+具体`config.h`如何设置,见:[set_config_h](#targetset_config_h)
+
+##### option:add_undefines_if_ok
+
+###### 如果检测选项通过,则取消宏定义
+
+<p class="tip">
+2.1.5版本之后已废弃,请用[add_undefines](#targetadd_undefines)接口代替。
+</p>
+
+跟[add_defines_if_ok](#optionadd_defines_if_ok)类似,只是检测通过后,取消被设置的宏定义。
+
+##### option:add_undefines_h_if_ok
+
+###### 如果检测选项通过,则在配置头文件中取消宏定义
+
+<p class="tip">
+2.1.5版本之后已废弃,请用[add_undefines_h](#targetadd_undefines_h)接口代替。
+</p>
+
+跟[add_defines_h_if_ok](#optionadd_defines_h_if_ok)类似,只是检测通过后,会在`config.h`中取消被设置的宏定义。
+
+```c
+#undef DEFINED_MACRO
+```
+
+具体`config.h`如何设置,见:[set_config_h](#targetset_config_h)
+
+#### Plugin and Task
+
+xmake可以实现自定义任务或者插件,其两者的核心就是`task`任务,其两者实际上是一样的,xmake的插件都是用`task`实现的。
+
+本质上都是任务,只是[set_category](#taskset_category)分类不同而已。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [task](#task) | 定义插件或者任务 | >= 2.0.1 |
+| [task_end](#task_end) | 结束定义插件或任务 | >= 2.1.1 |
+| [set_menu](#taskset_menu) | 设置任务菜单 | >= 2.0.1 |
+| [set_category](#taskset_category) | 设置任务类别 | >= 2.0.1 |
+| [on_run](#taskon_run) | 设置任务运行脚本 | >= 2.0.1 |
+
+##### task
+
+###### 定义插件或者任务
+
+`task`域用于描述一个自定义的任务实现,与[target](#target)和[option](#option)同级。
+
+例如,这里定义一个最简单的任务:
+
+```lua
+task("hello")
+
+ -- 设置运行脚本
+ on_run(function ()
+ print("hello xmake!")
+ end)
+```
+
+这个任务只需要打印`hello xmake!`,那如何来运行呢?
+
+由于这里没有使用[set_menu](#taskset_menu)设置菜单,因此这个任务只能再`xmake.lua`的自定义脚本或者其他任务内部调用,例如:
+
+```lua
+target("test")
+
+ after_build(function (target)
+
+ -- 导入task模块
+ import("core.project.task")
+
+ -- 运行hello任务
+ task.run("hello")
+ end)
+```
+
+在构建完`test`目标后运行`hello`任务。
+
+##### task_end
+
+###### 结束定义插件或任务
+
+这是一个可选api,显示离开选项作用域,用法和[target_end](#target_end)类似。
+
+##### task:set_menu
+
+###### 设置任务菜单
+
+通过设置一个菜单,这个任务就可以开放给用户自己通过命令行手动调用,菜单的设置如下:
+
+```lua
+task("echo")
+
+ -- 设置运行脚本
+ on_run(function ()
+
+ -- 导入参数选项模块
+ import("core.base.option")
+
+ -- 初始化颜色模式
+ local modes = ""
+ for _, mode in ipairs({"bright", "dim", "blink", "reverse"}) do
+ if option.get(mode) then
+ modes = modes .. " " .. mode
+ end
+ end
+
+ -- 获取参数内容并且显示信息
+ cprint("${%s%s}%s", option.get("color"), modes, table.concat(option.get("contents") or {}, " "))
+ end)
+
+ -- 设置插件的命令行选项,这里没有任何参数选项,仅仅显示插件描述
+ set_menu {
+ -- 设置菜单用法
+ usage = "xmake echo [options]"
+
+ -- 设置菜单描述
+ , description = "Echo the given info!"
+
+ -- 设置菜单选项,如果没有选项,可以设置为{}
+ , options =
+ {
+ -- 设置k模式作为key-only型bool参数
+ {'b', "bright", "k", nil, "Enable bright." }
+ , {'d', "dim", "k", nil, "Enable dim." }
+ , {'-', "blink", "k", nil, "Enable blink." }
+ , {'r', "reverse", "k", nil, "Reverse color." }
+
+ -- 菜单显示时,空白一行
+ , {}
+
+ -- 设置kv作为key-value型参数,并且设置默认值:black
+ , {'c', "color", "kv", "black", "Set the output color."
+ , " - red"
+ , " - blue"
+ , " - yellow"
+ , " - green"
+ , " - magenta"
+ , " - cyan"
+ , " - white" }
+
+ -- 设置`vs`作为values多值型参数,还有`v`单值类型
+ -- 一般放置在最后,用于获取可变参数列表
+ , {}
+ , {nil, "contents", "vs", nil, "The info contents." }
+ }
+ }
+```
+
+定义完这个任务后,执行`xmake --help`,就会多出一个任务项来:
+
+```
+Tasks:
+
+ ...
+
+ echo Echo the given info!
+```
+
+如果通过[set_category](#taskset_category)设置分类为`plugin`,那么这个任务就是一个插件了:
+
+```
+Plugins:
+
+ ...
+
+ echo Echo the given info!
+```
+
+想要手动运行这个任务,可以执行:
+
+```bash
+$ xmake echo hello xmake!
+```
+
+就行了,如果要看这个任务定义的菜单,只需要执行:`xmake echo [-h|--help]`,显示结果如下:
+
+```bash
+Usage: $xmake echo [options]
+
+Echo the given info!
+
+Options:
+ -v, --verbose Print lots of verbose information.
+ --backtrace Print backtrace information for debugging.
+ --profile Print performance data for debugging.
+ --version Print the version number and exit.
+ -h, --help Print this help message and exit.
+
+ -F FILE, --file=FILE Read a given xmake.lua file.
+ -P PROJECT, --project=PROJECT Change to the given project directory.
+ Search priority:
+ 1. The Given Command Argument
+ 2. The Envirnoment Variable: XMAKE_PROJECT_DIR
+ 3. The Current Directory
+
+ -b, --bright Enable bright.
+ -d, --dim Enable dim.
+ --, --blink Enable blink.
+ -r, --reverse Reverse color.
+
+ -c COLOR, --color=COLOR Set the output color. (default: black)
+ - red
+ - blue
+ - yellow
+ - green
+ - magenta
+ - cyan
+ - white
+
+ contents ... The info contents.
+```
+
+<p class="tip">
+其中菜单最开头的部分选项,是xmake内置的常用选项,基本上每个任务都会用到,不需要自己额外定义,简化菜单定义。
+</p>
+
+下面,我们来实际运行下这个任务,例如我要显示红色的`hello xmake!`,只需要:
+
+```bash
+$ xmake echo -c red hello xmake!
+```
+
+也可以使用选项全名,并且加上高亮:
+
+```bash
+$ xmake echo --color=red --bright hello xmake!
+```
+
+最后面的可变参数列表,在`run`脚本中通过`option.get("contents")`获取,返回的是一个`table`类型的数组。
+
+##### task:set_category
+
+###### 设置任务类别
+
+仅仅用于菜单的分组显示,当然插件默认会用`plugin`,内置任务默认会用:`action`,但也仅仅只是个约定。
+
+<p class="tips">
+你可以使用任何自己定义的名字,相同名字会分组归类到一起显示,如果设置为`plugin`,就会显示到xmake的Plugins分组中去。
+</p>
+
+例如:
+
+```lua
+Plugins:
+ l, lua Run the lua script.
+ m, macro Run the given macro.
+ doxygen Generate the doxygen document.
+ project Generate the project file.
+ hello Hello xmake!
+ app2ipa Generate .ipa file from the given .app
+ echo Echo the given info!
+```
+
+如果没有调用这个接口设置分类,默认使用`Tasks`分组显示,代表普通任务。
+
+##### task:on_run
+
+###### 设置任务运行脚本
+
+可以有两种设置方式,最简单的就是设置内嵌函数:
+
+```lua
+task("hello")
+
+ on_run(function ()
+ print("hello xmake!")
+ end)
+```
+
+这种对于小任务很方便,也很简洁,但是对于大型任务就不太适用了,例如插件等,需要复杂的脚本支持。
+
+这个时候就需要独立的模块文件来设置运行脚本,例如:
+
+```lua
+task("hello")
+ on_run("main")
+```
+
+这里的`main`设置为脚本运行主入口模块,文件名为`main.lua`,放在定义`task`的`xmake.lua`的同目录下,当然你可以起其他文件名。
+
+目录结构如下:
+
+```
+projectdir
+ - xmake.lua
+ - main.lua
+```
+
+`main.lua`里面内容如下:
+
+```lua
+function main(...)
+ print("hello xmake!")
+end
+```
+
+就是一个简单的带`main`主函数的脚本文件,你可以通过[import](#import)导入各种扩展模块,实现复杂功能,例如:
+
+```lua
+-- 导入参数选项模块
+import("core.base.option")
+
+-- 入口函数
+function main(...)
+
+ -- 获取参数内容
+ print("color: %s", option.get("color"))
+end
+```
+
+你也可以在当前目录下,创建多个自定义的模块文件,通过[import](#import)导入后使用,例如:
+
+```
+projectdir
+ - xmake.lua
+ - main.lua
+ - module.lua
+```
+
+`module.lua`的内容如下:
+
+```lua
+-- 定义一个导出接口
+function hello()
+ print("hello xmake!")
+end
+```
+
+<p class="tip">
+私有接口,通过`_hello`带下滑线前缀命名,这样导入的模块就不会包含此接口,只在模块自身内部使用。
+</p>
+
+然后在`main.lua`进行调用:
+
+
+```lua
+import("module")
+
+function main(...)
+ module.hello()
+end
+```
+
+更多模块介绍见:[内置模块](#内置模块)和[扩展模块](扩展模块)
+
+其中,`main(...)`中参数,是通过`task.run`指定的,例如:
+
+```lua
+task.run("hello", {color="red"}, arg1, arg2, arg3)
+```
+
+里面的`arg1, arg2`这些就是传入`hello`任务`main(...)`入口的参数列表,而`{color="red"}`用来指定任务菜单中的参数选项。
+
+更加详细的`task.run`描述,见:[task.run](#task-run)
+
+#### Extension Platforms
+
+xmake除了内置的一些构建平台,还可以自己扩展自定义构建平台,可以将自己实现的平台放置在以下目录即可, xmake会自动检测并且加载他们:
+
+| 平台目录 | 描述 |
+| --------------------------- | ------------------------------------ |
+| projectdir/.xmake/platforms | 当前工程的平台目录, 只对当前工程有效 |
+| globaldir/.xmake/platforms | 全局配置的平台目录,当前主机全局有效 |
+| installdir/xmake/platforms | xmake安装后内置的平台目录 |
+
+用户可根据不同需求,将自定义的平台放置在对应的目录中。
+
+<p class="warning">
+平台的扩展定义,尽量不要放到工程`xmake.lua`中去,新建一个单独的平台目录放置相关描述实现。
+</p>
+
+平台描述的目录结构:
+
+```
+platforms
+
+ - myplat1
+ - xmake.lua
+
+ - myplat2
+ - xmake.lua
+```
+
+其中`xmake.lua`为每个平台的主描述文件,相当于入口描述。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [platform](#platform) | 定义平台 | >= 2.0.1 |
+| [platform_end](#platform_end) | 结束定义平台 | >= 2.1.1 |
+| [set_os](#platformset_os) | 设置平台系统 | >= 2.0.1 |
+| [set_menu](#platformset_menu) | 设置平台菜单 | >= 2.0.1 |
+| [set_hosts](#platformset_hosts) | 设置平台支持的主机环境 | >= 2.0.1 |
+| [set_archs](#platformset_archs) | 设置平台支持的架构环境 | >= 2.0.1 |
+| [set_tooldirs](#platformset_tooldirs) | 设置平台工具的搜索目录 | >= 2.0.1 |
+| [on_load](#platformon_load) | 设置加载平台环境配置脚本 | >= 2.0.1 |
+| [on_check](#platformon_check) | 设置平台工具的检测脚本 | >= 2.0.1 |
+| [on_install](#platformon_install) | 设置平台相关的工程目标安装脚本 | >= 2.0.5 |
+| [on_uninstall](#platformon_uninstall) | 设置平台相关的工程目标卸载脚本 | >= 2.0.5 |
+
+##### platform
+
+###### 定义平台
+
+自定义一个平台域,例如:
+
+```lua
+platform("iphoneos")
+
+ -- 设置操作系统
+ set_os("ios")
+
+ -- 设置主机环境
+ set_hosts("macosx")
+
+ -- 设置支持的架构
+ set_archs("armv7", "armv7s", "arm64", "i386", "x86_64")
+
+ -- 设置gcc, clang等平台相关工具的搜索目录
+ set_tooldirs("/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin")
+
+ -- 设置gcc,clang等工具的检测脚本文件
+ on_check("check")
+
+ -- 设置平台初始化加载脚本文件,如果实现不复杂的话,可以使用内嵌函数
+ on_load("load")
+
+ -- 设置平台的帮助菜单
+ set_menu {
+ config =
+ {
+ {}
+ , {nil, "xcode_dir", "kv", "auto", "the xcode application directory" }
+ , {nil, "xcode_sdkver", "kv", "auto", "the sdk version for xcode" }
+ , {nil, "target_minver", "kv", "auto", "the target minimal version" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ }
+
+ , global =
+ {
+ {}
+ , {nil, "xcode_dir", "kv", "auto", "the xcode application directory" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ }
+ }
+
+```
+
+<p class="warning">
+是在`platforms`目录相关平台的`xmake.lua`中编写,而不是在工程目录的`xmake.lua`中。
+</p>
+
+##### platform_end
+
+###### 结束定义平台
+
+这是一个可选api,显示离开选项作用域,用法和[target_end](#target_end)类似。
+
+##### set_os
+
+###### 设置平台系统
+
+设置目标平台的操作系统,例如:`ios`, `android`, `linux`, `windows` 等
+
+```lua
+platform("iphoneos")
+ set_os("ios")
+```
+
+这个一般用于在自定义脚本和插件开发中,[core.platform.platform](#core-platform-platform)模块中进行访问,获取当前平台的操作系统。
+
+##### set_menu
+
+###### 设置平台菜单
+
+先给个设置的例子:
+
+```lua
+platform("iphoneos")
+ ...
+
+ -- 设置平台的帮助菜单
+ set_menu {
+ config =
+ {
+ {}
+ , {nil, "xcode_dir", "kv", "auto", "the xcode application directory" }
+ , {nil, "xcode_sdkver", "kv", "auto", "the sdk version for xcode" }
+ , {nil, "target_minver", "kv", "auto", "the target minimal version" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ }
+
+ , global =
+ {
+ {}
+ , {nil, "xcode_dir", "kv", "auto", "the xcode application directory" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ }
+ }
+```
+
+其中`config`组用来设置:`xmake f --help`中的本地工程菜单,`global`用来设置:`xmake g --help`全局平台配置中的菜单。
+
+具体设置格式可参考:[task:set_menu](#taskset_menu)。
+
+##### set_hosts
+
+###### 设置平台支持的主机环境
+
+用来设置当前目标平台支持主机构建环境,例如`iphoneos`平台可以在`macosx`主机系统上构建,那么可以设置为:
+
+```lua
+platform("iphoneos")
+ set_hosts("macosx")
+```
+
+而`android`平台可以同时在`linux`, "macosx", `windows`主机环境中构建,那么可以设置为:
+
+```lua
+platform("android")
+ set_hosts("linux", "macosx", "windows")
+```
+
+##### set_archs
+
+###### 设置平台支持的架构环境
+
+用来设置当前目标平台支持的编译架构环境,例如`iphoneos`平台可以构建`armv7`, `armv7s`, `arm64`, `i386`, `x86_64`等架构,那么可以设置为:
+
+```lua
+platform("iphoneos")
+ set_archs("armv7", "armv7s", "arm64", "i386", "x86_64")
+```
+
+配置好架构后,执行:`xmake f -h`,就会在对应arch参数描述,自动显示设置的架构列表:
+
+```
+ -a ARCH, --arch=ARCH Compile for the given architecture. (default: auto)
+ - android: armv5te armv6 armv7-a armv8-a arm64-v8a
+ - iphoneos: armv7 armv7s arm64 i386 x86_64
+ - linux: i386 x86_64
+ - macosx: i386 x86_64
+ - mingw: i386 x86_64
+ - watchos: armv7k i386
+ - windows: x86 x64 amd64 x86_amd64
+```
+
+##### set_tooldirs
+
+###### 设置平台工具的搜索目录
+
+xmake会自动检测当前平台支持的一些构建工具是否存在,例如编译器、链接器等,如果要提高检测通过率,可以在平台配置的时候,设置一些工具环境搜索目录,例如:
+
+```lua
+platform("linux")
+
+ -- 在linux下检测这些目录环境
+ set_tooldirs("/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin")
+```
+
+##### on_load
+
+###### 设置加载平台环境配置脚本
+
+一般用于在平台刚加载时,设置一些基本配置:生成目标文件命名格式、平台相关编译选项等
+
+```lua
+platform("windows")
+
+ -- on load
+ on_load(function ()
+
+ -- init the file formats
+ _g.formats = {}
+ _g.formats.static = {"", ".lib"}
+ _g.formats.object = {"", ".obj"}
+ _g.formats.shared = {"", ".dll"}
+ _g.formats.binary = {"", ".exe"}
+ _g.formats.symbol = {"", ".pdb"}
+
+ -- init flags for dlang
+ local dc_archs = { x86 = "-m32", x64 = "-m64", amd64 = "-m64", x86_amd64 = "-m64" }
+ _g.dcflags = { dc_archs[arch] or "" }
+ _g["dc-shflags"] = { dc_archs[arch] or "" }
+ _g["dc-ldflags"] = { dc_archs[arch] or "" }
+
+ -- ok
+ return _g
+ end)
+```
+
+如果加载逻辑比较复杂,可以独立成单独`init.lua`文件,然后设置为:
+
+```lua
+platform("xxxx")
+ on_load("init")
+```
+
+通过这种方式,会自动加载平台脚本目录下对应的`init.lua`文件,调用`function main() end`函数入口,完成复杂加载逻辑。
+
+##### on_check
+
+###### 设置平台工具的检测脚本
+
+由于每个平台检测的工具非常多,脚本比较复杂,一般直接独立成`check.lua`文件来实现检测逻辑,例如:
+
+```lua
+platform("xxx")
+ on_check("check")
+```
+
+具体的检测代码入口如下:
+
+```lua
+-- check it
+function main(kind)
+
+ -- init the check list of config
+ _g.config =
+ {
+ __check_arch
+ , checker.check_ccache
+ , _check_toolchains
+ }
+
+ -- init the check list of global
+ _g.global =
+ {
+ checker.check_ccache
+ , _check_ndk_sdkver
+ }
+
+ -- check it
+ checker.check(kind, _g)
+end
+```
+
+具体实现这里就不介绍了,可以参考xmake源码目录下的`platforms`平台配置代码: [check.lua](https://github.com/tboox/xmake/blob/master/xmake/platforms/macosx/check.lua)
+
+##### on_install
+
+###### 设置目标工程在指定平台的安装脚本
+
+具体实现逻辑见xmake源码:[install.lua](https://github.com/tboox/xmake/blob/master/xmake/platforms/macosx/install.lua)
+
+##### on_uninstall
+
+###### 设置目标工程在指定平台的卸载脚本
+
+具体实现逻辑见xmake源码:[uninstall.lua](https://github.com/tboox/xmake/blob/master/xmake/platforms/macosx/uninstall.lua)
+
+#### Extension Languages
+
+有待后续完善。。
+
+#### Project Templates
+
+##### template
+##### set_description
+##### set_projectdir
+##### add_macros
+##### add_macrofiles
+
+#### Builtin Variables
+
+xmake提供了 `$(varname)` 的语法,来支持内置变量的获取,例如:
+
+```lua
+add_cxflags("-I$(buildir)")
+```
+
+它将会在在实际编译的时候,将内置的 `buildir` 变量转换为实际的构建输出目录:`-I./build`
+
+一般内置变量可用于在传参时快速获取和拼接变量字符串,例如:
+
+```lua
+target("test")
+
+ -- 添加工程源码目录下的源文件
+ add_files("$(projectdir)/src/*.c")
+
+ -- 添加构建目录下的头文件搜索路径
+ add_includedirs("$(buildir)/inc")
+```
+
+也可以在自定义脚本的模块接口中使用,例如:
+
+```lua
+target("test")
+ on_run(function (target)
+ -- 复制当前脚本目录下的头文件到输出目录
+ os.cp("$(scriptdir)/xxx.h", "$(buildir)/inc")
+ end)
+```
+
+所有的内置变量,也可以通过[val](#val)接口,来获取他们的值。
+
+这种使用内置变量的方式,使得描述编写更加的简洁易读,下面是一些xmake内置的变量,可以直接获取:
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [$(os)](#var-os) | 获取当前编译平台的操作系统 | >= 2.0.1 |
+| [$(host)](#var-host) | 获取本机操作系统 | >= 2.0.1 |
+| [$(tmpdir)](#var-tmpdir) | 获取临时目录 | >= 2.0.1 |
+| [$(curdir)](#var-curdir) | 获取当前目录 | >= 2.0.1 |
+| [$(buildir)](#var-buildir) | 获取构建输出目录 | >= 2.0.1 |
+| [$(scriptdir)](#var-scriptdir) | 获取工程描述脚本目录 | >= 2.1.1 |
+| [$(globaldir)](#var-globaldir) | 获取全局配置目录 | >= 2.0.1 |
+| [$(configdir)](#var-configdir) | 获取本地工程配置目录 | >= 2.0.1 |
+| [$(programdir)](#var-programdir) | xmake安装脚本目录 | >= 2.1.5 |
+| [$(projectdir)](#var-projectdir) | 获取工程根目录 | >= 2.0.1 |
+| [$(shell)](#var-shell) | 执行外部shell命令 | >= 2.0.1 |
+| [$(env)](#var-env) | 获取外部环境变量 | >= 2.1.5 |
+| [$(reg)](#var-reg) | 获取windows注册表配置项的值 | >= 2.1.5 |
+
+当然这种变量模式,也是可以扩展的,默认通过`xmake f --var=val`命令,配置的参数都是可以直接获取,例如:
+
+```lua
+target("test")
+ add_defines("-DTEST=$(var)")
+```
+
+<p class="tip">
+所有`xmake f --xxx=...`配置的参数值,都是可以通过内置变量获取到,例如:`xmake f --arch=x86`对应`$(arch)`,其他的还有`$(plat)`, `$(mode)`等等。
+具体有哪些参数,可以通过:`xmake f -h`才查看。
+</p>
+
+既然支持直接从配置选项中获取,那么当然也就能很方便的扩展自定义的选项,来获取自定义的变量了,具体如何自定义选项见:[option](#option)
+
+##### var.$(os)
+
+###### 获取当前编译平台的操作系统
+
+如果当前编译的是iphoneos,那么这个值就是:`ios`,以此类推。
+
+##### var.$(host)
+
+###### 获取本机操作系统
+
+指的是当前本机环境的主机系统,如果你是在macOS上编译,那么系统就是:`macosx`
+
+##### var.$(tmpdir)
+
+###### 获取临时目录
+
+一般用于临时存放一些非永久性文件。
+
+##### var.$(curdir)
+
+###### 获取当前目录
+
+一般默认是执行`xmake`命令时的工程根目录,当然如果通过[os.cd](#os-cd)改变了目录的话,这个值也会一起改变。
+
+##### var.$(buildir)
+
+###### 获取当前的构建输出目录
+
+默认一般为当前工程根目录下的:`./build`目录,也可以通过执行:`xmake f -o /tmp/build`命令来修改默认的输出目录。
+
+##### var.$(scriptdir)
+
+###### 获取当前工程描述脚本的目录
+
+也就是对应`xmake.lua`所在的目录路径。
+
+##### var.$(globaldir)
+
+###### 全局配置目录
+
+xmake的`xmake g|global`全局配置命令,数据存储的目录路径,在里面可以放置一些自己的插件、平台脚本。
+
+默认为:`~/.config`
+
+##### var.$(configdir)
+
+###### 当前工程配置目录
+
+当前工程的配置存储目录,也就是`xmake f|config`配置命令的存储目录,默认为:`projectdir/.config`
+
+##### var.$(programdir)
+
+###### xmake安装脚本目录
+
+也就是`XMAKE_PROGRAM_DIR`环境变量所在目录,我们也可以通过设置这个环境量,来修改xmake的加载脚本,实现版本切换。
+
+##### var.$(projectdir)
+
+###### 工程根目录
+
+也就是`xmake -P xxx`命令中指定的目录路径,默认不指定就是`xmake`命令执行时的当前目录,一般用于定位工程文件。
+
+##### var.$(shell)
+
+###### 执行外部shell命令
+
+除了内置的变量处理,xmake还支持原生shell的运行,来处理一些xmake内置不支持的功能
+
+例如,现在有个需求,我想用在编译linux程序时,调用`pkg-config`获取到实际的第三方链接库名,可以这么做:
+
+```lua
+target("test")
+ set_kind("binary")
+ if is_plat("linux") then
+ add_ldflags("$(shell pkg-config --libs sqlite3)")
+ end
+```
+
+当然,xmake有自己的自动化第三库检测机制,一般情况下不需要这么麻烦,而且lua自身的脚本化已经很不错了。。
+
+但是这个例子可以说明,xmake是完全可以通过原生shell,来与一些第三方的工具进行配合使用。。
+
+##### var.$(env)
+
+###### 获取外部环境变量
+
+例如,可以通过获取环境变量中的路径:
+
+```lua
+target("test")
+ add_includedirs("$(env PROGRAMFILES)/OpenSSL/inc")
+```
+
+##### var.$(reg)
+
+###### 获取windows注册表配置项的值
+
+通过 `regpath; name` 的方式获取注册表中某个项的值:
+
+```lua
+print("$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name)")
+```
+
+#### Builtin Modules
+
+在自定义脚本、插件脚本、任务脚本、平台扩展、模板扩展等脚本代码中使用,也就是在类似下面的代码块中,可以使用这些模块接口:
+
+```lua
+on_run(function (target)
+ print("hello xmake!")
+end)
+```
+
+<p class="warning">
+为了保证外层的描述域尽可能简洁、安全,一般不建议在这个域使用接口和模块操作api,因此大部分模块接口只能再脚本域使用,来实现复杂功能。</br>
+当然少部分只读的内置接口还是可以在描述域使用的,具体见下表:
+</p>
+
+| 接口 | 描述 | 可使用域 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------------------------- | -------- |
+| [val](#val) | 获取内置变量的值 | 脚本域 | >= 2.1.5 |
+| [import](#import) | 导入扩展摸块 | 脚本域 | >= 2.0.1 |
+| [inherit](#inherit) | 导入并继承基类模块 | 脚本域 | >= 2.0.1 |
+| [ifelse](#ifelse) | 类似三元条件判断 | 描述域、脚本域 | >= 2.0.1 |
+| [try-catch-finally](#try-catch-finally) | 异常捕获 | 脚本域 | >= 2.0.1 |
+| [pairs](#pairs) | 用于遍历字典 | 描述域、脚本域 | >= 2.0.1 |
+| [ipairs](#ipairs) | 用于遍历数组 | 描述域、脚本域 | >= 2.0.1 |
+| [print](#print) | 换行打印终端日志 | 描述域、脚本域 | >= 2.0.1 |
+| [printf](#printf) | 无换行打印终端日志 | 脚本域 | >= 2.0.1 |
+| [cprint](#cprint) | 换行彩色打印终端日志 | 脚本域 | >= 2.0.1 |
+| [cprintf](#cprintf) | 无换行彩色打印终端日志 | 脚本域 | >= 2.0.1 |
+| [format](#format) | 格式化字符串 | 描述域、脚本域 | >= 2.0.1 |
+| [vformat](#vformat) | 格式化字符串,支持内置变量转义 | 脚本域 | >= 2.0.1 |
+| [raise](#raise) | 抛出异常中断程序 | 脚本域 | >= 2.0.1 |
+| [os](#os) | 系统操作模块 | 部分只读操作描述域、脚本域 | >= 2.0.1 |
+| [io](#io) | 文件操作模块 | 脚本域 | >= 2.0.1 |
+| [path](#path) | 路径操作模块 | 描述域、脚本域 | >= 2.0.1 |
+| [table](#table) | 数组和字典操作模块 | 描述域、脚本域 | >= 2.0.1 |
+| [string](#string) | 字符串操作模块 | 描述域、脚本域 | >= 2.0.1 |
+| [process](#process) | 进程操作模块 | 脚本域 | >= 2.0.1 |
+| [coroutine](#coroutine) | 协程操作模块 | 脚本域 | >= 2.0.1 |
+
+在描述域使用接口调用的实例如下,一般仅用于条件控制:
+
+```lua
+-- 扫描当前xmake.lua目录下的所有子目录,以每个目录的名字定义一个task任务
+for _, taskname in ipairs(os.dirs("*"), path.basename) do
+ task(taskname)
+ on_run(function ()
+ end)
+end
+```
+
+上面所说的脚本域、描述域主要是指:
+
+```lua
+-- 描述域
+target("test")
+
+ -- 描述域
+ set_kind("static")
+ add_files("src/*.c")
+
+ on_run(function (target)
+ -- 脚本域
+ end)
+
+-- 描述域
+```
+
+##### val
+
+###### 获取内置变量的值
+
+[内置变量](#内置变量)可以通过此接口直接获取,而不需要再加`$()`的包裹,使用更加简单,例如:
+
+```lua
+print(val("host"))
+print(val("env PATH"))
+local s = val("shell echo hello")
+```
+
+而用[vformat](#vformat)就比较繁琐了:
+
+```lua
+local s = vformat("$(shell echo hello)")
+```
+
+不过`vformat`支持字符串参数格式化,更加强大, 所以应用场景不同。
+
+##### import
+
+###### 导入扩展摸块
+
+import的主要用于导入xmake的扩展类库以及一些自定义的类库模块,一般用于:
+
+* 自定义脚本([on_build](#targeton_build), [on_run](#targeton_run) ..)
+* 插件开发
+* 模板开发
+* 平台扩展
+* 自定义任务task
+
+导入机制如下:
+
+1. 优先从当前脚本目录下导入
+2. 再从扩展类库中导入
+
+导入的语法规则:
+
+基于`.`的类库路径规则,例如:
+
+导入core核心扩展模块
+
+```lua
+import("core.base.option")
+import("core.project")
+import("core.base.task") -- 2.1.5 以前是 core.project.task
+import("core")
+
+function main()
+
+ -- 获取参数选项
+ print(option.get("version"))
+
+ -- 运行任务和插件
+ task.run("hello")
+ project.task.run("hello")
+ core.base.task.run("hello")
+end
+```
+
+导入当前目录下的自定义模块:
+
+目录结构:
+
+```
+plugin
+ - xmake.lua
+ - main.lua
+ - modules
+ - hello1.lua
+ - hello2.lua
+```
+
+在main.lua中导入modules
+
+```lua
+import("modules.hello1")
+import("modules.hello2")
+```
+
+导入后就可以直接使用里面的所有公有接口,私有接口用`_`前缀标示,表明不会被导出,不会被外部调用到。。
+
+除了当前目录,我们还可以导入其他指定目录里面的类库,例如:
+
+```lua
+import("hello3", {rootdir = "/home/xxx/modules"})
+```
+
+为了防止命名冲突,导入后还可以指定的别名:
+
+```lua
+import("core.platform.platform", {alias = "p"})
+
+function main()
+
+ -- 这样我们就可以使用p来调用platform模块的plats接口,获取所有xmake支持的平台列表了
+ table.dump(p.plats())
+end
+```
+
+import不仅可以导入类库,还支持导入的同时作为继承导入,实现模块间的继承关系
+
+```lua
+import("xxx.xxx", {inherit = true})
+```
+
+这样导入的不是这个模块的引用,而是导入的这个模块的所有公有接口本身,这样就会跟当前模块的接口进行合并,实现模块间的继承。
+
+2.1.5版本新增两个新属性:`import("xxx.xxx", {try = true, anonymous = true})`
+
+try为true,则导入的模块不存在的话,仅仅返回nil,并不会抛异常后中断xmake.
+anonymous为true,则导入的模块不会引入当前作用域,仅仅在import接口返回导入的对象引用。
+
+##### inherit
+
+###### 导入并继承基类模块
+
+这个等价于[import](#import)接口的`inherit`模式,也就是:
+
+```lua
+import("xxx.xxx", {inherit = true})
+```
+
+用`inherit`接口的话,会更简洁些:
+
+```lu
+inherit("xxx.xxx")
+```
+
+使用实例,可以参看xmake的tools目录下的脚本:[clang.lua](#https://github.com/tboox/xmake/blob/master/xmake/tools/clang.lua)
+
+这个就是clang工具模块继承了gcc的部分实现。
+
+##### ifelse
+
+###### 类似三元条件判断
+
+由于lua没有内置的三元运算符,通过封装`ifelse`接口,实现更加简洁的条件选择:
+
+```lua
+local ok = ifelse(a == 0, "ok", "no")
+```
+
+##### try-catch-finally
+
+###### 异常捕获
+
+lua原生并没有提供try-catch的语法来捕获异常处理,但是提供了`pcall/xpcall`等接口,可在保护模式下执行lua函数。
+
+因此,可以通过封装这两个接口,来实现try-catch块的捕获机制。
+
+我们可以先来看下,封装后的try-catch使用方式:
+
+```lua
+try
+{
+ -- try 代码块
+ function ()
+ error("error message")
+ end,
+
+ -- catch 代码块
+ catch
+ {
+ -- 发生异常后,被执行
+ function (errors)
+ print(errors)
+ end
+ }
+}
+```
+
+上面的代码中,在try块内部认为引发了一个异常,并且抛出错误消息,在catch中进行了捕获,并且将错误消息进行输出显示。
+
+而finally的处理,这个的作用是对于`try{}`代码块,不管是否执行成功,都会执行到finally块中
+
+也就说,其实上面的实现,完整的支持语法是:`try-catch-finally`模式,其中catch和finally都是可选的,根据自己的实际需求提供
+
+例如:
+
+```lua
+try
+{
+ -- try 代码块
+ function ()
+ error("error message")
+ end,
+
+ -- catch 代码块
+ catch
+ {
+ -- 发生异常后,被执行
+ function (errors)
+ print(errors)
+ end
+ },
+
+ -- finally 代码块
+ finally
+ {
+ -- 最后都会执行到这里
+ function (ok, errors)
+ -- 如果try{}中存在异常,ok为true,errors为错误信息,否则为false,errors为try中的返回值
+ end
+ }
+}
+
+```
+
+或者只有finally块:
+
+```lua
+try
+{
+ -- try 代码块
+ function ()
+ return "info"
+ end,
+
+ -- finally 代码块
+ finally
+ {
+ -- 由于此try代码没发生异常,因此ok为true,errors为返回值: "info"
+ function (ok, errors)
+ end
+ }
+}
+```
+
+处理可以在finally中获取try里面的正常返回值,其实在仅有try的情况下,也是可以获取返回值的:
+
+```lua
+-- 如果没发生异常,result 为返回值:"xxxx",否则为nil
+local result = try
+{
+ function ()
+ return "xxxx"
+ end
+}
+```
+
+在xmake的自定义脚本、插件开发中,也是完全基于此异常捕获机制
+
+这样使得扩展脚本的开发非常的精简可读,省去了繁琐的`if err ~= nil then`返回值判断,在发生错误时,xmake会直接抛出异常进行中断,然后高亮提示详细的错误信息。
+
+例如:
+
+```lua
+target("test")
+ set_kind("binary")
+ add_files("src/*.c")
+
+ -- 在编译完ios程序后,对目标程序进行ldid签名
+ after_build(function (target))
+ os.run("ldid -S %s", target:targetfile())
+ end
+```
+
+只需要一行`os.run`就行了,也不需要返回值判断是否运行成功,因为运行失败后,xmake会自动抛异常,中断程序并且提示错误
+
+如果你想在运行失败后,不直接中断xmake,继续往下运行,可以自己加个try快就行了:
+
+```lua
+target("test")
+ set_kind("binary")
+ add_files("src/*.c")
+
+ after_build(function (target))
+ try
+ {
+ function ()
+ os.run("ldid -S %s", target:targetfile())
+ end
+ }
+ end
+```
+
+如果还想捕获出错信息,可以再加个catch:
+
+```lua
+target("test")
+ set_kind("binary")
+ add_files("src/*.c")
+
+ after_build(function (target))
+ try
+ {
+ function ()
+ os.run("ldid -S %s", target:targetfile())
+ end,
+ catch
+ {
+ function (errors)
+ print(errors)
+ end
+ }
+ }
+ end
+```
+
+不过一般情况下,在xmake中写自定义脚本,是不需要手动加try-catch的,直接调用各种api,出错后让xmake默认的处理程序接管,直接中断就行了。。
+
+##### pairs
+
+###### 用于遍历字典
+
+这个是lua原生的内置api,在xmake中,在原有的行为上对其进行了一些扩展,来简化一些日常的lua遍历代码。
+
+先看下默认的原生写法:
+
+```lua
+local t = {a = "a", b = "b", c = "c", d = "d", e = "e", f = "f"}
+
+for key, val in pairs(t) do
+ print("%s: %s", key, val)
+end
+```
+
+这对于通常的遍历操作就足够了,但是如果我们相对其中每个遍历出来的元素,获取其大写,我们可以这么写:
+
+```lua
+for key, val in pairs(t, function (v) return v:upper() end) do
+ print("%s: %s", key, val)
+end
+```
+
+甚至传入一些参数到第二个`function`中,例如:
+
+```lua
+for key, val in pairs(t, function (v, a, b) return v:upper() .. a .. b end, "a", "b") do
+ print("%s: %s", key, val)
+end
+```
+
+##### ipairs
+
+###### 用于遍历数组
+
+这个是lua原生的内置api,在xmake中,在原有的行为上对其进行了一些扩展,来简化一些日常的lua遍历代码。
+
+先看下默认的原生写法:
+
+```lua
+for idx, val in ipairs({"a", "b", "c", "d", "e", "f"}) do
+ print("%d %s", idx, val)
+end
+```
+
+扩展写法类似[pairs](#pairs)接口,例如:
+
+```lua
+for idx, val in ipairs({"a", "b", "c", "d", "e", "f"}, function (v) return v:upper() end) do
+ print("%d %s", idx, val)
+end
+
+for idx, val in ipairs({"a", "b", "c", "d", "e", "f"}, function (v, a, b) return v:upper() .. a .. b end, "a", "b") do
+ print("%d %s", idx, val)
+end
+```
+
+这样可以简化`for`块代码的逻辑,例如我要遍历指定目录,获取其中的文件名,但不包括路径,就可以通过这种扩展方式,简化写法:
+
+```lua
+for _, filename in ipairs(os.dirs("*"), path.filename) do
+ -- ...
+end
+```
+
+##### print
+
+###### 换行打印终端日志
+
+此接口也是lua的原生接口,xmake在原有行为不变的基础上也进行了扩展,同时支持:格式化输出、多变量输出。
+
+先看下原生支持的方式:
+
+```lua
+print("hello xmake!")
+print("hello", "xmake!", 123)
+```
+
+并且同时还支持扩展的格式化写法:
+
+```lua
+print("hello %s!", "xmake")
+print("hello xmake! %d", 123)
+```
+
+xmake会同时支持这两种写法,内部会去自动智能检测,选择输出行为。
+
+##### printf
+
+###### 无换行打印终端日志
+
+类似[print](#print)接口,唯一的区别就是不换行。
+
+##### cprint
+
+###### 换行彩色打印终端日志
+
+行为类似[print](#print),区别就是此接口还支持彩色终端输出,并且支持`emoji`字符输出。
+
+例如:
+
+```lua
+ cprint('${bright}hello xmake')
+ cprint('${red}hello xmake')
+ cprint('${bright green}hello ${clear}xmake')
+ cprint('${blue onyellow underline}hello xmake${clear}')
+ cprint('${red}hello ${magenta}xmake')
+ cprint('${cyan}hello ${dim yellow}xmake')
+```
+
+显示结果如下:
+
+![cprint_colors](http://tboox.org/static/img/xmake/cprint_colors.png)
+
+跟颜色相关的描述,都放置在 `${ }` 里面,可以同时设置多个不同的属性,例如:
+
+```
+ ${bright red underline onyellow}
+```
+
+表示:高亮红色,背景黄色,并且带下滑线
+
+所有这些描述,都会影响后面一整行字符,如果只想显示部分颜色的文字,可以在结束位置,插入`${clear}`清楚前面颜色描述
+
+例如:
+
+```
+ ${red}hello ${clear}xmake
+```
+
+这样的话,仅仅hello是显示红色,其他还是正常默认黑色显示。
+
+其他颜色属于,我这里就不一一介绍,直接贴上xmake代码里面的属性列表吧:
+
+```lua
+ colors.keys =
+ {
+ -- 属性
+ reset = 0 -- 重置属性
+ , clear = 0 -- 清楚属性
+ , default = 0 -- 默认属性
+ , bright = 1 -- 高亮
+ , dim = 2 -- 暗色
+ , underline = 4 -- 下划线
+ , blink = 5 -- 闪烁
+ , reverse = 7 -- 反转颜色
+ , hidden = 8 -- 隐藏文字
+
+ -- 前景色
+ , black = 30
+ , red = 31
+ , green = 32
+ , yellow = 33
+ , blue = 34
+ , magenta = 35
+ , cyan = 36
+ , white = 37
+
+ -- 背景色
+ , onblack = 40
+ , onred = 41
+ , ongreen = 42
+ , onyellow = 43
+ , onblue = 44
+ , onmagenta = 45
+ , oncyan = 46
+ , onwhite = 47
+```
+
+除了可以色彩高亮显示外,如果你的终端是在macosx下,lion以上的系统,xmake还可以支持emoji表情的显示哦,对于不支持系统,会
+忽略显示,例如:
+
+```lua
+ cprint("hello xmake${beer}")
+ cprint("hello${ok_hand} xmake")
+```
+
+上面两行代码,我打印了一个homebrew里面经典的啤酒符号,下面那行打印了一个ok的手势符号,是不是很炫哈。。
+
+![cprint_emoji](http://tboox.org/static/img/xmake/cprint_emoji.png)
+
+所有的emoji表情,以及xmake里面对应的key,都可以通过[emoji符号](http://www.emoji-cheat-sheet.com/)里面找到。。
+
+2.1.7版本支持24位真彩色输出,如果终端支持的话:
+
+```lua
+import("core.base.colors")
+if colors.truecolor() then
+ cprint("${255;0;0}hello")
+ cprint("${on;255;0;0}hello${clear} xmake")
+ cprint("${bright 255;0;0 underline}hello")
+ cprint("${bright on;255;0;0 0;255;0}hello${clear} xmake")
+end
+```
+
+xmake对于truecolor的检测支持,是通过`$COLORTERM`环境变量来实现的,如果你的终端支持truecolor,可以手动设置此环境变量,来告诉xmake启用truecolor支持。
+
+可以通过下面的命令来启用和测试:
+
+```bash
+$ export COLORTERM=truecolor
+$ xmake --version
+```
+
+##### cprintf
+
+###### 无换行彩色打印终端日志
+
+此接口类似[cprint](#cprint),区别就是不换行输出。
+
+##### format
+
+###### 格式化字符串
+
+如果只是想格式化字符串,不进行输出,可以使用这个接口,此接口跟[string.format](#string-format)接口等价,只是个接口名简化版。
+
+```lua
+local s = format("hello %s", xmake)
+```
+
+##### vformat
+
+###### 格式化字符串,支持内置变量转义
+
+此接口跟[format](#format)接口类似,只是增加对内置变量的获取和转义支持。
+
+```lua
+local s = vformat("hello %s $(mode) $(arch) $(env PATH)", xmake)
+```
+
+##### raise
+
+###### 抛出异常中断程序
+
+如果想在自定义脚本、插件任务中中断xmake运行,可以使用这个接口跑出异常,如果上层没有显示调用[try-catch](#try-catch-finally)捕获的话,xmake就会中断执行,并且显示出错信息。
+
+```lua
+if (errors) raise(errors)
+```
+
+如果在try块中抛出异常,就会在catch和finally中进行errors信息捕获,具体见:[try-catch](#try-catch-finally)
+
+##### os
+
+系统操作模块,属于内置模块,无需使用[import](#import)导入,可直接脚本域调用其接口。
+
+此模块也是lua的原生模块,xmake在其基础上进行了扩展,提供更多实用的接口。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [os.cp](#os-cp) | 复制文件或目录 | >= 2.0.1 |
+| [os.mv](#os-mv) | 移动重命名文件或目录 | >= 2.0.1 |
+| [os.rm](#os-rm) | 删除文件或目录树 | >= 2.0.1 |
+| [os.cd](#os-cd) | 进入指定目录 | >= 2.0.1 |
+| [os.rmdir](#os-rmdir) | 删除目录树 | >= 2.0.1 |
+| [os.mkdir](#os-mkdir) | 创建指定目录 | >= 2.0.1 |
+| [os.isdir](#os-isdir) | 判断目录是否存在 | >= 2.0.1 |
+| [os.isfile](#os-isfile) | 判断文件是否存在 | >= 2.0.1 |
+| [os.exists](#os-exists) | 判断文件或目录是否存在 | >= 2.0.1 |
+| [os.dirs](#os-dirs) | 遍历获取指定目录下的所有目录 | >= 2.0.1 |
+| [os.files](#os-files) | 遍历获取指定目录下的所有文件 | >= 2.0.1 |
+| [os.filedirs](#os-filedirs) | 遍历获取指定目录下的所有文件或目录 | >= 2.0.1 |
+| [os.run](#os-run) | 安静运行程序 | >= 2.0.1 |
+| [os.runv](#os-runv) | 安静运行程序,带参数列表 | >= 2.1.5 |
+| [os.exec](#os-exec) | 回显运行程序 | >= 2.0.1 |
+| [os.execv](#os-execv) | 回显运行程序,带参数列表 | >= 2.1.5 |
+| [os.iorun](#os-iorun) | 运行并获取程序输出内容 | >= 2.0.1 |
+| [os.iorunv](#os-iorunv) | 运行并获取程序输出内容,带参数列表 | >= 2.1.5 |
+| [os.getenv](#os-getenv) | 获取环境变量 | >= 2.0.1 |
+| [os.setenv](#os-setenv) | 设置环境变量 | >= 2.0.1 |
+| [os.tmpdir](#os-tmpdir) | 获取临时目录路径 | >= 2.0.1 |
+| [os.tmpfile](#os-tmpfile) | 获取临时文件路径 | >= 2.0.1 |
+| [os.curdir](#os-curdir) | 获取当前目录路径 | >= 2.0.1 |
+| [os.scriptdir](#os-scriptdir) | 获取脚本目录路径 | >= 2.0.1 |
+| [os.programdir](#os-programdir) | 获取xmake安装主程序脚本目录 | >= 2.1.5 |
+| [os.projectdir](#os-projectdir) | 获取工程主目录 | >= 2.1.5 |
+| [os.arch](#os-arch) | 获取当前系统架构 | >= 2.0.1 |
+| [os.host](#os-host) | 获取当前主机系统 | >= 2.0.1 |
+
+###### os.cp
+
+- 复制文件或目录
+
+行为和shell中的`cp`命令类似,支持路径通配符匹配(使用的是lua模式匹配),支持多文件复制,以及内置变量支持。
+
+例如:
+
+```lua
+os.cp("$(scriptdir)/*.h", "$(projectdir)/src/test/**.h", "$(buildir)/inc")
+```
+
+上面的代码将:当前`xmake.lua`目录下的所有头文件、工程源码test目录下的头文件全部复制到`$(buildir)`输出目录中。
+
+其中`$(scriptdir)`, `$(projectdir)` 这些变量是xmake的内置变量,具体详情见:[内置变量](#内置变量)的相关文档。
+
+而`*.h`和`**.h`中的匹配模式,跟[add_files](#targetadd_files)中的类似,前者是单级目录匹配,后者是递归多级目录匹配。
+
+此接口同时支持目录的`递归复制`,例如:
+
+```lua
+-- 递归复制当前目录到临时目录
+os.cp("$(curdir)/test/", "$(tmpdir)/test")
+```
+
+<p class="tip">
+尽量使用`os.cp`接口,而不是`os.run("cp ..")`,这样更能保证平台一致性,实现跨平台构建描述。
+</p>
+
+###### os.mv
+
+- 移动重命名文件或目录
+
+跟[os.cp](#os-cp)的使用类似,同样支持多文件移动操作和模式匹配,例如:
+
+```lua
+-- 移动多个文件到临时目录
+os.mv("$(buildir)/test1", "$(buildir)/test2", "$(tmpdir)")
+
+-- 文件移动不支持批量操作,也就是文件重命名
+os.mv("$(buildir)/libtest.a", "$(buildir)/libdemo.a")
+```
+
+###### os.rm
+
+- 删除文件或目录树
+
+支持递归删除目录,批量删除操作,以及模式匹配和内置变量,例如:
+
+```lua
+os.rm("$(buildir)/inc/**.h", "$(buildir)/lib/")
+```
+
+###### os.cd
+
+- 进入指定目录
+
+这个操作用于目录切换,同样也支持内置变量,但是不支持模式匹配和多目录处理,例如:
+
+```lua
+-- 进入临时目录
+os.cd("$(tmpdir)")
+```
+
+如果要离开进入之前的目录,有多种方式:
+
+```lua
+-- 进入上级目录
+os.cd("..")
+
+-- 进入先前的目录,相当于:cd -
+os.cd("-")
+
+-- 进入目录前保存之前的目录,用于之后跨级直接切回
+local oldir = os.cd("./src")
+...
+os.cd(oldir)
+```
+
+###### os.rmdir
+
+- 仅删除目录
+
+如果不是目录就无法删除。
+
+###### os.mkdir
+
+- 创建目录
+
+支持批量创建和内置变量,例如:
+
+```lua
+os.mkdir("$(tmpdir)/test", "$(buildir)/inc")
+```
+
+###### os.isdir
+
+- 判断是否为目录
+
+如果目录不存在,则返回false
+
+```lua
+if os.isdir("src") then
+ -- ...
+end
+```
+
+###### os.isfile
+
+- 判断是否为文件
+
+如果文件不存在,则返回false
+
+```lua
+if os.isfile("$(buildir)/libxxx.a") then
+ -- ...
+end
+```
+
+###### os.exists
+
+- 判断文件或目录是否存在
+
+如果文件或目录不存在,则返回false
+
+```lua
+-- 判断目录存在
+if os.exists("$(buildir)") then
+ -- ...
+end
+
+-- 判断文件存在
+if os.exists("$(buildir)/libxxx.a") then
+ -- ...
+end
+```
+
+###### os.dirs
+
+- 遍历获取指定目录下的所有目录
+
+支持[add_files](#targetadd_files)中的模式匹配,支持递归和非递归模式遍历,返回的结果是一个table数组,如果获取不到,返回空数组,例如:
+
+```lua
+-- 递归遍历获取所有子目录
+for _, dir in ipairs(os.dirs("$(buildir)/inc/**")) do
+ print(dir)
+end
+```
+
+###### os.files
+
+- 遍历获取指定目录下的所有文件
+
+支持[add_files](#targetadd_files)中的模式匹配,支持递归和非递归模式遍历,返回的结果是一个table数组,如果获取不到,返回空数组,例如:
+
+```lua
+-- 非递归遍历获取所有子文件
+for _, filepath in ipairs(os.files("$(buildir)/inc/*.h")) do
+ print(filepath)
+end
+```
+
+###### os.filedirs
+
+- 遍历获取指定目录下的所有文件和目录
+
+支持[add_files](#targetadd_files)中的模式匹配,支持递归和非递归模式遍历,返回的结果是一个table数组,如果获取不到,返回空数组,例如:
+
+```lua
+-- 递归遍历获取所有子文件和目录
+for _, filedir in ipairs(os.filedirs("$(buildir)/**")) do
+ print(filedir)
+end
+```
+
+###### os.run
+
+- 安静运行原生shell命令
+
+用于执行第三方的shell命令,但不会回显输出,仅仅在出错后,高亮输出错误信息。
+
+此接口支持参数格式化、内置变量,例如:
+
+```lua
+-- 格式化参数传入
+os.run("echo hello %s!", "xmake")
+
+-- 列举构建目录文件
+os.run("ls -l $(buildir)")
+```
+
+<p class="warning">
+使用此接口执行shell命令,容易使构建跨平台性降低,对于`os.run("cp ..")`这种尽量使用`os.cp`代替。<br>
+如果必须使用此接口运行shell程序,请自行使用[config.plat](#config-plat)接口判断平台支持。
+</p>
+
+更加高级的进程运行和控制,见[process](#process)模块接口。
+
+###### os.runv
+
+- 安静运行原生shell命令,带参数列表
+
+跟[os.run](#os-run)类似,只是传递参数的方式是通过参数列表传递,而不是字符串命令,例如:
+
+```lua
+os.runv("echo", {"hello", "xmake!"})
+```
+
+###### os.exec
+
+- 回显运行原生shell命令
+
+与[os.run](#os-run)接口类似,唯一的不同是,此接口执行shell程序时,是带回显输出的,一般调试的时候用的比较多
+
+###### os.execv
+
+- 回显运行原生shell命令,带参数列表
+
+跟[os.execv](#os-execv)类似,只是传递参数的方式是通过参数列表传递,而不是字符串命令,例如:
+
+```lua
+os.execv("echo", {"hello", "xmake!"})
+```
+
+###### os.iorun
+
+- 安静运行原生shell命令并获取输出内容
+
+与[os.run](#os-run)接口类似,唯一的不同是,此接口执行shell程序后,会获取shell程序的执行结果,相当于重定向输出。
+
+可同时获取`stdout`, `stderr`中的内容,例如:
+
+```lua
+local outdata, errdata = os.iorun("echo hello xmake!")
+```
+
+###### os.iorunv
+
+- 安静运行原生shell命令并获取输出内容,带参数列表
+
+跟[os.iorunv](#os-iorunv)类似,只是传递参数的方式是通过参数列表传递,而不是字符串命令,例如:
+
+```lua
+local result, errors = os.iorunv("echo", {"hello", "xmake!"})
+```
+
+###### os.getenv
+
+- 获取系统环境变量
+
+```lua
+print(os.getenv("PATH"))
+```
+
+###### os.setenv
+
+- 设置系统环境变量
+
+```lua
+os.setenv("HOME", "/tmp/")
+```
+
+###### os.tmpdir
+
+- 获取临时目录
+
+跟[$(tmpdir)](#var-tmpdir)结果一致,只不过是直接获取返回一个变量,可以用后续字符串维护。
+
+```lua
+print(path.join(os.tmpdir(), "file.txt"))
+```
+
+等价于:
+
+```lua
+print("$(tmpdir)/file.txt"))
+```
+
+###### os.tmpfile
+
+- 获取临时文件路径
+
+用于获取生成一个临时文件路径,仅仅是个路径,文件需要自己创建。
+
+###### os.curdir
+
+- 获取当前目录路径
+
+跟[$(curdir)](#var-curdir)结果一致,只不过是直接获取返回一个变量,可以用后续字符串维护。
+
+用法参考:[os.tmpdir](#os-tmpdir)。
+
+###### os.scriptdir
+
+- 获取当前描述脚本的路径
+
+跟[$(scriptdir)](#var-scriptdir)结果一致,只不过是直接获取返回一个变量,可以用后续字符串维护。
+
+用法参考:[os.tmpdir](#os-tmpdir)。
+
+###### os.programdir
+
+- 获取xmake安装主程序脚本目录
+
+跟[$(programdir)](#var-programdir)结果一致,只不过是直接获取返回一个变量,可以用后续字符串维护。
+
+###### os.projectdir
+
+- 获取工程主目录
+
+跟[$(projectdir)](#var-projectdir)结果一致,只不过是直接获取返回一个变量,可以用后续字符串维护。
+
+###### os.arch
+
+- 获取当前系统架构
+
+也就是当前主机系统的默认架构,例如我在`linux x86_64`上执行xmake进行构建,那么返回值是:`x86_64`
+
+###### os.host
+
+- 获取当前主机的操作系统
+
+跟[$(host)](#var-host)结果一致,例如我在`linux x86_64`上执行xmake进行构建,那么返回值是:`linux`
+
+##### io
+
+io操作模块,扩展了lua内置的io模块,提供更多易用的接口。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [io.open](#io-open) | 打开文件用于读写 | >= 2.0.1 |
+| [io.load](#io-load) | 从指定路径文件反序列化加载所有table内容 | >= 2.0.1 |
+| [io.save](#io-save) | 序列化保存所有table内容到指定路径文件 | >= 2.0.1 |
+| [io.readfile](#io.readfile) | 从指定路径文件读取所有内容 | >= 2.1.3 |
+| [io.writefile](#io.writefile) | 写入所有内容到指定路径文件 | >= 2.1.3 |
+| [io.gsub](#io-gsub) | 全文替换指定路径文件的内容 | >= 2.0.1 |
+| [io.tail](#io-tail) | 读取和显示文件的尾部内容 | >= 2.0.1 |
+| [io.cat](#io-cat) | 读取和显示文件的所有内容 | >= 2.0.1 |
+| [io.print](#io-print) | 带换行格式化输出内容到文件 | >= 2.0.1 |
+| [io.printf](#io-printf) | 无换行格式化输出内容到文件 | >= 2.0.1 |
+
+###### io.open
+
+- 打开文件用于读写
+
+这个是属于lua的原生接口,详细使用可以参看lua的官方文档:[The Complete I/O Model](https://www.lua.org/pil/21.2.html)
+
+如果要读取文件所有内容,可以这么写:
+
+```lua
+local file = io.open("$(tmpdir)/file.txt", "r")
+if file then
+ local data = file:read("*all")
+ file:close()
+end
+```
+
+或者可以使用[io.readfile](#io.readfile)更加快速地读取。
+
+如果要写文件,可以这么操作:
+
+```lua
+-- 打开文件:w 为写模式, a 为追加写模式
+local file = io.open("xxx.txt", "w")
+if file then
+
+ -- 用原生的lua接口写入数据到文件,不支持格式化,无换行,不支持内置变量
+ file:write("hello xmake\n")
+
+ -- 用xmake扩展的接口写入数据到文件,支持格式化,无换行,不支持内置变量
+ file:writef("hello %s\n", "xmake")
+
+ -- 使用xmake扩展的格式化传参写入一行,带换行符,并且支持内置变量
+ file:print("hello %s and $(buildir)", "xmake")
+
+ -- 使用xmake扩展的格式化传参写入一行,无换行符,并且支持内置变量
+ file:printf("hello %s and $(buildir) \n", "xmake")
+
+ -- 关闭文件
+ file:close()
+end
+```
+
+###### io.load
+
+- 从指定路径文件反序列化加载所有table内容
+
+可以从文件中加载序列化好的table内容,一般与[io.save](#io-save)配合使用,例如:
+
+```lua
+-- 加载序列化文件的内容到table
+local data = io.load("xxx.txt")
+if data then
+
+ -- 在终端中dump打印整个table中内容,格式化输出
+ table.dump(data)
+end
+```
+
+###### io.save
+
+- 序列化保存所有table内容到指定路径文件
+
+可以序列化存储table内容到指定文件,一般与[io.load](#io-load)配合使用,例如:
+
+```lua
+io.save("xxx.txt", {a = "a", b = "b", c = "c"})
+```
+
+存储结果为:
+
+```
+{
+ ["b"] = "b"
+, ["a"] = "a"
+, ["c"] = "c"
+}
+```
+
+###### io.readfile
+
+- 从指定路径文件读取所有内容
+
+可在不打开文件的情况下,直接读取整个文件的内容,更加的方便,例如:
+
+```lua
+local data = io.readfile("xxx.txt")
+```
+
+###### io.writefile
+
+- 写入所有内容到指定路径文件
+
+可在不打开文件的情况下,直接写入整个文件的内容,更加的方便,例如:
+
+```lua
+io.writefile("xxx.txt", "all data")
+```
+
+###### io.gsub
+
+- 全文替换指定路径文件的内容
+
+类似[string.gsub](#string-gsub)接口,全文模式匹配替换内容,不过这里是直接操作文件,例如:
+
+```lua
+-- 移除文件所有的空白字符
+io.gsub("xxx.txt", "%s+", "")
+```
+
+###### io.tail
+
+- 读取和显示文件的尾部内容
+
+读取文件尾部指定行数的数据,并显示,类似`cat xxx.txt | tail -n 10`命令,例如:
+
+```lua
+-- 显示文件最后10行内容
+io.tail("xxx.txt", 10)
+```
+
+###### io.cat
+
+- 读取和显示文件的所有内容
+
+读取文件的所有内容并显示,类似`cat xxx.txt`命令,例如:
+
+```lua
+io.cat("xxx.txt")
+```
+
+###### io.print
+
+- 带换行格式化输出内容到文件
+
+直接格式化传参输出一行字符串到文件,并且带换行,例如:
+
+```lua
+io.print("xxx.txt", "hello %s!", "xmake")
+```
+
+###### io.printf
+
+- 无换行格式化输出内容到文件
+
+直接格式化传参输出一行字符串到文件,不带换行,例如:
+
+```lua
+io.printf("xxx.txt", "hello %s!\n", "xmake")
+```
+
+##### path
+
+路径操作模块,实现跨平台的路径操作,这是xmake的一个自定义的模块。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [path.join](#path-join) | 拼接路径 | >= 2.0.1 |
+| [path.translate](#path-translate) | 转换路径到当前平台的路径风格 | >= 2.0.1 |
+| [path.basename](#path-basename) | 获取路径最后不带后缀的文件名 | >= 2.0.1 |
+| [path.filename](#path-filename) | 获取路径最后带后缀的文件名 | >= 2.0.1 |
+| [path.extension](#path-extension) | 获取路径的后缀名 | >= 2.0.1 |
+| [path.directory](#path-directory) | 获取路径最后的目录名 | >= 2.0.1 |
+| [path.relative](#path-relative) | 转换成相对路径 | >= 2.0.1 |
+| [path.absolute](#path-absolute) | 转换成绝对路径 | >= 2.0.1 |
+| [path.is_absolute](#path-is_absolute) | 判断是否为绝对路径 | >= 2.0.1 |
+
+###### path.join
+
+- 拼接路径
+
+将多个路径项进行追加拼接,由于`windows/unix`风格的路径差异,使用api来追加路径更加跨平台,例如:
+
+```lua
+print(path.join("$(tmpdir)", "dir1", "dir2", "file.txt"))
+```
+
+上述拼接在unix上相当于:`$(tmpdir)/dir1/dir2/file.txt`,而在windows上相当于:`$(tmpdir)\\dir1\\dir2\\file.txt`
+
+如果觉得这样很繁琐,不够清晰简洁,可以使用:[path.translate](path-translate)方式,格式化转换路径字符串到当前平台支持的格式。
+
+###### path.translate
+
+- 转换路径到当前平台的路径风格
+
+格式化转化指定路径字符串到当前平台支持的路径风格,同时支持`windows/unix`格式的路径字符串参数传入,甚至混合传入,例如:
+
+```lua
+print(path.translate("$(tmpdir)/dir/file.txt"))
+print(path.translate("$(tmpdir)\\dir\\file.txt"))
+print(path.translate("$(tmpdir)\\dir/dir2//file.txt"))
+```
+
+上面这三种不同格式的路径字符串,经过`translate`规范化后,就会变成当前平台支持的格式,并且会去掉冗余的路径分隔符。
+
+###### path.basename
+
+- 获取路径最后不带后缀的文件名
+
+```lua
+print(path.basename("$(tmpdir)/dir/file.txt"))
+```
+
+显示结果为:`file`
+
+###### path.filename
+
+- 获取路径最后带后缀的文件名
+
+```lua
+print(path.filename("$(tmpdir)/dir/file.txt"))
+```
+
+显示结果为:`file.txt`
+
+###### path.extension
+
+- 获取路径的后缀名
+
+```lua
+print(path.extensione("$(tmpdir)/dir/file.txt"))
+```
+
+显示结果为:`.txt`
+
+###### path.directory
+
+- 获取路径最后的目录名
+
+```lua
+print(path.directory("$(tmpdir)/dir/file.txt"))
+```
+
+显示结果为:`dir`
+
+###### path.relative
+
+- 转换成相对路径
+
+```lua
+print(path.relative("$(tmpdir)/dir/file.txt", "$(tmpdir)"))
+```
+
+显示结果为:`dir/file.txt`
+
+第二个参数是指定相对的根目录,如果不指定,则默认相对当前目录:
+
+```lua
+os.cd("$(tmpdir)")
+print(path.relative("$(tmpdir)/dir/file.txt"))
+```
+
+这样结果是一样的。
+
+###### path.absolute
+
+- 转换成绝对路径
+
+```lua
+print(path.absolute("dir/file.txt", "$(tmpdir)"))
+```
+
+显示结果为:`$(tmpdir)/dir/file.txt`
+
+第二个参数是指定相对的根目录,如果不指定,则默认相对当前目录:
+
+```lua
+os.cd("$(tmpdir)")
+print(path.absolute("dir/file.txt"))
+```
+
+这样结果是一样的。
+
+###### path.is_absolute
+
+- 判断是否为绝对路径
+
+```lua
+if path.is_absolute("/tmp/file.txt") then
+ -- 如果是绝对路径
+end
+```
+
+##### table
+
+table属于lua原生提供的模块,对于原生接口使用可以参考:[lua官方文档](http://www.lua.org/manual/5.1/manual.html#5.5)
+
+xmake中对其进行了扩展,增加了一些扩展接口:
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [table.join](#table-join) | 合并多个table并返回 | >= 2.0.1 |
+| [table.join2](#table-join2) | 合并多个table到第一个table | >= 2.0.1 |
+| [table.dump](#table-dump) | 输出table的所有内容 | >= 2.0.1 |
+| [table.unique](#table-unique) | 对table中的内容进行去重 | >= 2.0.1 |
+| [table.slice](#table-slice) | 获取table的切片 | >= 2.0.1 |
+
+###### table.join
+
+- 合并多个table并返回
+
+可以将多个table里面的元素进行合并后,返回到一个新的table中,例如:
+
+```lua
+local newtable = table.join({1, 2, 3}, {4, 5, 6}, {7, 8, 9})
+```
+
+结果为:`{1, 2, 3, 4, 5, 6, 7, 8, 9}`
+
+并且它也支持字典的合并:
+
+```lua
+local newtable = table.join({a = "a", b = "b"}, {c = "c"}, {d = "d"})
+```
+
+结果为:`{a = "a", b = "b", c = "c", d = "d"}`
+
+###### table.join2
+
+- 合并多个table到第一个table
+
+类似[table.join](#table.join),唯一的区别是,合并的结果放置在第一个参数中,例如:
+
+```lua
+local t = {0, 9}
+table.join2(t, {1, 2, 3})
+```
+
+结果为:`t = {0, 9, 1, 2, 3}`
+
+###### table.dump
+
+- 输出table的所有内容
+
+递归格式化打印table中的所有内容,一般用于调试, 例如:
+
+```lua
+table.dump({1, 2, 3})
+```
+
+结果为:`{1, 2, 3}`
+
+###### table.unique
+
+- 对table中的内容进行去重
+
+去重table的元素,一般用于数组table,例如:
+
+```lua
+local newtable = table.unique({1, 1, 2, 3, 4, 4, 5})
+```
+
+结果为:`{1, 2, 3, 4, 5}`
+
+###### table.slice
+
+- 获取table的切片
+
+用于提取数组table的部分元素,例如:
+
+```lua
+-- 提取第4个元素后面的所有元素,结果:{4, 5, 6, 7, 8, 9}
+table.slice({1, 2, 3, 4, 5, 6, 7, 8, 9}, 4)
+
+-- 提取第4-8个元素,结果:{4, 5, 6, 7, 8}
+table.slice({1, 2, 3, 4, 5, 6, 7, 8, 9}, 4, 8)
+
+-- 提取第4-8个元素,间隔步长为2,结果:{4, 6, 8}
+table.slice({1, 2, 3, 4, 5, 6, 7, 8, 9}, 4, 8, 2)
+```
+
+##### string
+
+字符串模块为lua原生自带的模块,具体使用见:[lua官方手册](http://www.lua.org/manual/5.1/manual.html#5.4)
+
+xmake中对其进行了扩展,增加了一些扩展接口:
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [string.startswith](#string-startswith) | 判断字符串开头是否匹配 | >= 1.0.1 |
+| [string.endswith](#string-endswith) | 判断字符串结尾是否匹配 | >= 1.0.1 |
+| [string.split](#string-split) | 分割字符串 | >= 1.0.1 |
+| [string.trim](#string-trim) | 去掉字符串左右空白字符 | >= 1.0.1 |
+| [string.ltrim](#string-ltrim) | 去掉字符串左边空白字符 | >= 1.0.1 |
+| [string.rtrim](#string-rtrim) | 去掉字符串右边空白字符 | >= 1.0.1 |
+
+###### string.startswith
+
+- 判断字符串开头是否匹配
+
+```lua
+local s = "hello xmake"
+if s:startswith("hello") then
+ print("match")
+end
+```
+
+###### string.endswith
+
+- 判断字符串结尾是否匹配
+
+```lua
+local s = "hello xmake"
+if s:endswith("xmake") then
+ print("match")
+end
+```
+
+###### string.split
+
+- 分割字符串
+
+通过指定的分隔符进行字符串分割,分隔符可以是:字符,字符串、模式匹配字符串,例如:
+
+```lua
+local s = "hello xmake!"
+s:split("%s+")
+```
+
+根据连续空白字符进行分割,结果为:`hello`, `xmake!`
+
+```lua
+local s = "hello,xmake:123"
+s:split("[,:]")
+```
+
+上面的代码根据`,`或者`:`字符进行分割,结果为:`hello`, `xmake`, `123`
+
+###### string.trim
+
+- 去掉字符串左右空白字符
+
+```lua
+string.trim(" hello xmake! ")
+```
+
+结果为:"hello xmake!"
+
+###### string.ltrim
+
+- 去掉字符串左边空白字符
+
+```lua
+string.ltrim(" hello xmake! ")
+```
+
+结果为:"hello xmake! "
+
+###### string.rtrim
+
+- 去掉字符串右边空白字符
+
+```lua
+string.rtrim(" hello xmake! ")
+```
+
+结果为:" hello xmake!"
+
+##### process
+
+这个是xmake扩展的进程控制模块,用于更加灵活的控制进程,比起:[os.run](#os-run)系列灵活性更高,也更底层。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [process.open](#process-open) | 打开进程 | >= 2.0.1 |
+| [process.wait](#process-wait) | 等待进程结束 | >= 2.0.1 |
+| [process.close](#process-close) | 关闭进程对象 | >= 2.0.1 |
+| [process.waitlist](#process-waitlist) | 同时等待多个进程 | >= 2.0.1 |
+
+###### process.open
+
+- 打开进程
+
+通过路径创建运行一个指定程序,并且返回对应的进程对象:
+
+```lua
+-- 打开进程,后面两个参数指定需要捕获的stdout, stderr文件路径
+local proc = process.open("echo hello xmake!", outfile, errfile)
+if proc then
+
+ -- 等待进程执行完成
+ --
+ -- 参数二为等待超时,-1为永久等待,0为尝试获取进程状态
+ -- 返回值waitok为等待状态:1为等待进程正常结束,0为进程还在运行中,-1位等待失败
+ -- 返回值status为,等待进程结束后,进程返回的状态码
+ local waitok, status = process.wait(proc, -1)
+
+ -- 释放进程对象
+ process.close(proc)
+end
+```
+
+###### process.wait
+
+- 等待进程结束
+
+具体使用见:[process.open](#process-open)
+
+###### process.close
+
+- 关闭进程对象
+
+具体使用见:[process.open](#process-open)
+
+###### process.waitlist
+
+- 同时等待多个进程
+
+```lua
+-- 第二个参数是等待超时,返回进程状态列表
+for _, procinfo in ipairs(process.waitlist(procs, -1)) do
+
+ -- 每个进程的:进程对象、进程pid、进程结束状态码
+ local proc = procinfo[1]
+ local procid = procinfo[2]
+ local status = procinfo[3]
+
+end
+```
+
+##### coroutine
+
+协程模块是lua原生自带的模块,具使用见:[lua官方手册](http://www.lua.org/manual/5.1/manual.html#5.2)
+
+#### Extension Modules
+
+所有扩展模块的使用,都需要通过[import](#import)接口,进行导入后才能使用。
+
+##### core.base.option
+
+一般用于获取xmake命令参数选项的值,常用于插件开发。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [option.get](#option-get) | 获取参数选项值 | >= 2.0.1 |
+
+###### option.get
+
+- 获取参数选项值
+
+在插件开发中用于获取参数选项值,例如:
+
+```lua
+-- 导入选项模块
+import("core.base.option")
+
+-- 插件入口函数
+function main(...)
+ print(option.get("info"))
+end
+```
+
+上面的代码获取hello插件,执行:`xmake hello --info=xxxx` 命令时候传入的`--info=`选项的值,并显示:`xxxx`
+
+对于非main入口的task任务或插件,可以这么使用:
+
+```lua
+task("hello")
+ on_run(function ())
+ import("core.base.option")
+ print(option.get("info"))
+ end)
+```
+
+##### core.base.global
+
+用于获取xmake全局的配置信息,也就是`xmake g|global --xxx=val` 传入的参数选项值。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [global.get](#global-get) | 获取指定配置值 | >= 2.0.1 |
+| [global.load](#global-load) | 加载配置 | >= 2.0.1 |
+| [global.directory](#global-directory) | 获取全局配置信息目录 | >= 2.0.1 |
+| [global.dump](#global-dump) | 打印输出所有全局配置信息 | >= 2.0.1 |
+
+<p class="tip">
+2.1.5版本之前为`core.project.global`。
+</p>
+
+###### global.get
+
+- 获取指定配置值
+
+类似[config.get](#config-get),唯一的区别就是这个是从全局配置中获取。
+
+###### global.load
+
+- 加载配置
+
+类似[global.get](#global-get),唯一的区别就是这个是从全局配置中加载。
+
+###### global.directory
+
+- 获取全局配置信息目录
+
+默认为`~/.config`目录。
+
+###### global.dump
+
+- 打印输出所有全局配置信息
+
+输出结果如下:
+
+```lua
+{
+ clean = true
+, ccache = "ccache"
+, xcode_dir = "/Applications/Xcode.app"
+}
+```
+
+##### core.base.task
+
+用于任务操作,一般用于在自定义脚本中、插件任务中,调用运行其他task任务。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [task.run](#task-run) | 运行指定任务 | >= 2.0.1 |
+
+<p class="tip">
+2.1.5版本之前为`core.project.task`。
+</p>
+
+###### task.run
+
+- 运行指定任务
+
+用于在自定义脚本、插件任务中运行[task](#task)定义的任务或插件,例如:
+
+```lua
+task("hello")
+ on_run(function ()
+ print("hello xmake!")
+ end)
+
+target("demo")
+ on_clean(function(target)
+
+ -- 导入task模块
+ import("core.base.task")
+
+ -- 运行这个hello task
+ task.run("hello")
+ end)
+```
+
+我们还可以在运行任务时,增加参数传递,例如:
+
+```lua
+task("hello")
+ on_run(function (arg1, arg2)
+ print("hello xmake: %s %s!", arg1, arg2)
+ end)
+
+target("demo")
+ on_clean(function(target)
+
+ -- 导入task
+ import("core.base.task")
+
+ -- {} 这个是给第一种选项传参使用,这里置空,这里在最后面传入了两个参数:arg1, arg2
+ task.run("hello", {}, "arg1", "arg2")
+ end)
+```
+
+对于`task.run`的第二个参数,用于传递命令行菜单中的选项,而不是直接传入`function (arg, ...)`函数入口中,例如:
+
+```lua
+-- 导入task
+import("core.base.task")
+
+-- 插件入口
+function main(...)
+
+ -- 运行内置的xmake配置任务,相当于:xmake f|config --plat=iphoneos --arch=armv7
+ task.run("config", {plat="iphoneos", arch="armv7"})
+emd
+```
+
+##### core.tool.linker
+
+链接器相关操作,常用于插件开发。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [linker.link](#linker-link) | 执行链接 | >= 2.0.1 |
+| [linker.linkcmd](#linker-linkcmd) | 获取链接命令行 | >= 2.0.1 |
+| [linker.linkargv](#linker-linkargv) | 获取链接命令行列表 | >= 2.1.5 |
+| [linker.linkflags](#linker-linkflags) | 获取链接选项 | >= 2.0.1 |
+| [linker.has_flags](#linker-has_flags) | 判断指定链接选项是否支持 | >= 2.1.5 |
+
+###### linker.link
+
+- 执行链接
+
+针对target,链接指定对象文件列表,生成对应的目标文件,例如:
+
+```lua
+linker.link({"a.o", "b.o", "c.o"}, target:targetfile(), {target = target})
+```
+
+其中[target](#target),为工程目标,这里传入,主要用于获取target特定的链接选项,具体如果获取工程目标对象,见:[core.project.project](#core-project-project)
+
+当然也可以不指定target,例如:
+
+```lua
+linker.link("binary", "cc", {"a.o", "b.o", "c.o"}, "/tmp/targetfile")
+```
+
+###### linker.linkcmd
+
+- 获取链接命令行字符串
+
+直接获取[linker.link](#linker-link)中执行的命令行字符串,相当于:
+
+```lua
+local cmdstr = linker.linkcmd("static", "cxx", {"a.o", "b.o", "c.o"}, target:targetfile(), {target = target})
+```
+
+注:后面`{target = target}`扩展参数部分是可选的,如果传递了target对象,那么生成的链接命令,会加上这个target配置对应的链接选项。
+
+并且还可以自己传递各种配置,例如:
+
+```lua
+local cmdstr = linker.linkcmd("static", "cxx", {"a.o", "b.o", "c.o"}, target:targetfile(), {config = {linkdirs = "/usr/lib"}})
+```
+
+###### linker.linkargv
+
+- 获取链接命令行参数列表
+
+跟[linker.linkcmd](#linker-linkcmd)稍微有点区别的是,此接口返回的是参数列表,table表示,更加方便操作:
+
+```lua
+local program, argv = linker.linkargv("static", "cxx", {"a.o", "b.o", "c.o"}, target:targetfile(), {target = target})
+```
+
+其中返回的第一个值是主程序名,后面是参数列表,而`os.args(table.join(program, argv))`等价于`linker.linkcmd`。
+
+我们也可以通过传入返回值给[os.runv](#os-runv)来直接运行它:`os.runv(linker.linkargv(..))`
+
+###### linker.linkflags
+
+- 获取链接选项
+
+获取[linker.linkcmd](#linker-linkcmd)中的链接选项字符串部分,不带shellname和对象文件列表,并且是按数组返回,例如:
+
+```lua
+local flags = linker.linkflags("shared", "cc", {target = target})
+for _, flag in ipairs(flags) do
+ print(flag)
+end
+```
+
+返回的是flags的列表数组。
+
+###### linker.has_flags
+
+- 判断指定链接选项是否支持
+
+虽然通过[lib.detect.has_flags](detect-has_flags)也能判断,但是那个接口更加底层,需要指定链接器名称
+而此接口只需要指定target的目标类型,源文件类型,它会自动切换选择当前支持的链接器。
+
+```lua
+if linker.has_flags(target:targetkind(), target:sourcekinds(), "-L/usr/lib -lpthread") then
+ -- ok
+end
+```
+
+##### core.tool.compiler
+
+编译器相关操作,常用于插件开发。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [compiler.compile](#compiler-compile) | 执行编译 | >= 2.0.1 |
+| [compiler.compcmd](#compiler-compcmd) | 获取编译命令行 | >= 2.0.1 |
+| [compiler.compargv](#compiler-compargv) | 获取编译命令行列表 | >= 2.1.5 |
+| [compiler.compflags](#compiler-compflags) | 获取编译选项 | >= 2.0.1 |
+| [compiler.has_flags](#compiler-has_flags) | 判断指定编译选项是否支持 | >= 2.1.5 |
+| [compiler.features](#compiler-features) | 获取所有编译器特性 | >= 2.1.5 |
+| [compiler.has_features](#compiler-has_features) | 判断指定编译特性是否支持 | >= 2.1.5 |
+
+###### compiler.compile
+
+- 执行编译
+
+针对target,链接指定对象文件列表,生成对应的目标文件,例如:
+
+```lua
+compiler.compile("xxx.c", "xxx.o", "xxx.h.d", {target = target})
+```
+
+其中[target](#target),为工程目标,这里传入主要用于获取taeget的特定编译选项,具体如果获取工程目标对象,见:[core.project.project](#core-project-project)
+
+而`xxx.h.d`文件用于存储为此源文件的头文件依赖文件列表,最后这两个参数都是可选的,编译的时候可以不传他们:
+
+```lua
+compiler.compile("xxx.c", "xxx.o")
+```
+
+来单纯编译一个源文件。
+
+###### compiler.compcmd
+
+- 获取编译命令行
+
+直接获取[compiler.compile](#compiler-compile)中执行的命令行字符串,相当于:
+
+```lua
+local cmdstr = compiler.compcmd("xxx.c", "xxx.o", {target = target})
+```
+
+注:后面`{target = target}`扩展参数部分是可选的,如果传递了target对象,那么生成的编译命令,会加上这个target配置对应的链接选项。
+
+并且还可以自己传递各种配置,例如:
+
+```lua
+local cmdstr = compiler.compcmd("xxx.c", "xxx.o", {config = {includedirs = "/usr/include", defines = "DEBUG"}})
+```
+
+通过target,我们可以导出指定目标的所有源文件编译命令:
+
+```lua
+import("core.project.project")
+
+for _, target in pairs(project.targets()) do
+ for sourcekind, sourcebatch in pairs(target:sourcebatches()) do
+ for index, objectfile in ipairs(sourcebatch.objectfiles) do
+ local cmdstr = compiler.compcmd(sourcebatch.sourcefiles[index], objectfile, {target = target})
+ end
+ end
+end
+```
+
+###### compiler.compargv
+
+- 获取编译命令行列表
+
+跟[compiler.compargv](#compiler-compargv)稍微有点区别的是,此接口返回的是参数列表,table表示,更加方便操作:
+
+```lua
+local program, argv = compiler.compargv("xxx.c", "xxx.o")
+```
+
+###### compiler.compflags
+
+- 获取编译选项
+
+获取[compiler.compcmd](#compiler-compcmd)中的编译选项字符串部分,不带shellname和文件列表,例如:
+
+```lua
+local flags = compiler.compflags(sourcefile, {target = target})
+for _, flag in ipairs(flags) do
+ print(flag)
+end
+```
+
+返回的是flags的列表数组。
+
+###### compiler.has_flags
+
+- 判断指定编译选项是否支持
+
+虽然通过[lib.detect.has_flags](detect-has_flags)也能判断,但是那个接口更加底层,需要指定编译器名称。
+而此接口只需要指定语言类型,它会自动切换选择当前支持的编译器。
+
+```lua
+-- 判断c语言编译器是否支持选项: -g
+if compiler.has_flags("c", "-g") then
+ -- ok
+end
+
+-- 判断c++语言编译器是否支持选项: -g
+if compiler.has_flags("cxx", "-g") then
+ -- ok
+end
+```
+
+###### compiler.features
+
+- 获取所有编译器特性
+
+虽然通过[lib.detect.features](detect-features)也能获取,但是那个接口更加底层,需要指定编译器名称。
+而此接口只需要指定语言类型,它会自动切换选择当前支持的编译器,然后获取当前的编译器特性列表。
+
+```lua
+-- 获取当前c语言编译器的所有特性
+local features = compiler.features("c")
+
+-- 获取当前c++语言编译器的所有特性,启用c++11标准,否则获取不到新标准的特性
+local features = compiler.features("cxx", {cofnig = {cxxflags = "-std=c++11"}})
+
+-- 获取当前c++语言编译器的所有特性,传递工程target的所有配置信息
+local features = compiler.features("cxx", {target = target, config = {defines = "..", includedirs = ".."}})
+```
+
+所有c编译器特性列表:
+
+| 特性名 |
+| --------------------- |
+| c_static_assert |
+| c_restrict |
+| c_variadic_macros |
+| c_function_prototypes |
+
+所有c++编译器特性列表:
+
+| 特性名 |
+| ------------------------------------ |
+| cxx_variable_templates |
+| cxx_relaxed_constexpr |
+| cxx_aggregate_default_initializers |
+| cxx_contextual_conversions |
+| cxx_attribute_deprecated |
+| cxx_decltype_auto |
+| cxx_digit_separators |
+| cxx_generic_lambdas |
+| cxx_lambda_init_captures |
+| cxx_binary_literals |
+| cxx_return_type_deduction |
+| cxx_decltype_incomplete_return_types |
+| cxx_reference_qualified_functions |
+| cxx_alignof |
+| cxx_attributes |
+| cxx_inheriting_constructors |
+| cxx_thread_local |
+| cxx_alias_templates |
+| cxx_delegating_constructors |
+| cxx_extended_friend_declarations |
+| cxx_final |
+| cxx_nonstatic_member_init |
+| cxx_override |
+| cxx_user_literals |
+| cxx_constexpr |
+| cxx_defaulted_move_initializers |
+| cxx_enum_forward_declarations |
+| cxx_noexcept |
+| cxx_nullptr |
+| cxx_range_for |
+| cxx_unrestricted_unions |
+| cxx_explicit_conversions |
+| cxx_lambdas |
+| cxx_local_type_template_args |
+| cxx_raw_string_literals |
+| cxx_auto_type |
+| cxx_defaulted_functions |
+| cxx_deleted_functions |
+| cxx_generalized_initializers |
+| cxx_inline_namespaces |
+| cxx_sizeof_member |
+| cxx_strong_enums |
+| cxx_trailing_return_types |
+| cxx_unicode_literals |
+| cxx_uniform_initialization |
+| cxx_variadic_templates |
+| cxx_decltype |
+| cxx_default_function_template_args |
+| cxx_long_long_type |
+| cxx_right_angle_brackets |
+| cxx_rvalue_references |
+| cxx_static_assert |
+| cxx_extern_templates |
+| cxx_func_identifier |
+| cxx_variadic_macros |
+| cxx_template_template_parameters |
+
+###### compiler.has_features
+
+- 判断指定的编译器特性是否支持
+
+虽然通过[lib.detect.has_features](detect-has-features)也能获取,但是那个接口更加底层,需要指定编译器名称。
+而此接口只需要指定需要检测的特姓名称列表,就能自动切换选择当前支持的编译器,然后判断指定特性在当前的编译器中是否支持。
+
+```lua
+if compiler.has_features("c_static_assert") then
+ -- ok
+end
+
+if compiler.has_features({"c_static_assert", "cxx_constexpr"}, {languages = "cxx11"}) then
+ -- ok
+end
+
+if compiler.has_features("cxx_constexpr", {target = target, defines = "..", includedirs = ".."}) then
+ -- ok
+end
+```
+
+具体特性名有哪些,可以参考:[compiler.features](#compiler-features)。
+
+##### core.project.config
+
+用于获取工程编译时候的配置信息,也就是`xmake f|config --xxx=val` 传入的参数选项值。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [config.get](#config-get) | 获取指定配置值 | >= 2.0.1 |
+| [config.load](#config-load) | 加载配置 | >= 2.0.1 |
+| [config.arch](#config-arch) | 获取当前工程的架构配置 | >= 2.0.1 |
+| [config.plat](#config-plat) | 获取当前工程的平台配置 | >= 2.0.1 |
+| [config.mode](#config-mode) | 获取当前工程的编译模式配置 | >= 2.0.1 |
+| [config.buildir](#config-buildir) | 获取当前工程的输出目录配置 | >= 2.0.1 |
+| [config.directory](#config-directory) | 获取当前工程的配置信息目录 | >= 2.0.1 |
+| [config.dump](#config-dump) | 打印输出当前工程的所有配置信息 | >= 2.0.1 |
+
+###### config.get
+
+- 获取指定配置值
+
+用于获取`xmake f|config --xxx=val`的配置值,例如:
+
+```lua
+target("test")
+ on_run(function (target)
+
+ -- 导入配置模块
+ import("core.project.config")
+
+ -- 获取配置值
+ print(config.get("xxx"))
+ end)
+```
+
+###### config.load
+
+- 加载配置
+
+一般用于插件开发中,插件任务中不像工程的自定义脚本,环境需要自己初始化加载,默认工程配置是没有被加载的,如果要用[config.get](#config-get)接口获取工程配置,那么需要先:
+
+```lua
+
+-- 导入配置模块
+import("core.project.config")
+
+function main(...)
+
+ -- 先加载工程配置
+ config.load()
+
+ -- 获取配置值
+ print(config.get("xxx"))
+end
+```
+
+###### config.arch
+
+- 获取当前工程的架构配置
+
+也就是获取`xmake f|config --arch=armv7`的平台配置,相当于`config.get("arch")`。
+
+###### config.plat
+
+- 获取当前工程的平台配置
+
+也就是获取`xmake f|config --plat=iphoneos`的平台配置,相当于`config.get("plat")`。
+
+###### config.mode
+
+- 获取当前工程的编译模式配置
+
+也就是获取`xmake f|config --mode=debug`的平台配置,相当于`config.get("mode")`。
+
+###### config.buildir
+
+- 获取当前工程的输出目录配置
+
+也就是获取`xmake f|config -o /tmp/output`的平台配置,相当于`config.get("buildir")`。
+
+###### config.directory
+
+- 获取当前工程的配置信息目录
+
+获取工程配置的存储目录,默认为:`projectdir/.config`
+
+###### config.dump
+
+- 打印输出当前工程的所有配置信息
+
+输出结果例如:
+
+```lua
+{
+ sh = "xcrun -sdk macosx clang++"
+, xcode_dir = "/Applications/Xcode.app"
+, ar = "xcrun -sdk macosx ar"
+, small = true
+, object = false
+, arch = "x86_64"
+, xcode_sdkver = "10.12"
+, ex = "xcrun -sdk macosx ar"
+, cc = "xcrun -sdk macosx clang"
+, rc = "rustc"
+, plat = "macosx"
+, micro = false
+, host = "macosx"
+, as = "xcrun -sdk macosx clang"
+, dc = "dmd"
+, gc = "go"
+, openssl = false
+, ccache = "ccache"
+, cxx = "xcrun -sdk macosx clang"
+, sc = "xcrun -sdk macosx swiftc"
+, mm = "xcrun -sdk macosx clang"
+, buildir = "build"
+, mxx = "xcrun -sdk macosx clang++"
+, ld = "xcrun -sdk macosx clang++"
+, mode = "release"
+, kind = "static"
+}
+```
+
+##### core.project.global
+
+<p class="tip">
+此模块自2.1.5版本后迁移至[core.base.global](#core-base-global)。
+</p>
+
+##### core.project.task
+
+<p class="tip">
+此模块自2.1.5版本后迁移至[core.base.task](#core-base-task)。
+</p>
+
+##### core.project.project
+
+用于获取当前工程的一些描述信息,也就是在`xmake.lua`工程描述文件中定义的配置信息,例如:[target](#target)、[option](#option)等。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------------------- |
+| [project.load](#project-load) | 加载工程配置 | >= 2.0.1 (2.1.5废弃) |
+| [project.directory](#project-directory) | 获取工程目录 | >= 2.0.1 |
+| [project.target](#project-target) | 获取指定工程目标对象 | >= 2.0.1 |
+| [project.targets](#project-targets) | 获取工程目标对象列表 | >= 2.0.1 |
+| [project.option](#project-option) | 获取指定的选项对象 | >= 2.1.5 |
+| [project.options](#project-options) | 获取工程所有的选项对象 | >= 2.1.5 |
+| [project.name](#project-name) | 获取当前工程名 | >= 2.0.1 |
+| [project.version](#project-version) | 获取当前工程版本号 | >= 2.0.1 |
+
+###### project.load
+
+- 加载工程描述配置
+
+仅在插件中使用,因为这个时候还没有加载工程配置信息,在工程目标的自定义脚本中,不需要执行此操作,就可以直接访问工程配置。
+
+```lua
+-- 导入工程模块
+import("core.project.project")
+
+-- 插件入口
+function main(...)
+
+ -- 加载工程描述配置
+ project.load()
+
+ -- 访问工程描述,例如获取指定工程目标
+ local target = project.target("test")
+end
+```
+
+<p class="tip">
+2.1.5版本后,不在需要,工程加载会自动在合适时机延迟加载。
+</p>
+
+###### project.directory
+
+- 获取工程目录
+
+获取当前工程目录,也就是`xmake -P xxx`中指定的目录,否则为默认当前`xmake`命令执行目录。
+
+<p class="tip">
+2.1.5版本后,建议使用[os.projectdir](#os-projectdir)来获取。
+</p>
+
+###### project.target
+
+- 获取指定工程目标对象
+
+获取和访问指定工程目标配置,例如:
+
+```lua
+local target = project.target("test")
+if target then
+
+ -- 获取目标文件名
+ print(target:targetfile())
+
+ -- 获取目标类型,也就是:binary, static, shared
+ print(target:targetkind())
+
+ -- 获取目标名
+ print(target:name())
+
+ -- 获取目标源文件
+ local sourcefiles = target:sourcefiles()
+
+ -- 获取目标安装头文件列表
+ local srcheaders, dstheaders = target:headerfiles()
+
+ -- 获取目标依赖
+ print(target:get("deps"))
+end
+```
+
+###### project.targets
+
+- 获取工程目标对象列表
+
+返回当前工程的所有编译目标,例如:
+
+```lua
+for targetname, target in pairs(project.targets())
+ print(target:targetfile())
+end
+```
+
+###### project.option
+
+- 获取指定选项对象
+
+获取和访问工程中指定的选项对象,例如:
+
+```lua
+local option = project.option("test")
+if option:enabled() then
+ option:enable(false)
+end
+```
+
+###### project.options
+
+- 获取工程所有选项对象
+
+返回当前工程的所有编译目标,例如:
+
+```lua
+for optionname, option in pairs(project.options())
+ print(option:enabled())
+end
+```
+
+###### project.name
+
+- 获取当前工程名
+
+也就是获取[set_project](#set_project)的工程名配置。
+
+```lua
+print(project.name())
+```
+
+###### project.version
+
+- 获取当前工程版本号
+
+也就是获取[set_version](#set_version)的工程版本配置。
+
+```lua
+print(project.version())
+```
+
+##### core.language.language
+
+用于获取编译语言相关信息,一般用于代码文件的操作。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [language.extensions](#language-extensions) | 获取所有语言的代码后缀名列表 | >= 2.1.1 |
+| [language.targetkinds](#language-targetkinds) | 获取所有语言的目标类型列表 | >= 2.1.1 |
+| [language.sourcekinds](#language-sourcekinds) | 获取所有语言的源文件类型列表 | >= 2.1.1 |
+| [language.sourceflags](#language-sourceflags) | 加载所有语言的源文件编译选项名列表 | >= 2.1.1 |
+| [language.load](#language-load) | 加载指定语言 | >= 2.1.1 |
+| [language.load_sk](#language-load_sk) | 从源文件类型加载指定语言 | >= 2.1.1 |
+| [language.load_ex](#language-load_ex) | 从源文件后缀名加载指定语言 | >= 2.1.1 |
+| [language.sourcekind_of](#language-sourcekind_of) | 获取指定源文件的源文件类型 | >= 2.1.1 |
+
+###### language.extensions
+
+- 获取所有语言的代码后缀名列表
+
+获取结果如下:
+
+```lua
+{
+ [".c"] = cc
+, [".cc"] = cxx
+, [".cpp"] = cxx
+, [".m"] = mm
+, [".mm"] = mxx
+, [".swift"] = sc
+, [".go"] = gc
+}
+```
+
+###### language.targetkinds
+
+- 获取所有语言的目标类型列表
+
+获取结果如下:
+
+```lua
+{
+ binary = {"ld", "gc-ld", "dc-ld"}
+, static = {"ar", "gc-ar", "dc-ar"}
+, shared = {"sh", "dc-sh"}
+}
+```
+
+###### language.sourcekinds
+
+- 获取所有语言的源文件类型列表
+
+获取结果如下:
+
+```lua
+{
+ cc = ".c"
+, cxx = {".cc", ".cpp", ".cxx"}
+, mm = ".m"
+, mxx = ".mm"
+, sc = ".swift"
+, gc = ".go"
+, rc = ".rs"
+, dc = ".d"
+, as = {".s", ".S", ".asm"}
+}
+```
+
+###### language.sourceflags
+
+- 加载所有语言的源文件编译选项名列表
+
+获取结果如下:
+
+```lua
+{
+ cc = {"cflags", "cxflags"}
+, cxx = {"cxxflags", "cxflags"}
+, ...
+}
+```
+
+###### language.load
+
+- 加载指定语言
+
+从语言名称加载具体语言对象,例如:
+
+```lua
+local lang = language.load("c++")
+if lang then
+ print(lang:name())
+end
+```
+
+###### language.load_sk
+
+- 从源文件类型加载指定语言
+
+从源文件类型:`cc, cxx, mm, mxx, sc, gc, as ..`加载具体语言对象,例如:
+
+```lua
+local lang = language.load_sk("cxx")
+if lang then
+ print(lang:name())
+end
+```
+
+###### language.load_ex
+
+- 从源文件后缀名加载指定语言
+
+从源文件后缀名:`.cc, .c, .cpp, .mm, .swift, .go ..`加载具体语言对象,例如:
+
+```lua
+local lang = language.load_sk(".cpp")
+if lang then
+ print(lang:name())
+end
+```
+
+###### language.sourcekind_of
+
+- 获取指定源文件的源文件类型
+
+也就是从给定的一个源文件路径,获取它是属于那种源文件类型,例如:
+
+```lua
+print(language.sourcekind_of("/xxxx/test.cpp"))
+```
+
+显示结果为:`cxx`,也就是`c++`类型,具体对应列表见:[language.sourcekinds](#language-sourcekinds)
+
+##### core.platform.platform
+
+平台信息相关操作
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [platform.get](#platform-get) | 获取指定平台相关配置信息 | >= 2.0.1 |
+
+###### platform.get
+
+- 获取指定平台相关配置信息
+
+获取平台配置`xmake.lua`中设置的信息,一般只有在写插件的时候会用到,例如:
+
+```lua
+-- 获取当前平台的所有支持架构
+print(platform.get("archs"))
+
+-- 获取指定iphoneos平台的目标文件格式信息
+local formats = platform.get("formats", "iphoneos")
+table.dump(formats)
+```
+
+具体有哪些可读的平台配置信息,可参考:[platform](#platform)
+
+##### core.platform.environment
+
+环境相关操作,用于进入和离开指定环境变量对应的终端环境,一般用于`path`环境的进入和离开,尤其是一些需要特定环境的构建工具,例如:msvc的工具链。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [environment.enter](#environment-enter) | 进入指定环境 | >= 2.0.1 |
+| [environment.leave](#environment-leave) | 离开指定环境 | >= 2.0.1 |
+
+目前支持的环境有:
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| toolchains | 工具链执行环境 | >= 2.0.1 |
+
+###### environment.enter
+
+- 进入指定环境
+
+进入指定环境,例如msvc有自己的环境变量环境用于运行构建工具,例如:`cl.exe`, `link.exe`这些,这个时候想要在xmake里面运行他们,需要:
+
+```lua
+-- 进入工具链环境
+environment.enter("toolchains")
+
+-- 这个时候运行cl.exe才能正常运行,这个时候的path等环境变量都会进入msvc的环境模式
+os.run("cl.exe ..")
+
+-- 离开工具链环境
+environment.leave("toolchains")
+```
+
+因此为了通用性,默认xmake编译事都会设置这个环境,在linux下基本上内部环境不需要特殊切换,目前仅对windows下msvc进行了处理。
+
+###### environment.leave
+
+- 离开指定环境
+
+具体使用见:[environment.enter](#environment-enter)
+
+##### lib.detect
+
+此模块提供了非常强大的探测功能,用于探测程序、编译器、语言特性、依赖包等。
+
+<p class="tip">
+此模块的接口分散在多个模块目录中,尽量通过导入单个接口来使用,这样效率更高,例如:`import("lib.detect.find_package")`,而不是通过`import("lib.detect")`导入所有来调用。
+</p>
+
+| 接口 | 描述 | 支持版本 |
+| --------------------------------------------------- | -------------------------------------------- | -------------------- |
+| [detect.find_file](#detect-find_file) | 查找文件 | >= 2.1.5 |
+| [detect.find_path](#detect-find_path) | 查找文件路径 | >= 2.1.5 |
+| [detect.find_library](#detect-find_library) | 查找库文件 | >= 2.1.5 |
+| [detect.find_program](#detect-find_program) | 查找可执行程序 | >= 2.1.5 |
+| [detect.find_programver](#detect-find_programver) | 查找可执行程序版本号 | >= 2.1.5 |
+| [detect.find_package](#detect-find_package) | 查找包文件,包含库文件和搜索路径 | >= 2.1.5 |
+| [detect.find_tool](#detect-find_tool) | 查找工具 | >= 2.1.5 |
+| [detect.find_toolname](#detect-find_toolname) | 查找工具名 | >= 2.1.5 |
+| [detect.features](#detect-features) | 获取指定工具的所有特性 | >= 2.1.5 |
+| [detect.has_features](#detect-has_features) | 判断指定特性是否支持 | >= 2.1.5 |
+| [detect.has_flags](#detect-has_flags) | 判断指定参数选项是否支持 | >= 2.1.5 |
+| [detect.has_cfuncs](#detect-has_cfuncs) | 判断指定c函数是否存在 | >= 2.1.5 |
+| [detect.has_cxxfuncs](#detect-has_cxxfuncs) | 判断指定c++函数是否存在 | >= 2.1.5 |
+| [detect.has_cincludes](#detect-has_cincludes) | 判断指定c头文件是否存在 | >= 2.1.5 |
+| [detect.has_cxxincludess](#detect-has_cxxincludes) | 判断指定c++头文件是否存在 | >= 2.1.5 |
+| [detect.has_ctypes](#detect-has_ctypes) | 判断指定c类型是否存在 | >= 2.1.5 |
+| [detect.has_cxxtypes](#detect-has_cxxtypes) | 判断指定c++类型是否存在 | >= 2.1.5 |
+| [detect.check_cxsnippets](#detect-check_cxsnippets) | 检测c/c++代码片段是否能够编译通过 | >= 2.1.5 |
+
+###### detect.find_file
+
+- 查找文件
+
+这个接口提供了比[os.files](#os-files)更加强大的工程, 可以同时指定多个搜索目录,并且还能对每个目录指定附加的子目录,来模式匹配查找,相当于是[os.files](#os-files)的增强版。
+
+例如:
+
+```lua
+import("lib.detect.find_file")
+
+local file = find_file("ccache", { "/usr/bin", "/usr/local/bin"})
+```
+
+如果找到,返回的结果是:`/usr/bin/ccache`
+
+它同时也支持模式匹配路径,进行递归查找,类似`os.files`:
+
+```lua
+local file = find_file("test.h", { "/usr/include", "/usr/local/include/**"})
+```
+
+不仅如此,里面的路径也支持内建变量,来从环境变量和注册表中获取路径进行查找:
+
+```lua
+local file = find_file("xxx.h", { "$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name)"})
+```
+
+如果路径规则比较复杂多变,还可以通过自定义脚本来动态生成路径传入:
+
+```lua
+local file = find_file("xxx.h", { "$(env PATH)", function () return val("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name"):match("\"(.-)\"") end})
+```
+
+大部分场合下,上面的使用已经满足各种需求了,如果还需要一些扩展功能,可以通过传入第三个参数,自定义一些可选配置,例如:
+
+```lua
+local file = find_file("test.h", { "/usr", "/usr/local"}, {suffixes = {"/include", "/lib"}})
+```
+
+通过指定suffixes子目录列表,可以扩展路径列表(第二个参数),使得实际的搜索目录扩展为:
+
+```
+/usr/include
+/usr/lib
+/usr/local/include
+/usr/local/lib
+```
+
+并且不用改变路径列表,就能动态切换子目录来搜索文件。
+
+<p class="tip">
+我们也可以通过`xmake lua`插件来快速调用和测试此接口:`xmake lua lib.detect.find_file test.h /usr/local`
+</p>
+
+###### detect.find_path
+
+- 查找路径
+
+这个接口的用法跟[lib.detect.find_file](#detect-find_file)类似,唯一的区别是返回的结果不同。
+此接口查找到传入的文件路径后,返回的是对应的搜索路径,而不是文件路径本身,一般用于查找文件对应的父目录位置。
+
+```lua
+import("lib.detect.find_path")
+
+local p = find_path("include/test.h", { "/usr", "/usr/local"})
+```
+
+上述代码如果查找成功,则返回:`/usr/local`,如果`test.h`在`/usr/local/include/test.h`的话。
+
+还有一个区别就是,这个接口传入不只是文件路径,还可以传入目录路径来查找:
+
+```lua
+local p = find_path("lib/xxx", { "$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name)"})
+```
+
+同样,此接口也支持模式匹配和后缀子目录:
+
+```lua
+local p = find_path("include/*.h", { "/usr", "/usr/local/**"}, {suffixes = "/subdir"})
+```
+
+###### detect.find_library
+
+- 查找库文件
+
+此接口用于指定的搜索目录中查找库文件(静态库,动态库),例如:
+
+```lua
+import("lib.detect.find_library")
+
+local library = find_library("crypto", {"/usr/lib", "/usr/local/lib"})
+```
+
+在macosx上运行,返回的结果如下:
+
+```lua
+{
+ filename = libcrypto.dylib
+, linkdir = /usr/lib
+, link = crypto
+, kind = shared
+}
+```
+
+如果不指定是否需要静态库还是动态库,那么此接口会自动选择一个存在的库(有可能是静态库、也有可能是动态库)进行返回。
+
+如果需要强制指定需要查找的库类型,可以指定kind参数为(`static/shared`):
+
+```lua
+local library = find_library("crypto", {"/usr/lib", "/usr/local/lib"}, {kind = "static"})
+```
+
+此接口也支持suffixes后缀子目录搜索和模式匹配操作:
+
+```lua
+local library = find_library("cryp*", {"/usr", "/usr/local"}, {suffixes = "/lib"})
+```
+
+###### detect.find_program
+
+- 查找可执行程序
+
+这个接口比[lib.detect.find_tool](#detect-find_tool)较为原始底层,通过指定的参数目录来查找可执行程序。
+
+```lua
+import("lib.detect.find_program")
+
+local program = find_program("ccache")
+```
+
+上述代码犹如没有传递搜索目录,所以它会尝试直接执行指定程序,如果运行ok,那么直接返回:`ccache`,表示查找成功。
+
+指定搜索目录,修改尝试运行的检测命令参数(默认是:`ccache --version`):
+
+```lua
+local program = find_program("ccache", {"/usr/bin", "/usr/local/bin"}, "--help")
+```
+
+上述代码会尝试运行:`/usr/bin/ccache --help`,如果运行成功,则返回:`/usr/bin/ccache`。
+
+如果`--help`也没法满足需求,有些程序没有`--version/--help`参数,那么可以自定义运行脚本,来运行检测:
+
+```lua
+local program = find_program("ccache", {"/usr/bin", "/usr/local/bin"}, function (program) os.run("%s -h", program) end)
+```
+
+同样,搜索路径列表支持内建变量和自定义脚本:
+
+```lua
+local program = find_program("ccache", {"$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug;Debugger)"})
+local program = find_program("ccache", {"$(env PATH)", function () return "/usr/local/bin" end})
+```
+
+<p class="tip">
+为了加速频发查找的效率,此接口是默认自带cache的,所以就算频繁查找相同的程序,也不会花太多时间。
+如果要禁用cache,可以在工程目录执行`xmake f -c`清除本地cache。
+</p>
+
+我们也可以通过`xmake lua lib.detect.find_program ccache` 来快速测试。
+
+###### detect.find_programver
+
+- 查找可执行程序版本号
+
+
+```lua
+import("lib.detect.find_programver")
+
+local programver = find_programver("ccache")
+```
+
+返回结果为:3.2.2
+
+默认它会通过`ccache --version`尝试获取版本,如果不存在此参数,可以自己指定其他参数:
+
+```lua
+local version = find_programver("ccache", "-v")
+```
+
+甚至自定义版本获取脚本:
+
+```lua
+local version = find_programver("ccache", function () return os.iorun("ccache --version") end)
+```
+
+对于版本号的提取规则,如果内置的匹配模式不满足要求,也可以自定义:
+
+```lua
+local version = find_programver("ccache", "--version", "(%d+%.?%d*%.?%d*.-)%s")
+local version = find_programver("ccache", "--version", function (output) return output:match("(%d+%.?%d*%.?%d*.-)%s") end)
+```
+
+<p class="tip">
+为了加速频发查找的效率,此接口是默认自带cache的,如果要禁用cache,可以在工程目录执行`xmake f -c`清除本地cache。
+</p>
+
+我们也可以通过`xmake lua lib.detect.find_programver ccache` 来快速测试。
+
+###### detect.find_package
+
+- 查找包文件
+
+此接口也是用于查找库文件,但是比[lib.detect.find_library](#detect-find_library)更加上层,也更为强大和简单易用,因为它是以包为力度进行查找。
+
+那怎样算是一个完整的包,它包含:
+
+1. 多个静态库或者动态库文件
+2. 库的搜索目录
+3. 头文件的搜索目录
+4. 可选的编译链接选项,例如:`defines`等
+5. 可选的版本号
+
+例如我们查找一个openssl包:
+
+```lua
+import("lib.detect.find_package")
+
+local package = find_package("openssl")
+```
+
+返回的结果如下:
+
+```lua
+{links = {"ssl", "crypto", "z"}, linkdirs = {"/usr/local/lib"}, includedirs = {"/usr/local/include"}}
+```
+
+如果查找成功,则返回一个包含所有包信息的table,如果失败返回nil
+
+这里的返回结果可以直接作为`target:add`, `option:add`的参数传入,用于动态增加`target/option`的配置:
+
+```lua
+option("zlib")
+ set_showmenu(true)
+ before_check(function (option)
+ import("lib.detect.find_package")
+ option:add(find_package("zlib"))
+ end)
+```
+
+```lua
+target("test")
+ on_load(function (target)
+ import("lib.detect.find_package")
+ target:add(find_package("zlib"))
+ end)
+```
+
+如果系统上装有`homebrew`, `pkg-config`等第三方工具,那么此接口会尝试使用它们去改进查找结果。
+
+我们也可以通过指定版本号,来选择查找指定版本的包(如果这个包获取不到版本信息或者没有匹配版本的包,则返回nil):
+
+```lua
+local package = find_package("openssl", {version = "1.0.1"})
+```
+
+默认情况下查找的包是根据如下规则匹配平台,架构和模式的:
+
+1. 如果参数传入指定了`{plat = "iphoneos", arch = "arm64", mode = "release"}`,则优先匹配,例如:`find_package("openssl", {plat = "iphoneos"})`。
+2. 如果是在当前工程环境,存在配置文件,则优先尝试从`config.get("plat")`, `config.get("arch")`和`config.get("mode")`获取平台架构进行匹配。
+3. 最后从`os.host()`和`os.arch()`中进行匹配,也就是当前主机的平台架构环境。
+
+如果系统的库目录以及`pkg-config`都不能满足需求,找不到包,那么可以自己手动设置搜索路径:
+
+```lua
+local package = find_package("openssl", {linkdirs = {"/usr/lib", "/usr/local/lib"}, includedirs = "/usr/local/include"})
+```
+
+也可以同时指定需要搜索的链接名,头文件名:
+
+```lua
+local package = find_package("openssl", {links = {"ssl", "crypto"}, includes = "ssl.h"}})
+```
+
+甚至可以指定xmake的`packagedir/*.pkg`包目录,用于查找对应的`openssl.pkg`包,一般用于查找内置在工程目录中的本地包。
+
+例如,tbox工程内置了`pkg/openssl.pkg`本地包载项目中,我们可以通过下面的脚本,传入`{packagedirs = ""}`参数优先查找本地包,如果找不到再去找系统包。
+
+```lua
+target("test")
+ on_load(function (target)
+ import("lib.detect.find_package")
+ target:add(find_package("openssl", {packagedirs = path.join(os.projectdir(), "pkg")}))
+ end)
+```
+
+总结下,现在的查找顺序:
+
+1. 如果指定`{packagedirs = ""}`参数,优先从这个参数指定的路径中查找本地包`*.pkg`
+2. 如果在`xmake/modules`下面存在`detect.packages.find_xxx`脚本,那么尝试调用此脚本来改进查找结果
+3. 如果系统存在`pkg-config`,并且查找的是系统环境的库,则尝试使用`pkg-config`提供的路径和链接信息进行查找
+4. 如果系统存在`homebrew`,并且查找的是系统环境的库,则尝试使用`brew --prefix xxx`提供的信息进行查找
+5. 从参数中指定的pathes路径和一些已知的系统路径`/usr/lib`, `/usr/include`中进行查找
+
+这里需要着重说下第二点,通过在`detect.packages.find_xxx`脚本来改进查找结果,很多时候自动的包探测是没法完全探测到包路径的,
+尤其是针对windows平台,没有默认的库目录,也没有包管理app,很多库装的时候,都是自己所处放置在系统目录,或者添加注册表项。
+
+因此查找起来没有同意的规则,这个时候,就可以自定义一个查找脚本,去改进`find_package`的查找机制,对指定包进行更精准的查找。
+
+在xmake自带的`xmake/modules/detect/packages`目录下,已经有许多的内置包脚本,来对常用的包进行更好的查找支持。
+当然这不可能满足所有用户的需求,如果用户需要的包还是找不到,那么可以自己定义一个查找脚本,例如:
+
+查找一个名为`openssl`的包,可以编写一个`find_openssl.lua`的脚本放置在工程目录:
+
+```
+projectdir
+ - xmake
+ - modules
+ - detect/package/find_openssl.lua
+```
+
+然后在工程的`xmake.lua`文件的开头指定下这个modules的目录:
+
+```lua
+add_moduledirs("$(projectdir)/xmake/modules")
+```
+
+这样xmake就能找到自定义的扩展模块了。
+
+接下来我们看下`find_openssl.lua`的实现:
+
+```lua
+-- imports
+import("lib.detect.find_path")
+import("lib.detect.find_library")
+
+-- find openssl
+--
+-- @param opt the package options. e.g. see the options of find_package()
+--
+-- @return see the return value of find_package()
+--
+function main(opt)
+
+ -- for windows platform
+ --
+ -- http://www.slproweb.com/products/Win32OpenSSL.html
+ --
+ if opt.plat == "windows" then
+
+ -- init bits
+ local bits = ifelse(opt.arch == "x64", "64", "32")
+
+ -- init search pathes
+ local pathes = {"$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL %(" .. bits .. "-bit%)_is1;Inno Setup: App Path)",
+ "$(env PROGRAMFILES)/OpenSSL",
+ "$(env PROGRAMFILES)/OpenSSL-Win" .. bits,
+ "C:/OpenSSL",
+ "C:/OpenSSL-Win" .. bits}
+
+ -- find library
+ local result = {links = {}, linkdirs = {}, includedirs = {}}
+ for _, name in ipairs({"libssl", "libcrypto"}) do
+ local linkinfo = find_library(name, pathes, {suffixes = "lib"})
+ if linkinfo then
+ table.insert(result.links, linkinfo.link)
+ table.insert(result.linkdirs, linkinfo.linkdir)
+ end
+ end
+
+ -- not found?
+ if #result.links ~= 2 then
+ return
+ end
+
+ -- find include
+ table.insert(result.includedirs, find_path("openssl/ssl.h", pathes, {suffixes = "include"}))
+
+ -- ok
+ return result
+ end
+end
+```
+
+里面对windows平台进行注册表读取,去查找指定的库文件,其底层其实也是调用的[find_library](#detect-find_library)等接口。
+
+<p class="tip">
+为了加速频发查找的效率,此接口是默认自带cache的,如果要禁用cache,可以在工程目录执行`xmake f -c`清除本地cache。
+也可以通过指定force参数,来禁用cache,强制重新查找:`find_package("openssl", {force = true})`
+</p>
+
+我们也可以通过`xmake lua lib.detect.find_package openssl` 来快速测试。
+
+###### detect.find_tool
+
+- 查找工具
+
+此接口也是用于查找可执行程序,不过比[lib.detect.find_program](#detect-find_program)更加的高级,功能也更加强大,它对可执行程序进行了封装,提供了工具这个概念:
+
+* toolname: 工具名,可执行程序的简称,用于标示某个工具,例如:`gcc`, `clang`等
+* program: 可执行程序命令,例如:`xcrun -sdk macosx clang`
+
+其对应关系如下:
+
+| toolname | program |
+| --------- | ----------------------------------- |
+| clang | `xcrun -sdk macosx clang` |
+| gcc | `/usr/toolchains/bin/arm-linux-gcc` |
+| link | `link.exe -lib` |
+
+[lib.detect.find_program](#detect-find_program)只能通过传入的原始program命令或路径,去判断该程序是否存在。
+而`find_tool`则可以通过更加一致的toolname去查找工具,并且返回对应的program完整命令路径,例如:
+
+```lua
+import("lib.detect.find_tool")
+
+local tool = find_tool("clang")
+```
+
+返回的结果为:`{name = "clang", program = "clang"}`,这个时候还看不出区别,我们可以手动指定可执行的命令:
+
+```lua
+local tool = find_tool("clang", {program = "xcrun -sdk macosx clang"})
+```
+
+返回的结果为:`{name = "clang", program = "xcrun -sdk macosx clang"}`
+
+而在macosx下,gcc就是clang,如果我们执行`gcc --version`可以看到就是clang的一个马甲,我们可以通过`find_tool`接口进行智能识别:
+
+```lua
+local tool = find_tool("gcc")
+```
+
+返回的结果为:`{name = "clang", program = "gcc"}`
+
+通过这个结果就可以看的区别来了,工具名实际会被标示为clang,但是可执行的命令用的是gcc。
+
+我们也可以指定`{version = true}`参数去获取工具的版本,并且指定一个自定义的搜索路径,也支持内建变量和自定义脚本哦:
+
+```lua
+local tool = find_tool("clang", {version = true, {pathes = {"/usr/bin", "/usr/local/bin", "$(env PATH)", function () return "/usr/xxx/bin" end}})
+```
+
+返回的结果为:`{name = "clang", program = "/usr/bin/clang", version = "4.0"}`
+
+这个接口是对`find_program`的上层封装,因此也支持自定义脚本检测:
+
+```lua
+local tool = find_tool("clang", {check = "--help"})
+local tool = find_tool("clang", {check = function (tool) os.run("%s -h", tool) end})
+```
+
+最后总结下,`find_tool`的查找流程:
+
+1. 优先通过`{program = "xxx"}`的参数来尝试运行和检测。
+2. 如果在`xmake/modules/detect/tools`下存在`detect.tools.find_xxx`脚本,则调用此脚本进行更加精准的检测。
+3. 尝试从`/usr/bin`,`/usr/local/bin`等系统目录进行检测。
+
+我们也可以在工程`xmake.lua`中`add_moduledirs`指定的模块目录中,添加自定义查找脚本,来改进检测机制:
+
+```
+projectdir
+ - xmake/modules
+ - detect/tools/find_xxx.lua
+```
+
+例如我们自定义一个`find_7z.lua`的查找脚本:
+
+```lua
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+
+ -- find program
+ local program = find_program(opt.program or "7z", opt.pathes, opt.check or "--help")
+
+ -- find program version
+ local version = nil
+ if program and opt and opt.version then
+ version = find_programver(program, "--help", "(%d+%.?%d*)%s")
+ end
+
+ -- ok?
+ return program, version
+end
+```
+
+将它放置到工程的模块目录下后,执行:`xmake l lib.detect.find_tool 7z`就可以查找到了。
+
+<p class="tip">
+为了加速频发查找的效率,此接口是默认自带cache的,如果要禁用cache,可以在工程目录执行`xmake f -c`清除本地cache。
+</p>
+
+我们也可以通过`xmake lua lib.detect.find_tool clang` 来快速测试。
+
+###### detect.find_toolname
+
+- 查找工具名
+
+通过program命令匹配对应的工具名,例如:
+
+| program | toolname |
+| ------------------------- | ---------- |
+| `xcrun -sdk macosx clang` | clang |
+| `/usr/bin/arm-linux-gcc` | gcc |
+| `link.exe -lib` | link |
+| `gcc-5` | gcc |
+| `arm-android-clang++` | clangxx |
+| `pkg-config` | pkg_config |
+
+toolname相比program,更能唯一标示某个工具,也方便查找和加载对应的脚本`find_xxx.lua`。
+
+###### detect.features
+
+- 获取指定工具的所有特性
+
+此接口跟[compiler.features](#compiler-features)类似,区别就是此接口更加的原始,传入的参数是实际的工具名toolname。
+
+并且此接口不仅能够获取编译器的特性,任何工具的特性都可以获取,因此更加通用。
+
+```lua
+import("lib.detect.features")
+
+local features = features("clang")
+local features = features("clang", {flags = "-O0", program = "xcrun -sdk macosx clang"})
+local features = features("clang", {flags = {"-g", "-O0", "-std=c++11"}})
+```
+
+通过传入flags,可以改变特性的获取结果,例如一些c++11的特性,默认情况下获取不到,通过启用`-std=c++11`后,就可以获取到了。
+
+所有编译器的特性列表,可以见:[compiler.features](#compiler-features)。
+
+###### detect.has_features
+
+- 判断指定特性是否支持
+
+此接口跟[compiler.has_features](#compiler-has_features)类似,但是更加原始,传入的参数是实际的工具名toolname。
+
+并且此接口不仅能够判断编译器的特性,任何工具的特性都可以判断,因此更加通用。
+
+```lua
+import("lib.detect.has_features")
+
+local features = has_features("clang", "cxx_constexpr")
+local features = has_features("clang", {"cxx_constexpr", "c_static_assert"}, {flags = {"-g", "-O0"}, program = "xcrun -sdk macosx clang"})
+local features = has_features("clang", {"cxx_constexpr", "c_static_assert"}, {flags = "-g"})
+```
+
+如果指定的特性列表存在,则返回实际支持的特性子列表,如果都不支持,则返回nil,我们也可以通过指定flags去改变特性的获取规则。
+
+所有编译器的特性列表,可以见:[compiler.features](#compiler-features)。
+
+###### detect.has_flags
+
+- 判断指定参数选项是否支持
+
+此接口跟[compiler.has_flags](#compiler-has_flags)类似,但是更加原始,传入的参数是实际的工具名toolname。
+
+```lua
+import("lib.detect.has_flags")
+
+local ok = has_flags("clang", "-g")
+local ok = has_flags("clang", {"-g", "-O0"}, {program = "xcrun -sdk macosx clang"})
+local ok = has_flags("clang", "-g -O0", {toolkind = "cxx"})
+```
+
+如果检测通过,则返回true。
+
+此接口的检测做了一些优化,除了cache机制外,大部分场合下,会去拉取工具的选项列表(`--help`)直接判断,如果选项列表里获取不到的话,才会通过尝试运行的方式来检测。
+
+###### detect.has_cfuncs
+
+- 判断指定c函数是否存在
+
+此接口是[lib.detect.check_cxsnippets](#detect-check_cxsnippets)的简化版本,仅用于检测函数。
+
+```lua
+import("lib.detect.has_cfuncs")
+
+local ok = has_cfuncs("setjmp")
+local ok = has_cfuncs({"sigsetjmp((void*)0, 0)", "setjmp"}, {includes = "setjmp.h"})
+```
+
+对于函数的描述规则如下:
+
+| 函数描述 | 说明 |
+| ----------------------------------------------- | ------------- |
+| `sigsetjmp` | 纯函数名 |
+| `sigsetjmp((void*)0, 0)` | 函数调用 |
+| `sigsetjmp{int a = 0; sigsetjmp((void*)a, a);}` | 函数名 + {}块 |
+
+在最后的可选参数中,除了可以指定`includes`外,还可以指定其他的一些参数用于控制编译检测的选项条件:
+
+```lua
+{ verbose = false, target = [target|option], includes = .., config = {linkdirs = .., links = .., defines = ..}}
+```
+
+其中verbose用于回显检测信息,target用于在检测前追加target中的配置信息, 而config用于自定义配置跟target相关的编译选项。
+
+###### detect.has_cxxfuncs
+
+- 判断指定c++函数是否存在
+
+此接口跟[lib.detect.has_cfuncs](#detect-has_cfuncs)类似,请直接参考它的使用说明,唯一区别是这个接口用于检测c++函数。
+
+###### detect.has_cincludes
+
+- 判断指定c头文件是否存在
+
+此接口是[lib.detect.check_cxsnippets](#detect-check_cxsnippets)的简化版本,仅用于检测头文件。
+
+```lua
+import("lib.detect.has_cincludes")
+
+local ok = has_cincludes("stdio.h")
+local ok = has_cincludes({"stdio.h", "stdlib.h"}, {target = target})
+local ok = has_cincludes({"stdio.h", "stdlib.h"}, {config = {defines = "_GNU_SOURCE=1", languages = "cxx11"}})
+```
+
+###### detect.has_cxxincludes
+
+- 判断指定c++头文件是否存在
+
+此接口跟[lib.detect.has_cincludess](#detect-has_cincludes)类似,请直接参考它的使用说明,唯一区别是这个接口用于检测c++头文件。
+
+###### detect.has_ctypes
+
+- 判断指定c类型是否存在
+
+此接口是[lib.detect.check_cxsnippets](#detect-check_cxsnippets)的简化版本,仅用于检测函数。
+
+```lua
+import("lib.detect.has_ctypes")
+
+local ok = has_ctypes("wchar_t")
+local ok = has_ctypes({"char", "wchar_t"}, {includes = "stdio.h"})
+local ok = has_ctypes("wchar_t", {includes = {"stdio.h", "stdlib.h"}, config = {"defines = "_GNU_SOURCE=1", languages = "cxx11"}})
+```
+
+###### detect.has_cxxtypes
+
+- 判断指定c++类型是否存在
+
+此接口跟[lib.detect.has_ctypess](#detect-has_ctypes)类似,请直接参考它的使用说明,唯一区别是这个接口用于检测c++类型。
+
+###### detect.check_cxsnippets
+
+- 检测c/c++代码片段是否能够编译通过
+
+通用的c/c++代码片段检测接口,通过传入多个代码片段列表,它会自动生成一个编译文件,然后常识对它进行编译,如果编译通过返回true。
+
+对于一些复杂的编译器特性,连[compiler.has_features](#compiler-has_features)都无法检测到的时候,可以通过此接口通过尝试编译来检测它。
+
+```lua
+import("lib.detect.check_cxsnippets")
+
+local ok = check_cxsnippets("void test() {}")
+local ok = check_cxsnippets({"void test(){}", "#define TEST 1"}, {types = "wchar_t", includes = "stdio.h"})
+```
+
+此接口是[detect.has_cfuncs](#detect-has_cfuncs), [detect.has_cincludes](#detect-has_cincludes)和[detect.has_ctypes](detect-has_ctypes)等接口的通用版本,也更加底层。
+
+因此我们可以用它来检测:types, functions, includes 还有 links,或者是组合起来一起检测。
+
+第一个参数为代码片段列表,一般用于一些自定义特性的检测,如果为空,则可以仅仅检测可选参数中条件,例如:
+
+```lua
+local ok = check_cxsnippets({}, {types = {"wchar_t", "char*"}, includes = "stdio.h", funcs = {"sigsetjmp", "sigsetjmp((void*)0, 0)"}})
+```
+
+上面那个调用,会去同时检测types, includes和funcs是否都满足,如果通过返回true。
+
+还有其他一些可选参数:
+
+```lua
+{ verbose = false, target = [target|option], sourcekind = "[cc|cxx]"}
+```
+
+其中verbose用于回显检测信息,target用于在检测前追加target中的配置信息, sourcekind 用于指定编译器等工具类型,例如传入`cxx`强制作为c++代码来检测。
+
+##### net.http
+
+此模块提供http的各种操作支持,目前提供的接口如下:
+
+| 接口 | 描述 | 支持版本 |
+| --------------------------------------------------- | -------------------------------------------- | -------------------- |
+| [http.download](#http-download) | 下载http文件 | >= 2.1.5 |
+
+###### http.download
+
+- 下载http文件
+
+这个接口比较简单,就是单纯的下载文件。
+
+```lua
+import("net.http")
+
+http.download("http://xmake.io", "/tmp/index.html")
+```
+
+##### privilege.sudo
+
+此接口用于通过`sudo`来运行命令,并且提供了平台一致性处理,对于一些需要root权限运行的脚本,可以使用此接口。
+
+<p class="warning">
+为了保证安全性,除非必须使用的场合,其他情况下尽量不要使用此接口。
+</p>
+
+| 接口 | 描述 | 支持版本 |
+| --------------------------------------------------- | -------------------------------------------- | -------------------- |
+| [sudo.has](#sudo-has) | 判断sudo是否支持 | >= 2.1.5 |
+| [sudo.run](#sudo-run) | 安静运行程序 | >= 2.1.5 |
+| [sudo.runv](#sudo-runv) | 安静运行程序,带参数列表 | >= 2.1.5 |
+| [sudo.exec](#sudo-exec) | 回显运行程序 | >= 2.1.5 |
+| [sudo.execv](#sudo-execv) | 回显运行程序,带参数列表 | >= 2.1.5 |
+| [sudo.iorun](#sudo-iorun) | 运行并获取程序输出内容 | >= 2.1.5 |
+| [sudo.iorunv](#sudo-iorunv) | 运行并获取程序输出内容,带参数列表 | >= 2.1.5 |
+
+###### sudo.has
+
+- 判断sudo是否支持
+
+目前仅在`macosx/linux`下支持sudo,windows上的管理员权限运行暂时还不支持,因此建议使用前可以通过此接口判断支持情况后,针对性处理。
+
+```lua
+import("privilege.sudo")
+
+if sudo.has() then
+ sudo.run("rm /system/file")
+end
+```
+
+###### sudo.run
+
+- 安静运行原生shell命令
+
+具体用法可参考:[os.run](#os-run)。
+
+```lua
+import("privilege.sudo")
+
+sudo.run("rm /system/file")
+```
+
+###### sudo.runv
+
+- 安静运行原生shell命令,带参数列表
+
+具体用法可参考:[os.runv](#os-runv)。
+
+###### sudo.exec
+
+- 回显运行原生shell命令
+
+具体用法可参考:[os.exec](#os-exec)。
+
+###### sudo.execv
+
+- 回显运行原生shell命令,带参数列表
+
+具体用法可参考:[os.execv](#os-execv)。
+
+###### sudo.iorun
+
+- 安静运行原生shell命令并获取输出内容
+
+具体用法可参考:[os.iorun](#os-iorun)。
+
+###### sudo.iorunv
+
+- 安静运行原生shell命令并获取输出内容,带参数列表
+
+具体用法可参考:[os.iorunv](#os-iorunv)。
+
+##### devel.git
+
+此接口提供了git各种命令的访问接口,相对于直接调用git命令,此模块提供了更加上层易用的封装接口,并且提供对git的自动检测和跨平台处理。
+
+<p class="tip">
+目前windows上,需要手动安装git包后,才能检测到,后续版本会提供自动集成git功能,用户将不用关心如何安装git,就可以直接使用。
+</p>
+
+| 接口 | 描述 | 支持版本 |
+| --------------------------------------------------- | -------------------------------------------- | -------------------- |
+| [git.clone](#git-clone) | clone代码库 | >= 2.1.5 |
+| [git.pull](#git-pull) | 拉取代码库最新提交 | >= 2.1.5 |
+| [git.clean](#git-clean) | 清理代码库文件 | >= 2.1.5 |
+| [git.checkout](#git-checkout) | 签出指定分支版本 | >= 2.1.5 |
+| [git.refs](#git-refs) | 获取所有引用列表 | >= 2.1.5 |
+| [git.tags](#git-tags) | 获取所有标记列表 | >= 2.1.5 |
+| [git.branches](#git-branches) | 获取所有分支列表 | >= 2.1.5 |
+
+###### git.clone
+
+- clone代码库
+
+此接口对应`git clone`命令
+
+```lua
+import("devel.git")
+
+git.clone("git@github.com:tboox/xmake.git")
+git.clone("git@github.com:tboox/xmake.git", {depth = 1, branch = "master", outputdir = "/tmp/xmake"})
+```
+
+###### git.pull
+
+- 拉取代码库最新提交
+
+此接口对应`git pull`命令
+
+```lua
+import("devel.git")
+
+git.pull()
+git.pull({remote = "origin", tags = true, branch = "master", repodir = "/tmp/xmake"})
+```
+
+###### git.clean
+
+- 清理代码库文件
+
+此接口对应`git clean`命令
+
+```lua
+import("devel.git")
+
+git.clean()
+git.clean({repodir = "/tmp/xmake", force = true})
+```
+
+###### git.checkout
+
+- 签出指定分支版本
+
+此接口对应`git checkout`命令
+
+```lua
+import("devel.git")
+
+git.checkout("master", {repodir = "/tmp/xmake"})
+git.checkout("v1.0.1", {repodir = "/tmp/xmake"})
+```
+
+###### git.refs
+
+- 获取所有引用列表
+
+此接口对应`git ls-remote --refs`命令
+
+```lua
+import("devel.git")
+
+local refs = git.refs(url)
+```
+
+###### git.tags
+
+- 获取所有标记列表
+
+此接口对应`git ls-remote --tags`命令
+
+```lua
+import("devel.git")
+
+local tags = git.tags(url)
+```
+
+###### git.branches
+
+- 获取所有分支列表
+
+此接口对应`git ls-remote --heads`命令
+
+```lua
+import("devel.git")
+
+local branches = git.branches(url)
+```
+
+##### utils.archive
+
+此模块用于压缩和解压缩文件。
+
+| 接口 | 描述 | 支持版本 |
+| --------------------------------------------------- | -------------------------------------------- | -------------------- |
+| [archive.extract](#archive-extract) | 解压文件 | >= 2.1.5 |
+
+###### archive.extract
+
+- 解压文件
+
+支持大部分常用压缩文件的解压,它会自动检测系统提供了哪些解压工具,然后适配到最合适的解压器对指定压缩文件进行解压操作。
+
+```lua
+import("utils.archive")
+
+archive.extract("/tmp/a.zip", "/tmp/outputdir")
+archive.extract("/tmp/a.7z", "/tmp/outputdir")
+archive.extract("/tmp/a.gzip", "/tmp/outputdir")
+archive.extract("/tmp/a.tar.bz2", "/tmp/outputdir")
+```
diff --git a/pages/donation.html b/pages/donation.html
new file mode 100644
index 00000000..d0873051
--- /dev/null
+++ b/pages/donation.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<html lang="en-us">
+
+ <head>
+ <meta charset="UTF-8">
+ <title>xmake</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="theme-color" content="#157878">
+ <meta name="description" content="A cross-platform build utility based on Lua">
+ <meta name="keywords" content="make,makefile,build,lua,cross-compile,linux" />
+
+ <link rel="stylesheet" href="/assets/css/normalize.css">
+ <link rel='stylesheet' href="/assets/css/opensans.css" type='text/css'>
+ <link rel="stylesheet" href="/assets/css/cayman.css">
+
+ <!-- baidu stats -->
+ <script>
+ var _hmt = _hmt || [];
+ (function() {
+ var hm = document.createElement("script");
+ hm.src = "//hm.baidu.com/hm.js?eb3c91c672a001d78a113bfb8e42017a";
+ var s = document.getElementsByTagName("script")[0];
+ s.parentNode.insertBefore(hm, s);
+ })();
+ </script>
+</head>
+
+
+ <body>
+ <section class="page-header">
+ <h1 class="project-name">xmake</h1>
+ <h2 class="project-tagline">A cross-platform build utility based on Lua</h2>
+ <a href="/#/home" class="btn">GET STARTED</a>
+ <br><br>
+ <iframe src="https://ghbtns.com/github-btn.html?user=tboox&repo=xmake&type=star&count=true" frameborder="0" scrolling="0" width="110px" height="20px"></iframe>
+ <span class="donate" style="width: 100px">
+ <img src="/assets/img/patreon.png">
+ <a href="/pages/donation.html#donate">Support us</a>
+ </span>
+ <br><br>
+ <ul id="translations">
+ <li><a href="/cn/" class="nav-link">中文</a></li>
+ <li class="delimiter">|</li>
+ <li><a href="/" class="nav-link">English</a></li>
+ </ul>
+</section>
+
+
+
+ <section class="main-content">
+
+ <div id="donate"></div>
+
+<p>The xmake projects is a personal open source projects, their development need your help.</p>
+
+<p>If you would like to support the development of xmake, welcome to donate to us.</p>
+
+<h2 id="paypal">Paypal</h2>
+
+<p><a href="http://paypal.me/tboox/5"><img src="/assets/img/paypal.png" alt="Paypal Me" /></a></p>
+
+<h2 id="backers">Backers</h2>
+
+<p><a href="https://opencollective.com/xmake#backers" target="_blank"><img src="https://opencollective.com/xmake/backers.svg?width=890" /></a></p>
+
+<table>
+ <tbody>
+ <tr>
+ <td>2016.11.10</td>
+ <td><a href="https://github.com/lc-soft">lc-soft</a></td>
+ <td>oschina</td>
+ <td>¥10</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="sponsors">Sponsors</h2>
+
+<p>Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [<a href="https://opencollective.com/xmake#sponsor">Become a sponsor</a>]</p>
+
+<p><a href="https://opencollective.com/xmake/sponsor/0/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/0/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/1/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/1/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/2/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/2/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/3/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/3/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/4/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/4/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/5/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/5/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/6/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/6/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/7/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/7/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/8/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/8/avatar.svg" /></a>
+<a href="https://opencollective.com/xmake/sponsor/9/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/9/avatar.svg" /></a></p>
+
+<h2 id="alipay">Alipay</h2>
+
+<p><img src="/assets/img/alipay.png" alt="alipay" width="256" height="256" /></p>
+
+<h2 id="weixin">Weixin</h2>
+
+<p><img src="/assets/img/weixin.png" alt="weixin" width="218" height="218" /></p>
+
+
+
+ <footer class="site-footer">
+ <span class="site-footer-owner">Copyright (c) 2015-2017 <a href="http://www.tboox.org">tboox.org</a>.</span>
+ <span class="site-footer-power">
+ <span>
+ <!--Site powered by <a href="https://jekyllrb.com/">Jekyll</a> & <a href="http://pages.coding.me">Coding Pages</a>.-->
+ Site powered by <a href="https://jekyllrb.com/">Jekyll</a> & <a href="https://pages.github.com/">Github Pages</a>.
+ </span>
+ <span>
+ Theme designed by <a href="https://github.com/pietromenna/jekyll-cayman-theme">cayman</a>.
+ </span>
+</span>
+</footer>
+
+
+ </section>
+
+ </body>
+</html>
diff --git a/plugins.md b/plugins.md
new file mode 100644
index 00000000..216c8a4a
--- /dev/null
+++ b/plugins.md
@@ -0,0 +1,499 @@
+---
+search: en
+---
+
+## Plugin Development
+
+#### Introduction
+
+XMake supports the plugin module and we can develop ourself plugin module conveniently.
+
+We can run command `xmake -h` to look over some builtin plugins of xmake
+
+```
+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: Run a given lua script.
+* macro: Record and playback some xmake commands repeatly.
+* doxygen:Generate doxygen document automatically.
+* hello: The demo plugin and only print: 'hello xmake!'
+* project:Generate project file for IDE, only generate makefile now and will generate vs, xcode project in the future
+
+#### Quick Start
+
+Now we write a simple plugin demo for printing 'hello xmake!'
+
+```lua
+-- define a plugin task
+task("hello")
+
+ -- set the category for showing it in plugin category menu (optional)
+ set_category("plugin")
+
+ -- the main entry of the plugin
+ on_run(function ()
+
+ -- print 'hello xmake!'
+ print("hello xmake!")
+ end)
+
+ -- set the menu options, but we put empty options now.
+ set_menu {
+ -- usage
+ usage = "xmake hello [options]"
+
+ -- description
+ , description = "Hello xmake!"
+
+ -- options
+ , options = {}
+ }
+```
+
+The file tree of this plugin:
+
+```
+hello
+ - xmake.lua
+
+```
+
+Now one of the most simple plugin finished, how was it to be xmake detected it, there are three ways:
+
+1. Put this plugin directory into xmake/plugins the source codes as the builtin plugin.
+2. Put this plugin directory into ~/.xmake/plugins as the global user plugin.
+3. Put this plugin directory to anywhere and call `add_plugindirs("./hello")` in xmake.lua as the local project plugin.
+
+#### Run Plugin
+
+Next we run this plugin
+
+```bash
+xmake hello
+```
+
+The results is
+
+```
+hello xmake!
+```
+
+Finally, we can also run this plugin in the custom scripts of `xmake.lua`
+
+```lua
+
+target("demo")
+
+ -- run this plugin after building target
+ after_build(function (target)
+
+ -- import task module
+ import("core.project.task")
+
+ -- run the plugin task
+ task.run("hello")
+ end)
+```
+
+## Builtin Plugins
+
+#### Macros Recording and Playback
+
+##### Introduction
+
+We can record and playback our xmake commands and save as macro quickly using this plugin.
+
+And we can run this macro to simplify our jobs repeatly.
+
+##### Record Commands
+
+```bash
+# begin to record commands
+$ xmake macro --begin
+
+# run some xmake commands
+$ 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
+
+# stop to record and save as anonymous macro
+xmake macro --end
+```
+
+##### Playback Macro
+
+```bash
+# playback the previous anonymous macro
+$ xmake macro .
+```
+
+##### Named Macro
+
+```bash
+$ xmake macro --begin
+$ ...
+$ xmake macro --end macroname
+$ xmake macro macroname
+```
+
+##### Import and Export Macro
+
+Import the given macro file or directory.
+
+```bash
+$ xmake macro --import=/xxx/macro.lua macroname
+$ xmake macro --import=/xxx/macrodir
+```
+
+Export the given macro to file or directory.
+
+```bash
+$ xmake macro --export=/xxx/macro.lua macroname
+$ xmake macro --export=/xxx/macrodir
+```
+
+##### List and Show Macro
+
+List all builtin macros.
+
+```bash
+$ xmake macro --list
+```
+
+Show the given macro script content.
+
+```bash
+$ xmake macro --show macroname
+```
+
+##### Custom Macro Script
+
+Create and write a `macro.lua` script first.
+
+```lua
+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
+```
+
+Import this macro script to xmake.
+
+```bash
+$ xmake macro --import=/xxx/macro.lua [macroname]
+```
+
+Playback this macro script.
+
+```bash
+$ xmake macro [.|macroname]
+```
+
+##### Builtin Macros
+
+XMake supports some builtins macros to simplify our jobs.
+
+For example, we use `package` macro to package all architectures of the iphoneos platform just for once.
+
+```bash
+$ xmake macro package -p iphoneos
+```
+
+##### Advance Macro Script
+
+Let's see the `package` macro script:
+
+```lua
+-- 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">
+ If you want to known more options, please run: `xmake macro --help`
+</p>
+
+#### Run the Custom Lua Script
+
+##### Run the given script
+
+Write a simple lua script:
+
+```lua
+function main()
+ print("hello xmake!")
+end
+```
+
+Run this lua script.
+
+```bash
+$ xmake lua /tmp/test.lua
+```
+
+<p class="tip">
+ You can also use `import` api to write a more advance lua script.
+</p>
+
+##### Run the builtin script
+
+You can run `xmake lua -l` to list all builtin script name, for example:
+
+```bash
+$ xmake lua -l
+scripts:
+ cat
+ cp
+ echo
+ versioninfo
+ ...
+```
+
+And run them:
+
+```bash
+$ xmake lua cat ~/file.txt
+$ xmake lua echo "hello xmake"
+$ xmake lua cp /tmp/file /tmp/file2
+$ xmake lua versioninfo
+```
+
+##### Run interactive commands (REPL)
+
+Enter interactive mode:
+
+```bash
+$ xmake lua
+> 1 + 2
+3
+
+> a = 1
+> a
+1
+
+> for _, v in pairs({1, 2, 3}) do
+>> print(v)
+>> end
+1
+2
+3
+```
+
+And we can `import` modules:
+
+```bash
+> task = import("core.project.task")
+> task.run("hello")
+hello xmake!
+```
+
+If you want to cancel multiline input, please input character `q`, for example:
+
+```bash
+> for _, v in ipairs({1, 2}) do
+>> print(v)
+>> q <-- cancel multiline and clear previous input
+> 1 + 2
+3
+```
+
+#### Generate IDE Project Files
+
+##### Generate Makefile
+
+```bash
+$ xmake project -k makefile
+```
+
+##### Generate compiler_commands
+
+We can export the compilation commands info of all source files and it is JSON compilation database format.
+
+```console
+$ xmake project -k compile_commands
+```
+
+The the content of the output file:
+
+```
+[
+ { "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" },
+ ...
+]
+
+```
+
+Please see [JSONCompilationDatabase](#https://clang.llvm.org/docs/JSONCompilationDatabase.html) if need known more info about `compile_commands`.
+
+##### Generate VisualStudio Project
+
+```bash
+$ xmake project -k [vs2008|vs2013|vs2015|..]
+```
+
+v2.1.2 or later, it supports multi-mode and multi-architecture generation for vs201x project.
+
+For example:
+
+```bash
+$ xmake project -k vs2017 -m "debug,release"
+```
+
+It will generate four project configurations: `debug|x86`, `debug|x64`, `release|x86`, `release|x64`.
+
+Or you can set modes to `xmake.lua`:
+
+```lua
+set_modes("debug", "release")
+```
+
+Then, we run the following command:
+
+```bash
+$ xmake project -k vs2017
+```
+
+The effect is same.
+
+#### Generate Doxygen Document
+
+Please ensure that the doxygen tool has been installed first.
+
+```bash
+$ xmake doxygen
+```
+
+## More Plugins
+
+Please download and install from the plugins repository [xmake-plugins](https://github.com/tboox/xmake-plugins).
+
+#### Convert .app to .ipa
+
+```bash
+$ xmake app2ipa --icon=/xxx.png /xxx/ios.app -o /xxx.ios.ipa
+```
diff --git a/zh/README.md b/zh/README.md
new file mode 100644
index 00000000..2e7a4c69
--- /dev/null
+++ b/zh/README.md
@@ -0,0 +1,645 @@
+---
+nav: zh
+search: zh
+---
+
+<p>
+<div align="center">
+ <a href="http://xmake.io/cn">
+ <img width="200" heigth="200" src="http://tboox.org/static/img/xmake/logo256c.png">
+ </a>
+
+ <h1>xmake</h1>
+
+ <div>
+ <a href="https://travis-ci.org/tboox/xmake">
+ <img src="https://img.shields.io/travis/tboox/xmake/master.svg?style=flat-square" alt="travis-ci" />
+ </a>
+ <a href="https://ci.appveyor.com/project/waruqi/xmake/branch/master">
+ <img src="https://img.shields.io/appveyor/ci/waruqi/xmake/master.svg?style=flat-square" alt="appveyor-ci" />
+ </a>
+ <a href="https://codecov.io/gh/tboox/xmake">
+ <img src="https://img.shields.io/codecov/c/github/tboox/xmake/master.svg?style=flat-square" alt="Coverage" />
+ </a>
+ <a href="https://github.com/tboox/xmake/releases">
+ <img src="https://img.shields.io/github/release/tboox/xmake.svg?style=flat-square" alt="Github All Releases" />
+ </a>
+ <a href="https://aur.archlinux.org/packages/xmake">
+ <img src="https://img.shields.io/aur/votes/xmake.svg?style=flat-square" alt="AUR votes" />
+ </a>
+ </div>
+ <div>
+ <a href="https://github.com/tboox/xmake/blob/master/LICENSE.md">
+ <img src="https://img.shields.io/github/license/tboox/xmake.svg?colorB=f48041&style=flat-square" alt="license" />
+ </a>
+ <a href="https://gitter.im/tboox/tboox?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge">
+ <img src="https://img.shields.io/gitter/room/tboox/tboox.svg?style=flat-square&colorB=96c312" alt="Gitter" />
+ </a>
+ <a href="http://xmake.io/cn/pages/donation.html#donate">
+ <img src="https://img.shields.io/badge/donate-us-orange.svg?style=flat-square" alt="Donate" />
+ </a>
+ </div>
+
+ <p>一个基于Lua的轻量级跨平台自动构建工具</p>
+</div>
+</p>
+
+## 简介
+
+XMake是一个基于Lua的轻量级跨平台自动构建工具,支持在各种主流平台上构建项目
+
+xmake的目标是开发者更加关注于项目本身开发,简化项目的描述和构建,并且提供平台无关性,使得一次编写,随处构建
+
+它跟cmake、automake、premake有点类似,但是机制不同,它默认不会去生成IDE相关的工程文件,采用直接编译,并且更加的方便易用
+采用lua的工程描述语法更简洁直观,支持在大部分常用平台上进行构建,以及交叉编译
+
+并且xmake提供了创建、配置、编译、打包、安装、卸载、运行等一些actions,使得开发和构建更加的方便和流程化。
+
+不仅如此,它还提供了许多更加高级的特性,例如插件扩展、脚本宏记录、批量打包、自动文档生成等等。。
+
+## 安装
+
+#### Master版本
+
+##### 使用curl
+
+```bash
+bash <(curl -fsSL https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh)
+```
+
+##### 使用wget
+
+```bash
+bash <(wget https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh -O -)
+```
+
+##### 使用powershell
+
+```bash
+Invoke-Expression (Invoke-Webrequest 'https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.ps1' -UseBasicParsing).Content
+```
+
+#### Windows
+
+1. 从 [Releases](https://github.com/tboox/xmake/releases) 上下载windows安装包
+2. 运行安装程序 xmake-[version].exe
+
+#### MacOS
+
+```bash
+$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
+$ brew install xmake
+```
+
+或者:
+
+1. 从 [Releases](https://github.com/tboox/xmake/releases) 上下载pkg安装包
+2. 双击运行
+
+或者安装master版本:
+
+```bash
+# 使用homebrew安装master版本
+$ brew install xmake --HEAD
+
+# 或者直接调用shell下载安装
+$ bash <(curl -fsSL https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh)
+```
+
+#### Linux
+
+在archlinux上安装:
+
+```bash
+$ yaourt xmake
+```
+
+在ubuntu上安装:
+
+```bash
+$ sudo add-apt-repository ppa:tboox/xmake
+$ sudo apt-get update
+$ sudo apt-get install xmake
+```
+
+或者手动添加包源:
+
+```
+deb http://ppa.launchpad.net/tboox/xmake/ubuntu yakkety main
+deb-src http://ppa.launchpad.net/tboox/xmake/ubuntu yakkety main
+```
+
+然后执行:
+
+```bash
+$ sudo apt-get update
+$ sudo apt-get install xmake
+```
+
+或者下载deb包来安装:
+
+1. 从 [Releases](https://github.com/tboox/xmake/releases) 上下载deb安装包
+2. 运行: `dpkg -i xmake-xxxx.deb`
+
+在`redhat/centos`上安装:
+
+1. 从 [Releases](https://github.com/tboox/xmake/releases) 上下载rpm安装包
+2. 运行: `yum install xmake-xxx.rpm --nogpgcheck`
+
+#### 编译安装
+
+```bash
+$ git clone git@github.com:waruqi/xmake.git
+$ cd ./xmake
+$ ./scripts/get.sh __local__
+```
+
+## 快速开始
+
+[![asciicast](https://asciinema.org/a/133693.png)](https://asciinema.org/a/133693)
+
+#### 创建工程
+
+创建一个名叫`hello`的`c`控制台工程:
+
+```bash
+$ xmake create -l c -P ./hello
+```
+
+执行完后,将会生成一个简单工程结构:
+
+```
+hello
+├── src
+│   └── main.c
+└── xmake.lua
+```
+
+其中`xmake.lua`是工程描述文件,内容非常简单,告诉xmake添加`src`目录下的所有`.c`源文件:
+
+```lua
+target("hello")
+ set_kind("binary")
+ add_files("src/*.c")
+```
+
+目前支持的语言如下:
+
+* c/c++
+* objc/c++
+* asm
+* swift
+* dlang
+* golang
+* rust
+
+<p class="tip">
+ 如果你想了解更多参数选项,请运行: `xmake create --help`
+</p>
+
+#### 构建工程
+
+```bash
+$ xmake
+```
+
+#### 运行程序
+
+```bash
+$ xmake run hello
+```
+
+#### 调试程序
+
+```bash
+$ xmake run -d hello
+```
+
+xmake将会使用系统自带的调试器去加载程序运行,目前支持:lldb, gdb, windbg, vsjitdebugger, ollydbg 等各种调试器。
+
+```bash
+[lldb]$target create "build/hello"
+Current executable set to 'build/hello' (x86_64).
+[lldb]$b main
+Breakpoint 1: where = hello`main, address = 0x0000000100000f50
+[lldb]$r
+Process 7509 launched: '/private/tmp/hello/build/hello' (x86_64)
+Process 7509 stopped
+* thread #1: tid = 0x435a2, 0x0000000100000f50 hello`main, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
+ frame #0: 0x0000000100000f50 hello`main
+hello`main:
+-> 0x100000f50 <+0>: pushq %rbp
+ 0x100000f51 <+1>: movq %rsp, %rbp
+ 0x100000f54 <+4>: leaq 0x2b(%rip), %rdi ; "hello world!"
+ 0x100000f5b <+11>: callq 0x100000f64 ; symbol stub for: puts
+[lldb]$
+```
+
+<p class="tip">
+ 你也可以使用简写的命令行选项,例如: `xmake r` 或者 `xmake run`
+</p>
+
+## 配置
+
+通过`xmake f|config`配置命令,设置构建前的相关配置信息,详细参数选项,请运行: `xmake f --help`。
+
+<p class="tip">
+ 你可以使用命令行缩写来简化输入,也可以使用全名,例如: <br>
+ `xmake f` 或者 `xmake config`.<br>
+ `xmake f -p linux` 或者 `xmake config --plat=linux`.
+</p>
+
+#### 目标平台
+
+##### 主机平台
+
+```bash
+$ xmake
+```
+
+<p class="tip">
+ xmake将会自动探测当前主机平台,默认自动生成对应的目标程序。
+</p>
+
+##### Linux
+
+```bash
+$ xmake f -p linux [-a i386|x86_64]
+$ xmake
+```
+
+##### Android
+
+```bash
+$ xmake f -p android --ndk=~/files/android-ndk-r10e/ [-a armv5te|armv6|armv7-a|armv8-a|arm64-v8a]
+$ xmake
+```
+
+如果要手动指定ndk中具体某个工具链,而不是使用默认检测的配置,可以通过[--toolchains](#-toolchains)来设置,例如:
+
+```bash
+$ xmake f -p android --ndk=~/files/android-ndk-r10e/ -a arm64-v8a --toolchains=~/files/android-ndk-r10e/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin
+```
+
+[--toolchains](#-toolchains)主要用于设置选择编译工具的具体bin目录,这个的使用跟[交叉编译](#交叉编译)中的[--toolchains](#-toolchains)的行为是一致的。
+
+<p class="tip">
+如果手动设置了`toolchains`的bin目录,没有通过检测,可以看下是否`--arch=`参数没有匹配对。
+</p>
+
+##### iPhoneOS
+
+```bash
+$ xmake f -p iphoneos [-a armv7|armv7s|arm64|i386|x86_64]
+$ xmake
+```
+
+##### Windows
+
+```bash
+$ xmake f -p windows [-a x86|x64]
+$ xmake
+```
+
+##### Mingw
+
+```bash
+$ xmake f -p mingw --sdk=/usr/local/i386-mingw32-4.3.0/ [-a i386|x86_64]
+$ xmake
+```
+
+##### Apple WatchOS
+
+```bash
+$ xmake f -p watchos [-a i386|armv7k]
+$ xmake
+```
+
+##### 交叉编译
+
+linux平台的交叉编译:
+
+```bash
+$ xmake f -p linux --sdk=/usr/local/arm-linux-gcc/ [--toolchains=/sdk/bin] [--cross=arm-linux-]
+$ xmake
+```
+
+其他平台的交叉编译:
+
+```bash
+$ xmake f -p cross --sdk=/usr/local/arm-xxx-gcc/ [--toolchains=/sdk/bin] [--cross=arm-linux-]
+$ xmake
+```
+
+如果不关心实际的平台名,只想交叉编译,可以直接用上面的命令,如果需要通过`is_plat("myplat")`判断自己的平台逻辑,则:
+
+```bash
+$ xmake f -p myplat --sdk=/usr/local/arm-xxx-gcc/ [--toolchains=/sdk/bin] [--cross=arm-linux-]
+$ xmake
+```
+
+其中:
+
+| 参数名 | 描述 |
+| ---------------------------- | -------------------------------- |
+| [--sdk](#-sdk) | 设置交叉工具链的sdk根目录 |
+| [--toolchains](#-toolchains) | 设置工具链bin目录 |
+| [--cross](#-cross) | 设置交叉工具链工具前缀 |
+| [--as](#-as) | 设置`asm`汇编器 |
+| [--cc](#-cc) | 设置`c`编译器 |
+| [--cxx](#-cxx) | 设置`c++`编译器 |
+| [--mm](#-mm) | 设置`objc`编译器 |
+| [--mxx](#-mxx) | 设置`objc++`编译器 |
+| [--sc](#-sc) | 设置`swift`编译器 |
+| [--gc](#-gc) | 设置`golang`编译器 |
+| [--dc](#-dc) | 设置`dlang`编译器 |
+| [--rc](#-rc) | 设置`rust`编译器 |
+| [--ld](#-ld) | 设置`c/c++/objc/asm`链接器 |
+| [--sh](#-sh) | 设置`c/c++/objc/asm`共享库链接器 |
+| [--ar](#-ar) | 设置`c/c++/objc/asm`静态库归档器 |
+| [--sc-ld](#-sc-ld) | 设置`swift`链接器 |
+| [--sc-sh](#-sc-sh) | 设置`swift`共享库链接器 |
+| [--gc-ld](#-gc-ld) | 设置`golang`链接器 |
+| [--gc-ar](#-gc-ar) | 设置`golang`静态库归档器 |
+| [--dc-ld](#-dc-ld) | 设置`dlang`链接器 |
+| [--dc-sh](#-dc-sh) | 设置`dlang`共享库链接器 |
+| [--dc-ar](#-dc-ar) | 设置`dlang`静态库归档器 |
+| [--rc-ld](#-rc-ld) | 设置`rust`链接器 |
+| [--rc-sh](#-rc-sh) | 设置`rust`共享库链接器 |
+| [--rc-ar](#-rc-ar) | 设置`rust`静态库归档器 |
+| [--asflags](#-asflags) | 设置`asm`汇编编译选项 |
+| [--cflags](#-cflags) | 设置`c`编译选项 |
+| [--cxflags](#-cxflags) | 设置`c/c++`编译选项 |
+| [--cxxflags](#-cxxflags) | 设置`c++`编译选项 |
+| [--mflags](#-mflags) | 设置`objc`编译选项 |
+| [--mxflags](#-mxflags) | 设置`objc/c++`编译选项 |
+| [--mxxflags](#-mxxflags) | 设置`objc++`编译选项 |
+| [--scflags](#-scflags) | 设置`swift`编译选项 |
+| [--gcflags](#-gcflags) | 设置`golang`编译选项 |
+| [--dcflags](#-dcflags) | 设置`dlang`编译选项 |
+| [--rcflags](#-rcflags) | 设置`rust`编译选项 |
+| [--ldflags](#-ldflags) | 设置链接选项 |
+| [--shflags](#-shflags) | 设置共享库链接选项 |
+| [--arflags](#-arflags) | 设置静态库归档选项 |
+
+<p class="tip">
+如果你想要了解更多参数选项,请运行: `xmake f --help`。
+</p>
+
+###### --sdk
+
+- 设置交叉工具链的sdk根目录
+
+大部分情况下,都不需要配置很复杂的toolchains前缀,例如:`arm-linux-` 什么的
+
+只要这个工具链的sdk目录满足如下结构(大部分的交叉工具链都是这个结构):
+
+```
+/home/toolchains_sdkdir
+ - bin
+ - arm-linux-gcc
+ - arm-linux-ld
+ - ...
+ - lib
+ - libxxx.a
+ - include
+ - xxx.h
+```
+
+那么,使用xmake进行交叉编译的时候,只需要进行如下配置和编译:
+
+```bash
+$ xmake f -p linux --sdk=/home/toolchains_sdkdir
+$ xmake
+```
+
+这个时候,xmake会去自动探测,gcc等编译器的前缀名:`arm-linux-`,并且编译的时候,也会自动加上`链接库`和`头文件`的搜索选项,例如:
+
+```
+-I/home/toolchains_sdkdir/include -L/home/toolchains_sdkdir/lib
+```
+
+这些都是xmake自动处理的,不需要手动配置他们。。
+
+###### --toolchains
+
+- 设置工具链bin目录
+
+对于不规则工具链目录结构,靠单纯地[--sdk](#-sdk)选项设置,没法完全检测通过的情况下,可以通过这个选项继续附加设置工具链的bin目录位置。
+
+例如:一些特殊的交叉工具链的,编译器bin目录,并不在 `/home/toolchains_sdkdir/bin` 这个位置,而是独立到了 `/usr/opt/bin`
+
+```bash
+$ xmake f -p linux --sdk=/home/toolchains_sdkdir --toolchains=/usr/opt/bin
+$ xmake
+```
+
+###### --cross
+
+- 设置交叉工具链工具前缀
+
+像`aarch64-linux-android-`这种,通常如果你配置了[--sdk](-sdk)或者[--toolchains](-toolchains)的情况下,xmake会去自动检测的,不需要自己手动设置。
+
+但是对于一些极特殊的工具链,一个目录下同时有多个cross前缀的工具bin混在一起的情况,你需要手动设置这个配置,来区分到底需要选用哪个bin。
+
+例如,toolchains的bin目录下同时存在两个不同的编译器:
+
+```
+/opt/bin
+ - armv7-linux-gcc
+ - aarch64-linux-gcc
+```
+
+我们现在想要选用armv7的版本,则配置如下:
+
+```bash
+$ xmake f -p linux --sdk=/usr/toolsdk --toolchains=/opt/bin --cross=armv7-linux-
+```
+
+###### --as
+
+- 设置`asm`汇编器
+
+如果还要继续细分选择编译器,则继续追加相关编译器选项,例如:
+
+```bash
+$ xmake f -p linux --sdk=/user/toolsdk --as=armv7-linux-as
+```
+
+如果存在`AS`环境变量的话,会优先使用当前环境变量中指定的值。
+
+###### --cc
+
+- 设置c编译器
+
+如果还要继续细分选择编译器,则继续追加相关编译器选项,例如:
+
+```bash
+$ xmake f -p linux --sdk=/user/toolsdk --cc=armv7-linux-clang
+```
+
+如果存在`CC`环境变量的话,会优先使用当前环境变量中指定的值。
+
+###### --cxx
+
+- 设置`c++`编译器
+
+如果还要继续细分选择编译器,则继续追加相关编译器选项,例如:
+
+```bash
+$ xmake f -p linux --sdk=/user/toolsdk --cxx=armv7-linux-clang++
+```
+
+如果存在`CXX`环境变量的话,会优先使用当前环境变量中指定的值。
+
+###### --ld
+
+- 设置`c/c++/objc/asm`链接器
+
+如果还要继续细分选择链接器,则继续追加相关编译器选项,例如:
+
+```bash
+$ xmake f -p linux --sdk=/user/toolsdk --ld=armv7-linux-clang++
+```
+
+如果存在`LD`环境变量的话,会优先使用当前环境变量中指定的值。
+
+###### --sh
+
+- 设置`c/c++/objc/asm`共享库链接器
+
+```bash
+$ xmake f -p linux --sdk=/user/toolsdk --sh=armv7-linux-clang++
+```
+
+如果存在`SH`环境变量的话,会优先使用当前环境变量中指定的值。
+
+###### --ar
+
+- 设置`c/c++/objc/asm`静态库归档器
+
+```bash
+$ xmake f -p linux --sdk=/user/toolsdk --ar=armv7-linux-ar
+```
+
+如果存在`AR`环境变量的话,会优先使用当前环境变量中指定的值。
+
+#### 全局配置
+
+我们也可以将一些常用配置保存到全局配置中,来简化频繁地输入:
+
+例如:
+
+```bash
+$ xmake g --ndk=~/files/android-ndk-r10e/
+```
+
+现在,我们重新配置和编译`android`程序:
+
+```bash
+$ xmake f -p android
+$ xmake
+```
+
+以后,就不需要每次重复配置`--ndk=`参数了。
+
+<p class="tip">
+ 每个命令都有其简写,例如: `xmake g` 或者 `xmake global`.<br>
+</p>
+
+#### 清除配置
+
+有时候,配置出了问题编译不过,或者需要重新检测各种依赖库和接口,可以加上`-c`参数,清除缓存的配置,强制重新检测和配置
+
+```bash
+$ xmake f -c
+$ xmake
+```
+
+或者:
+
+```bash
+$ xmake f -p iphoneos -c
+$ xmake
+```
+
+## 问答
+
+#### 怎样获取更多参数选项信息?
+
+获取主菜单的帮助信息,里面有所有action和plugin的列表描述。
+
+```bash
+$ xmake [-h|--help]
+```
+
+获取配置菜单的帮助信息,里面有所有配置选项的描述信息,以及支持平台、架构列表。
+
+```bash
+$ xmake f [-h|--help]
+```
+
+获取action和plugin命令菜单的帮助信息,里面有所有内置命令和插件任务的参数使用信息。
+
+```bash
+$ xmake [action|plugin] [-h|--help]
+```
+
+例如,获取`run`命令的参数信息:
+
+```bash
+$ xmake run --help
+```
+
+#### 怎样实现静默构建,不输出任何信息?
+
+```bash
+$ xmake [-q|--quiet]
+```
+
+#### 如果xmake运行失败了怎么办?
+
+可以先尝试清除下配置,重新构建下:
+
+```bash
+$ xmake f -c
+$ xmake
+```
+
+如果还是失败了,请加上 `-v` 或者 `--verbose` 选项重新执行xmake后,获取更加详细的输出信息
+
+例如:
+
+```hash
+$ xmake -v
+$ xmake --verbose
+```
+
+并且可以加上 `--backtrace` 选项获取出错时的xmake的调试栈信息, 然后你可以提交这些信息到[issues](https://github.com/tboox/xmake/issues).
+
+```bash
+$ xmake -v --backtrace
+```
+
+## 支持项目
+
+xmake项目属于个人开源项目,它的发展需要您的帮助,如果您愿意支持xmake项目的开发,欢迎为其捐赠,支持它的发展。 🙏 [[支持此项目](https://opencollective.com/xmake#backer)]
+
+<a href="https://opencollective.com/xmake#backers" target="_blank"><img src="https://opencollective.com/xmake/backers.svg?width=890"></a>
+
+## 赞助项目
+
+通过赞助支持此项目,您的logo和网站链接将显示在这里。[[赞助此项目](https://opencollective.com/xmake#sponsor)]
+
+<a href="https://opencollective.com/xmake/sponsor/0/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/0/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/1/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/1/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/2/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/2/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/3/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/3/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/4/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/4/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/5/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/5/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/6/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/6/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/7/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/7/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/8/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/8/avatar.svg"></a>
+<a href="https://opencollective.com/xmake/sponsor/9/website" target="_blank"><img src="https://opencollective.com/xmake/sponsor/9/avatar.svg"></a>
+
+
diff --git a/zh/manual.md b/zh/manual.md
new file mode 100644
index 00000000..6c8fe5e4
--- /dev/null
+++ b/zh/manual.md
@@ -0,0 +1,6835 @@
+---
+nav: zh
+search: zh
+---
+
+## 接口规范
+
+#### 命名规范
+
+接口的命名,是有按照预定义的一些规范来命名的,这样更加方便理解和易于使用,目前命名按照如下一些规则:
+
+| 接口规则 | 描述 |
+| --------------------- | ------------------------------------------------------------ |
+| `is_`前缀的接口 | 表示为条件判断 |
+| `set_`前缀的接口 | 表示为覆盖设置 |
+| `add_`前缀的接口 | 表示为追加设置 |
+| `s`后缀的接口 | 表示支持多值传入,例如:`add_files("*.c", "test.cpp")` |
+| `on_`前缀的接口 | 表示为覆盖内置脚本 |
+| `before_`前缀的接口 | 表示为在内置脚本运行前,执行此脚本 |
+| `after_`前缀的接口 | 表示为在内置脚本运行后,执行此脚本 |
+| `scope("name")`的接口 | 表示为定义一个描述域,例如:`target("xxx")`, `option("xxx")` |
+| 描述域/描述设置 | 建议缩进表示 |
+
+
+## 接口文档
+
+#### 条件判断
+
+条件判断的api,一般用于必须要处理特定平台的编译逻辑的场合。。通常跟lua的if语句配合使用。
+
+| 接口 | 描述 | 支持版本 |
+| ------------------------- | ----------------------------- | -------- |
+| [is_os](#is_os) | 判断当前构建目标的操作系统 | >= 2.0.1 |
+| [is_arch](#is_arch) | 判断当前编译架构 | >= 2.0.1 |
+| [is_plat](#is_plat) | 判断当前编译平台 | >= 2.0.1 |
+| [is_host](#is_host) | 判断当前主机环境操作系统 | >= 2.1.4 |
+| [is_mode](#is_mode) | 判断当前编译模式 | >= 2.0.1 |
+| [is_kind](#is_kind) | 判断当前编译类型 | >= 2.0.1 |
+| [is_option](#is_option) | 判断选项是否启用 | >= 2.0.1 |
+
+##### is_os
+
+###### 判断当前构建目标的操作系统
+
+```lua
+-- 如果当前操作系统是ios
+if is_os("ios") then
+ add_files("src/xxx/*.m")
+end
+```
+
+目前支持的操作系统有:
+
+* windows
+* linux
+* android
+* macosx
+* ios
+
+##### is_arch
+
+###### 判断当前编译架构
+
+用于检测编译配置:`xmake f -a armv7`
+
+```lua
+-- 如果当前架构是x86_64或者i386
+if is_arch("x86_64", "i386") then
+ add_files("src/xxx/*.c")
+end
+
+-- 如果当前平台是armv7, arm64, armv7s, armv7-a
+if is_arch("armv7", "arm64", "armv7s", "armv7-a") then
+ -- ...
+end
+```
+
+如果像上面那样一个个去判断所有arm架构,也许会很繁琐,毕竟每个平台的架构类型很多,xmake提供了类似[add_files](#targetadd_files)中的通配符匹配模式,来更加简洁的进行判断:
+
+```lua
+--如果当前平台是arm平台
+if is_arch("arm*") then
+ -- ...
+end
+```
+
+用`*`就可以匹配所有了。。
+
+##### is_plat
+
+###### 判断当前编译平台
+
+用于检测编译配置:`xmake f -p iphoneos`
+
+```lua
+-- 如果当前平台是android
+if is_plat("android") then
+ add_files("src/xxx/*.c")
+end
+
+-- 如果当前平台是macosx或者iphoneos
+if is_plat("macosx", "iphoneos") then
+ add_mxflags("-framework Foundation")
+ add_ldflags("-framework Foundation")
+end
+```
+
+目前支持的平台有:
+
+* windows
+* cross
+* linux
+* macosx
+* android
+* iphoneos
+* watchos
+
+当然你也可以自己扩展添加自己的平台,甚至直接指定自己的平台名:
+
+```bash
+$ xmake f -p other --sdk=...
+```
+
+如果指定的平台名不存在,就会自动切到`cross`平台进行交叉编译,但是缺可以通过`is_plat("other")`来判断自己的平台逻辑。
+
+##### is_host
+
+###### 判断当前主机环境的操作系统
+
+有些编译平台是可以在多个不同的操作系统进行构建的,例如:android的ndk就支持linux,macOS还有windows环境。
+
+这个时候就可以通过这个接口,区分当前是在哪个系统环境下进行的构建。
+
+```lua
+-- 如果当前主机环境是windows
+if is_host("windows") then
+ add_includes("C:\\includes")
+else
+ add_includes("/usr/includess")
+end
+```
+
+目前支持的主机环境有:
+
+* windows
+* linux
+* macosx
+
+你也可以通过[$(host)](#var-host)内置变量或者[os.host](#os-host)接口,来进行获取
+
+##### is_mode
+
+###### 判断当前编译模式
+
+用于检测编译配置:`xmake f -m debug`
+
+编译模式的类型并不是内置的,可以自由指定,一般指定:`debug`, `release`, `profile` 这些就够用了,当然你也可以在xmake.lua使用其他模式名来判断。
+
+```lua
+-- 如果当前编译模式是debug
+if is_mode("debug") then
+
+ -- 添加DEBUG编译宏
+ add_defines("DEBUG")
+
+ -- 启用调试符号
+ set_symbols("debug")
+
+ -- 禁用优化
+ set_optimize("none")
+
+end
+
+-- 如果是release或者profile模式
+if is_mode("release", "profile") then
+
+ -- 如果是release模式
+ if is_mode("release") then
+
+ -- 隐藏符号
+ set_symbols("hidden")
+
+ -- strip所有符号
+ set_strip("all")
+
+ -- 忽略帧指针
+ add_cxflags("-fomit-frame-pointer")
+ add_mxflags("-fomit-frame-pointer")
+
+ -- 如果是profile模式
+ else
+
+ -- 启用调试符号
+ set_symbols("debug")
+
+ end
+
+ -- 添加扩展指令集
+ add_vectorexts("sse2", "sse3", "ssse3", "mmx")
+end
+```
+
+##### is_kind
+
+###### 判断当前编译类型
+
+判断当前是否编译的是动态库还是静态库,用于检测编译配置:`xmake f -k [static|shared]`
+
+一般用于如下场景:
+
+```lua
+target("test")
+
+ -- 通过配置设置目标的kind
+ set_kind("$(kind)")
+ add_files("src/*c")
+
+ -- 如果当前编译的是静态库,那么添加指定文件
+ if is_kind("static") then
+ add_files("src/xxx.c")
+ end
+```
+
+编译配置的时候,可手动切换,编译类型:
+
+```bash
+# 编译静态库
+$ xmake f -k static
+$ xmake
+```
+
+```bash
+# 编译动态库
+$ xmake f -k shared
+$ xmake
+```
+
+##### is_option
+
+###### 判断选项是否启用
+
+用于检测自定义的编译配置选型:`xmake f --xxxx=y`
+
+如果某个自动检测选项、手动设置选项被启用,那么可以通过`is_option`接口来判断,例如:
+
+```lua
+-- 如果手动启用了xmake f --demo=y 选项
+if is_option("demo") then
+
+ -- 编译demo目录下的代码
+ add_subdirs("src/demo")
+end
+```
+
+#### 全局接口
+
+全局接口影响整个工程描述,被调用后,后面被包含进来的所有子`xmake.lua`都会受影响。
+
+| 接口 | 描述 | 支持版本 |
+| ------------------------------------- | ----------------------------- | -------- |
+| [includes](#includes) | 添加子工程文件和目录 | >= 2.1.5 |
+| [set_modes](#set_modes) | 设置支持的编译模式 | >= 2.1.2 |
+| [set_project](#set_project) | 设置工程名 | >= 2.0.1 |
+| [set_version](#set_version) | 设置工程版本 | >= 2.0.1 |
+| [set_xmakever](#set_xmakever) | 设置最小xmake版本 | >= 2.1.1 |
+| [add_subdirs](#add_subdirs) | 添加子工程目录 | >= 1.0.1 |
+| [add_subfiles](#add_subfiles) | 添加子工程文件 | >= 1.0.1 |
+| [add_moduledirs](#add_moduledirs) | 添加模块目录 | >= 2.1.5 |
+| [add_plugindirs](#add_plugindirs) | 添加插件目录 | >= 2.0.1 |
+| [add_packagedirs](#add_packagedirs) | 添加包目录 | >= 2.0.1 |
+
+##### includes
+
+###### 添加子工程文件和目录
+
+同时支持子工程文件和目录的添加,用于替代[add_subdirs](#add_subdirs)和[add_subfiles](#add_subfiles)接口。
+
+##### set_modes
+
+###### 设置支持的编译模式
+
+这个是可选接口,一般情况下不需要设置,目前仅用于对工程增加更加细致的描述信息,方便vs工程的多模式生成,以及其他xmake插件中获取模式信息。
+
+例如:
+
+```lua
+set_modes("debug", "release")
+```
+
+如果设置了这个,xmake就知道当前工程支持哪些编译模式,这样生成vs工程文件的时候,只需要:
+
+```bash
+$ xmake project -k vs2017
+```
+
+不再需要额外手动指定需要的编译模式了,此外其他一些想要获取工程信息的插件,也许也会需要这些设置信息。
+
+<p class="tip">
+当然,对于[is_mode](#is_mode)接口,`set_modes`不是必须的,就算不设置,也是可以通过`is_mode`正常判断当前的编译模式。
+</p>
+
+##### set_project
+
+###### 设置工程名
+
+设置工程名,在doxygen自动文档生成插件、工程文件生成插件中会用到,一般设置在xmake.lua的最开头,当然放在其他地方也是可以的
+
+```lua
+-- 设置工程名
+set_project("tbox")
+
+-- 设置工程版本
+set_version("1.5.1")
+```
+
+##### set_version
+
+###### 设置工程版本
+
+设置项目版本,可以放在xmake.lua任何地方,一般放在最开头,例如:
+
+```lua
+set_version("1.5.1")
+```
+
+以tbox为例,如果调用[set_config_header](#targetset_config_header)设置了`config.h`,那么会自动生成如下宏:
+
+```c
+// version
+#define TB_CONFIG_VERSION "1.5.1"
+#define TB_CONFIG_VERSION_MAJOR 1
+#define TB_CONFIG_VERSION_MINOR 5
+#define TB_CONFIG_VERSION_ALTER 1
+#define TB_CONFIG_VERSION_BUILD 201510220917
+```
+
+2.1.7版本支持buildversion的配置:
+
+```lua
+set_version("1.5.1", {build = "%Y%m%d%H%M"})
+```
+
+##### set_xmakever
+
+###### 设置最小xmake版本
+
+用于处理xmake版本兼容性问题,如果项目的`xmake.lua`,通过这个接口设置了最小xmake版本支持,那么用户环境装的xmake低于要求的版本,就会提示错误。
+
+一般情况下,建议默认对其进行设置,这样对用户比较友好,如果`xmake.lua`中用到了高版本的api接口,用户那边至少可以知道是否因为版本不对导致的构建失败。
+
+设置如下:
+
+```lua
+-- 设置最小版本为:2.1.0,低于此版本的xmake编译此工程将会提示版本错误信息
+set_xmakever("2.1.0")
+```
+
+##### add_subdirs
+
+###### 添加子工程目录
+
+每个子工程对应一个`xmake.lua`的工程描述文件。
+
+虽然一个`xmake.lua`也可以描述多个子工程模块,但是如果工程越来越大,越来越复杂,适当的模块化是很有必要的。。
+
+这就需要`add_subdirs`了,将每个子模块放到不同目录中,并为其建立一个新的`xmake.lua`独立去维护它,例如:
+
+```
+./tbox
+├── src
+│ ├── demo
+│ │ └── xmake.lua (用来描述测试模块)
+│ └── tbox
+│ └── xmake.lua(用来描述libtbox库模块)
+└── xmake.lua(用该描述通用配置信息,以及对子模块的维护)
+````
+
+在`tbox/xmake.lua`中通过`add_subdirs`将拥有`xmale.lua`的子模块的目录,添加进来,就可以了,例如:
+
+```lua
+-- 添加libtbox库模块目录
+add_subdirs("src/tbox")
+
+-- 如果xmake f --demo=y,启用了demo模块,那么包含demo目录
+if is_option("demo") then
+ add_subdirs("src/demo")
+end
+```
+
+默认情况下,xmake会去编译在所有xmake.lua中描述的所有target目标,如果只想编译指定目标,可以执行:
+
+```bash
+# 仅仅编译tbox库模块
+$ xmake build tbox
+```
+
+需要注意的是,每个子`xmake.lua`中所有的路径设置都是相对于当前这个子`xmake.lua`所在的目录的,都是相对路径,这样方便维护
+
+##### add_subfiles
+
+###### 添加子工程文件
+
+`add_subfiles`的作用与[add_subdirs](#add_subdirs)类似,唯一的区别就是:这个接口直接指定`xmake.lua`文件所在的路径,而不是目录,例如:
+
+```lua
+add_subfiles("src/tbox/xmake.lua")
+```
+
+##### add_moduledirs
+
+###### 添加模块目录
+
+xmake内置的扩展模块都在`xmake/modules`目录下,可通过[import](#import)来导入他们,如果自己在工程里面实现了一些扩展模块,
+可以放置在这个接口指定的目录下,import也就会能找到,并且优先进行导入。
+
+例如定义一个`find_openssl.lua`的扩展模块,用于扩展内置的[lib.detect.find_package](#detect-find_package)接口,则只需要将它放置在:
+
+```
+projectdir/xmake/modules/detect/packages/find_openssl.lua
+```
+
+然后在工程`xmake.lua`下指定这个模块目录,`find_package`就可以自动找到了:
+
+```lua
+add_moduledirs("projectdir/xmake/modules")
+```
+
+##### add_plugindirs
+
+###### 添加插件目录
+
+xmake内置的插件都是放在`xmake/plugins`目录下,但是对于用户自定义的一些特定工程的插件,如果不想放置在xmake安装目录下,那么可以在`xmake.lua`中进行配置指定的其他插件路径。
+
+```lua
+-- 将当前工程下的plugins目录设置为自定义插件目录
+add_plugindirs("$(projectdir)/plugins")
+```
+
+这样,xmake在编译此工程的时候,也就加载这些插件。
+
+##### add_packagedirs
+
+###### 添加包目录
+
+通过设置依赖包目录,可以方便的集成一些第三方的依赖库,以tbox工程为例,其包目录如下:
+
+```
+tbox.pkg
+- base.pkg
+- zlib.pkg
+- polarssl.pkg
+- openssl.pkg
+- mysql.pkg
+- pcre.pkg
+- ...
+```
+
+如果要让当前工程识别加载这些包,首先要指定包目录路径,例如:
+
+```lua
+add_packagedirs("pkg")
+```
+
+指定好后,就可以在target作用域中,通过[add_packages](#add_packages)接口,来添加集成包依赖了,例如:
+
+```lua
+target("tbox")
+ add_packages("zlib", "polarssl", "pcre", "mysql")
+```
+
+#### 工程目标
+
+定义和设置子工程模块,每个`target`对应一个子工程,最后会生成一个目标程序,有可能是可执行程序,也有可能是库模块。
+
+<p class="tip">
+target的接口,都是可以放置在target外面的全局作用域中的,如果在全局中设置,那么会影响所有子工程target。
+</p>
+
+例如:
+
+```lua
+-- 会同时影响test和test2目标
+add_defines("DEBUG")
+
+target("test")
+ add_files("*.c")
+
+target("test2")
+ add_files("*.c")
+```
+
+<p class="tip">
+`target`域是可以重复进入来实现分离设置的。
+</p>
+
+
+| 接口 | 描述 | 支持版本 |
+| --------------------------------------------- | ------------------------------------ | -------- |
+| [target](#target) | 定义工程目标 | >= 1.0.1 |
+| [target_end](#target_end) | 结束定义工程目标 | >= 2.1.1 |
+| [set_kind](#targetset_kind) | 设置目标编译类型 | >= 1.0.1 |
+| [set_strip](#targetset_strip) | 设置是否strip信息 | >= 1.0.1 |
+| [set_default](#targetset_default) | 设置是否为默认构建安装目标 | >= 2.1.3 |
+| [set_options](#targetset_options) | 设置关联选项 | >= 1.0.1 |
+| [set_symbols](#targetset_symbols) | 设置符号信息 | >= 1.0.1 |
+| [set_basename](#targetset_basename) | 设置目标文件名 | >= 2.1.2 |
+| [set_warnings](#targetset_warnings) | 设置警告级别 | >= 1.0.1 |
+| [set_optimize](#targetset_optimize) | 设置优化级别 | >= 1.0.1 |
+| [set_languages](#targetset_languages) | 设置代码语言标准 | >= 1.0.1 |
+| [set_headerdir](#targetset_headerdir) | 设置头文件安装目录 | >= 1.0.1 |
+| [set_targetdir](#targetset_targetdir) | 设置生成目标文件目录 | >= 1.0.1 |
+| [set_objectdir](#targetset_objectdir) | 设置对象文件生成目录 | >= 1.0.1 |
+| [on_load](#targeton_load) | 自定义目标加载脚本 | >= 2.1.5 |
+| [on_build](#targeton_build) | 自定义编译脚本 | >= 2.0.1 |
+| [on_clean](#targeton_clean) | 自定义清理脚本 | >= 2.0.1 |
+| [on_package](#targeton_package) | 自定义打包脚本 | >= 2.0.1 |
+| [on_install](#targeton_install) | 自定义安装脚本 | >= 2.0.1 |
+| [on_uninstall](#targeton_uninstall) | 自定义卸载脚本 | >= 2.0.1 |
+| [on_run](#targeton_run) | 自定义运行脚本 | >= 2.0.1 |
+| [before_build](#targetbefore_build) | 在构建之前执行一些自定义脚本 | >= 2.0.1 |
+| [before_clean](#targetbefore_clean) | 在清除之前执行一些自定义脚本 | >= 2.0.1 |
+| [before_package](#targetbefore_package) | 在打包之前执行一些自定义脚本 | >= 2.0.1 |
+| [before_install](#targetbefore_install) | 在安装之前执行一些自定义脚本 | >= 2.0.1 |
+| [before_uninstall](#targetbefore_uninstall) | 在卸载之前执行一些自定义脚本 | >= 2.0.1 |
+| [before_run](#targetbefore_run) | 在运行之前执行一些自定义脚本 | >= 2.0.1 |
+| [after_build](#targetafter_build) | 在构建之后执行一些自定义脚本 | >= 2.0.1 |
+| [after_clean](#targetafter_clean) | 在清除之后执行一些自定义脚本 | >= 2.0.1 |
+| [after_package](#targetafter_package) | 在打包之后执行一些自定义脚本 | >= 2.0.1 |
+| [after_install](#targetafter_install) | 在安装之后执行一些自定义脚本 | >= 2.0.1 |
+| [after_uninstall](#targetafter_uninstall) | 在卸载之后执行一些自定义脚本 | >= 2.0.1 |
+| [after_run](#targetafter_run) | 在运行之后执行一些自定义脚本 | >= 2.0.1 |
+| [set_config_h](#targetset_config_h) | 设置自动生成的配置头文件路径 | >= 1.0.1 < 2.1.5 已废弃 |
+| [set_config_h_prefix](#targetset_config_h) | 设置自动生成的头文件中宏定义命名前缀 | >= 1.0.1 < 2.1.5 已废弃 |
+| [set_config_header](#targetset_config_header) | 设置自动生成的配置头文件路径和前缀 | >= 2.1.5 |
+| [set_pcheader](#targetset_pcheader) | 设置c预编译头文件 | >= 2.1.5 |
+| [set_pcxxheader](#targetset_pcxxheader) | 设置c++预编译头文件 | >= 2.1.5 |
+| [add_deps](#targetadd_deps) | 添加子工程目标依赖 | >= 1.0.1 |
+| [add_links](#targetadd_links) | 添加链接库名 | >= 1.0.1 |
+| [add_files](#targetadd_files) | 添加源代码文件 | >= 1.0.1 |
+| [add_headers](#targetadd_headers) | 添加安装的头文件 | >= 1.0.1 |
+| [add_linkdirs](#targetadd_linkdirs) | 添加链接库搜索目录 | >= 1.0.1 |
+| [add_rpathdirs](#targetadd_rpathdirs) | 添加运行时候动态链接库搜索目录 | >= 2.1.3 |
+| [add_includedirs](#targetadd_includedirs) | 添加头文件搜索目录 | >= 1.0.1 |
+| [add_defines](#targetadd_defines) | 添加宏定义 | >= 1.0.1 |
+| [add_undefines](#targetadd_undefines) | 取消宏定义 | >= 1.0.1 |
+| [add_defines_h](#targetadd_defines_h) | 添加宏定义到头文件 | >= 1.0.1 |
+| [add_undefines_h](#targetadd_undefines_h) | 取消宏定义到头文件 | >= 1.0.1 |
+| [add_cflags](#targetadd_cflags) | 添加c编译选项 | >= 1.0.1 |
+| [add_cxflags](#targetadd_cxflags) | 添加c/c++编译选项 | >= 1.0.1 |
+| [add_cxxflags](#targetadd_cxxflags) | 添加c++编译选项 | >= 1.0.1 |
+| [add_mflags](#targetadd_mflags) | 添加objc编译选项 | >= 1.0.1 |
+| [add_mxflags](#targetadd_mxflags) | 添加objc/objc++编译选项 | >= 1.0.1 |
+| [add_mxxflags](#targetadd_mxxflags) | 添加objc++编译选项 | >= 1.0.1 |
+| [add_scflags](#targetadd_scflags) | 添加swift编译选项 | >= 2.0.1 |
+| [add_asflags](#targetadd_asflags) | 添加汇编编译选项 | >= 2.0.1 |
+| [add_gcflags](#targetadd_gcflags) | 添加go编译选项 | >= 2.1.1 |
+| [add_ldflags](#targetadd_ldflags) | 添加链接选项 | >= 1.0.1 |
+| [add_arflags](#targetadd_arflags) | 添加静态库归档选项 | >= 1.0.1 |
+| [add_shflags](#targetadd_shflags) | 添加动态库链接选项 | >= 1.0.1 |
+| [add_cfunc](#targetadd_cfunc) | 添加单个c库函数检测 | >= 2.0.1 |
+| [add_cxxfunc](#targetadd_cxxfunc) | 添加单个c++库函数检测 | >= 2.0.1 |
+| [add_cfuncs](#targetadd_cfuncs) | 添加c库函数检测 | >= 2.0.1 |
+| [add_cxxfuncs](#targetadd_cxxfuncs) | 添加c++库函数接口 | >= 2.0.1 |
+| [add_packages](#targetadd_packages) | 添加包依赖 | >= 2.0.1 |
+| [add_options](#targetadd_options) | 添加关联选项 | >= 2.0.1 |
+| [add_languages](#targetadd_languages) | 添加语言标准 | >= 1.0.1 |
+| [add_vectorexts](#targetadd_vectorexts) | 添加向量扩展指令 | >= 1.0.1 |
+| [add_frameworks](#targetadd_frameworks) | 添加链接框架 | >= 2.1.1 |
+| [add_frameworkdirs](#targetadd_frameworkdirs) | 添加链接框架的搜索目录 | >= 2.1.5 |
+
+##### target
+
+###### 定义工程目标
+
+定义一个新的控制台工程目标,工程名为`test`,最后生成的目标名也是`test`。
+
+```lua
+target("test")
+ set_kind("binary")
+ add_files("src/*.c")
+```
+
+可以重复调用这个api,进入target域修改设置
+
+```lua
+-- 定义目标demo,并进入demo设置模式
+target("demo")
+ set_kind("binary")
+ add_files("src/demo.c")
+
+-- 定义和设置其他目标
+target("other")
+ ...
+
+-- 重新进入demo目标域,添加test.c文件
+target("demo")
+ add_files("src/test.c")
+```
+
+<p class="tip">
+所有根域的设置,会全局影响所有target目标,但是不会影响option的定义。
+</p>
+
+```lua
+-- 在根域对所有target添加-DDEBUG的宏定义,影响所有target(demo和test都会加上此宏定义)
+add_defines("DEBUG")
+
+target("demo")
+ set_kind("binary")
+ add_files("src/demo.c")
+
+target("test")
+ set_kind("binary")
+ add_files("src/test.c")
+```
+
+##### target_end
+
+###### 结束定义工程目标
+
+这是一个可选的api,如果不调用,那么`target("xxx")`之后的所有设置都是针对这个target进行的,除非进入其他`target`, `option`, `task`域。
+
+如果想设置完当前`target`后,显示离开`target`域,进入根域设置,那么可以通过这个api才操作,例如:
+
+```lua
+target("test")
+ set_kind("static")
+ add_files("src/*.c")
+target_end()
+
+-- 此处已在根域
+-- ...
+```
+
+如果不调用这个api的话:
+
+```lua
+target("test")
+ set_kind("static")
+ add_files("src/*.c")
+
+-- 此处还在上面target域中,之后的设置还是针对test进行的设置
+-- ...
+
+-- 这个时候才离开test,进入另外一个target域中
+target("test2")
+ ...
+```
+
+##### target:set_kind
+
+###### 设置目标编译类型
+
+设置目标类型,目前支持的类型有:
+
+| 值 | 描述 |
+| ------ | -----------|
+| binary | 二进制程序 |
+| static | 静态库程序 |
+| shared | 动态库程序 |
+
+```lua
+target("demo")
+ set_kind("binary")
+```
+
+##### target:set_strip
+
+###### 设置是否strip信息
+
+设置当前目标的strip模式,目前支持一下模式:
+
+| 值 | 描述 |
+| ------ | ----------------------------------------- |
+| debug | 链接的时候,strip掉调试符号 |
+| all | 链接的时候,strip掉所有符号,包括调试符号 |
+
+这个api一般在release模式下使用,可以生成更小的二进制程序。。
+
+```lua
+target("xxxx")
+ set_strip("all")
+```
+
+<p class="tip">
+这个api不一定非得在target之后使用,如果没有target指定,那么将会设置到全局模式。。
+</p>
+
+##### target:set_default
+
+###### 设置是否为默认构建安装目标
+
+这个接口用于设置给定工程目标是否作为默认构建,如果没有调用此接口进行设置,那么这个目标就是默认被构建的,例如:
+
+```lua
+target("test1")
+ set_default(false)
+
+target("test2")
+ set_default(true)
+
+target("test3")
+ ...
+```
+
+上述代码的三个目标,在执行`xmake`, `xmake install`, `xmake package`, `xmake run`等命令的时候,如果不指定目标名,那么:
+
+| 目标名 | 行为 |
+| ------ | -------------------------------- |
+| test1 | 不会被默认构建、安装、打包和运行 |
+| test2 | 默认构建、安装、打包和运行 |
+| test3 | 默认构建、安装、打包和运行 |
+
+通过上面的例子,可以看到默认目标可以设置多个,运行的时候也会依次运行。
+
+<p class="tip">
+ 需要注意的是,`xmake uninstall`和`xmake clean`命令不受此接口设置影响,因为用户大部分情况下都是喜欢清除和卸载所有。
+</p>
+
+如果不想使用默认的目标,那么可以手动指定需要构建安装的目标:
+
+```bash
+$ xmake build targetname
+$ xmake install targetname
+```
+
+如果要强制构建安装所有目标,可以传入`[-a|--all]`参数:
+
+```bash
+$ xmake build [-a|--all]
+$ xmake install [-a|--all]
+```
+
+##### target:set_options
+
+###### 设置关联选项
+
+添加选项依赖,如果通过[option](#option)接口自定义了一些选项,那么只有在指定`target`目标域下,添加此选项,才能进行关联生效。
+
+```lua
+-- 定义一个hello选项
+option("hello")
+ set_default(false)
+ set_showmenu(true)
+ add_defines("HELLO_ENABLE")
+
+target("test")
+ -- 如果hello选项被启用了,这个时候就会将-DHELLO_ENABLE宏应用到test目标上去
+ set_options("hello")
+```
+
+<p class="warning">
+只有调用`set_options`进行关联生效后,[option](#option) 中定义的一些设置才会影响到此`target`目标,例如:宏定义、链接库、编译选项等等
+</p>
+
+##### target:set_symbols
+
+###### 设置符号信息
+
+设置目标的符号模式,如果当前没有定义target,那么将会设置到全局状态中,影响所有后续的目标。
+
+目前主要支持一下几个级别:
+
+| 值 | 描述 |
+| ------ | ---------------------- |
+| debug | 添加调试符号 |
+| hidden | 设置符号不可见 |
+
+这两个值也可以同时被设置,例如:
+
+```lua
+-- 添加调试符号, 设置符号不可见
+set_symbols("debug", "hidden")
+```
+
+如果没有调用这个api,默认是禁用调试符号的。。
+
+##### target:set_basename
+
+###### 设置目标文件名
+
+默认情况下,生成的目标文件名基于`target("name")`中配置的值,例如:
+
+```lua
+-- 目标文件名为:libxxx.a
+target("xxx")
+ set_kind("static")
+
+-- 目标文件名为:libxxx2.so
+target("xxx2")
+ set_kind("shared")
+```
+
+默认的命名方式,基本上可以满足大部分情况下的需求,但是如果有时候想要更加定制化目标文件名
+
+例如,按编译模式和架构区分目标名,这个时候可以使用这个接口,来设置:
+
+```lua
+target("xxx")
+ set_kind("static")
+ set_basename("xxx_$(mode)_$(arch)")
+```
+
+如果这个时候,编译配置为:`xmake f -m debug -a armv7`,那么生成的文件名为:`libxxx_debug_armv7.a`
+
+如果还想进一步定制目标文件的目录名,可参考:[set_targetdir](#targetset_targetdir)。
+
+或者通过编写自定义脚本,实现更高级的逻辑,具体见:[after_build](#targetafter_build)和[os.mv](#os-mv)。
+
+##### target:set_warnings
+
+###### 设置警告级别
+
+设置当前目标的编译的警告级别,一般支持一下几个级别:
+
+| 值 | 描述 |
+| ----- | ---------------------- |
+| none | 禁用所有警告 |
+| less | 启用较少的警告 |
+| more | 启用较多的警告 |
+| all | 启用所有警告 |
+| error | 将所有警告作为编译错误 |
+
+这个api的参数是可以混合添加的,例如:
+
+```lua
+-- 启用所有警告,并且作为编译错误处理
+set_warnings("all", "error")
+```
+
+如果当前没有目标,调用这个api将会设置到全局模式。。
+
+##### target:set_optimize
+
+###### 设置优化级别
+
+设置目标的编译优化等级,如果当前没有设置目标,那么将会设置到全局状态中,影响所有后续的目标。
+
+目前主要支持一下几个级别:
+
+| 值 | 描述 |
+| ---------- | ---------------------- |
+| none | 禁用优化 |
+| fast | 快速优化 |
+| faster | 更快的优化 |
+| fastest | 最快运行速度的优化 |
+| smallest | 最小化代码优化 |
+| aggressive | 过度优化 |
+
+例如:
+
+```lua
+-- 最快运行速度的优化
+set_optimize("fastest")
+```
+
+##### target:set_languages
+
+###### 设置代码语言标准
+
+设置目标代码编译的语言标准,如果当前没有目标存在,将会设置到全局模式中。。。
+
+支持的语言标准目前主要有以下几个:
+
+| 值 | 描述 |
+| ---------- | ---------------------- |
+| ansi | c语言标准: ansi |
+| c89 | c语言标准: c89 |
+| gnu89 | c语言标准: gnu89 |
+| c99 | c语言标准: c99 |
+| gnu99 | c语言标准: gnu99 |
+| cxx98 | c++语言标准: `c++98` |
+| gnuxx98 | c++语言标准: `gnu++98` |
+| cxx11 | c++语言标准: `c++11` |
+| gnuxx11 | c++语言标准: `gnu++11` |
+| cxx14 | c++语言标准: `c++14` |
+| gnuxx14 | c++语言标准: `gnu++14` |
+| cxx1z | c++语言标准: `c++1z` |
+| gnuxx1z | c++语言标准: `gnu++1z` |
+| cxx17 | c++语言标准: `c++17` |
+| gnuxx17 | c++语言标准: `gnu++17` |
+
+c标准和c++标准可同时进行设置,例如:
+
+```lua
+-- 设置c代码标准:c99, c++代码标准:c++11
+set_languages("c99", "cxx11")
+```
+
+<p class="warning">
+并不是设置了指定的标准,编译器就一定会按这个标准来编译,毕竟每个编译器支持的力度不一样,但是xmake会尽最大可能的去适配当前编译工具的支持标准。。。
+<br><br>
+例如:
+<br>
+windows下vs的编译器并不支持按c99的标准来编译c代码,只能支持到c89,但是xmake为了尽可能的支持它,所以在设置c99的标准后,xmake会强制按c++代码模式去编译c代码,从一定程度上解决了windows下编译c99的c代码问题。。
+用户不需要去额外做任何修改。。
+</p>
+
+##### target:set_headerdir
+
+###### 设置头文件安装目录
+
+设置头文件的输出目录,默认输出到build目录中。
+
+```lua
+target("test")
+ set_headerdir("$(buildir)/include")
+```
+
+对于需要安装哪些头文件,可参考[add_headers](#targetadd_headers)接口。
+
+##### target:set_targetdir
+
+###### 设置生成目标文件目录
+
+设置目标程序文件的输出目录,一般情况下,不需要设置,默认会输出在build目录下
+
+而build的目录可以在工程配置的时候,手动修改:
+
+```bash
+xmake f -o /tmp/build
+```
+
+修改成`/tmp/build`后,目标文件默认输出到`/tmp/build`下面。
+
+而如果用这个接口去设置,就不需要每次敲命令修改了,例如:
+
+```lua
+target("test")
+ set_targetdir("/tmp/build")
+```
+
+<p class="tip">
+如果显示设置了`set_targetdir`, 那么优先选择`set_targetdir`指定的目录为目标文件的输出目录。
+</p>
+
+##### target:set_objectdir
+
+###### 设置对象文件生成目录
+
+设置目标target的对象文件(`*.o/obj`)的输出目录,例如:
+
+```lua
+target("test")
+ set_objectdir("$(buildir)/.objs")
+```
+
+##### target:on_load
+
+###### 自定义目标加载脚本
+
+在target初始化加载的时候,将会执行此脚本,在里面可以做一些动态的目标配置,实现更灵活的目标描述定义,例如:
+
+```lua
+target("test")
+ on_load(function (target)
+ target:add("defines", "DEBUG", "TEST=\"hello\"")
+ target:add("linkdirs", "/usr/lib", "/usr/local/lib")
+ target:add({includedirs = "/usr/include", "links" = "pthread"})
+ end)
+```
+
+可以在`on_load`里面,通过`target:set`, `target:add` 来动态添加各种target属性。
+
+##### target:on_build
+
+###### 自定义编译脚本
+
+覆盖target目标默认的构建行为,实现自定义的编译过程,一般情况下,并不需要这么做,除非确实需要做一些xmake默认没有提供的编译操作。
+
+你可以通过下面的方式覆盖它,来自定义编译操作:
+
+```lua
+target("test")
+
+ -- 设置自定义编译脚本
+ on_build(function (target)
+ print("build it")
+ end)
+```
+
+注:2.1.5版本之后,所有target的自定义脚本都可以针对不同平台和架构,分别处理,例如:
+
+```lua
+target("test")
+ on_build("iphoneos|arm*", function (target)
+ print("build for iphoneos and arm")
+ end)
+```
+
+其中如果第一个参数为字符串,那么就是指定这个脚本需要在哪个`平台|架构`下,才会被执行,并且支持模式匹配,例如`arm*`匹配所有arm架构。
+
+当然也可以只设置平台,不设置架构,这样就是匹配指定平台下,执行脚本:
+
+```lua
+target("test")
+ on_build("windows", function (target)
+ print("build for windows")
+ end)
+```
+
+<p class="tip">
+一旦对这个target目标设置了自己的build过程,那么xmake默认的构建过程将不再被执行。
+</p>
+
+##### target:on_clean
+
+###### 自定义清理脚本
+
+覆盖target目标的`xmake [c|clean}`的清理操作,实现自定义清理过程。
+
+```lua
+target("test")
+
+ -- 设置自定义清理脚本
+ on_clean(function (target)
+
+ -- 仅删掉目标文件
+ os.rm(target:targetfile())
+ end)
+```
+
+一些target接口描述如下:
+
+| target接口 | 描述 |
+| ----------------------------------- | ---------------------------------------------------------------- |
+| target:name() | 获取目标名 |
+| target:targetfile() | 获取目标文件路径 |
+| target:get("kind") | 获取目标的构建类型 |
+| target:get("defines") | 获取目标的宏定义 |
+| target:get("xxx") | 其他通过 `set_/add_`接口设置的target信息,都可以通过此接口来获取 |
+| target:add("links", "pthread") | 添加目标设置 |
+| target:set("links", "pthread", "z") | 覆写目标设置 |
+| target:deps() | 获取目标的所有依赖目标 |
+| target:dep("depname") | 获取指定的依赖目标 |
+| target:sourcebatches() | 获取目标的所有源文件列表 |
+
+##### target:on_package
+
+###### 自定义打包脚本
+
+覆盖target目标的`xmake [p|package}`的打包操作,实现自定义打包过程,如果你想对指定target打包成自己想要的格式,可以通过这个接口自定义它。
+
+这个接口还是挺实用的,例如,编译玩jni后,将生成的so,打包进apk包中。
+
+```lua
+-- 定义一个android app的测试demo
+target("demo")
+
+ -- 生成动态库:libdemo.so
+ set_kind("shared")
+
+ -- 设置对象的输出目录,可选
+ set_objectdir("$(buildir)/.objs")
+
+ -- 每次编译完的libdemo.so的生成目录,设置为app/libs/armeabi
+ set_targetdir("libs/armeabi")
+
+ -- 添加jni的代码文件
+ add_files("jni/*.c")
+
+ -- 设置自定义打包脚本,在使用xmake编译完libdemo.so后,执行xmake p进行打包
+ -- 会自动使用ant将app编译成apk文件
+ --
+ on_package(function (target)
+
+ -- 使用ant编译app成apk文件,输出信息重定向到日志文件
+ os.run("ant debug")
+ end)
+```
+
+##### target:on_install
+
+###### 自定义安装脚本
+
+覆盖target目标的`xmake [i|install}`的安装操作,实现自定义安装过程。
+
+例如,将生成的apk包,进行安装。
+
+```lua
+target("test")
+
+ -- 设置自定义安装脚本,自动安装apk文件
+ on_install(function (target)
+
+ -- 使用adb安装打包生成的apk文件
+ os.run("adb install -r ./bin/Demo-debug.apk")
+ end)
+```
+
+##### target:on_uninstall
+
+###### 自定义卸载脚本
+
+覆盖target目标的`xmake [u|uninstall}`的卸载操作,实现自定义卸载过程。
+
+```lua
+target("test")
+ on_uninstall(function (target)
+ ...
+ end)
+```
+
+##### target:on_run
+
+###### 自定义运行脚本
+
+覆盖target目标的`xmake [r|run}`的运行操作,实现自定义运行过程。
+
+例如,运行安装好的apk程序:
+
+```lua
+target("test")
+
+ -- 设置自定义运行脚本,自动运行安装好的app程序,并且自动获取设备输出信息
+ on_run(function (target)
+
+ os.run("adb shell am start -n com.demo/com.demo.DemoTest")
+ os.run("adb logcat")
+ end)
+```
+
+##### target:before_build
+
+###### 在构建之前执行一些自定义脚本
+
+并不会覆盖默认的构建操作,只是在构建之前增加一些自定义的操作。
+
+```lua
+target("test")
+ before_build(function (target)
+ print("")
+ end)
+```
+
+##### target:before_clean
+
+###### 在清理之前执行一些自定义脚本
+
+并不会覆盖默认的清理操作,只是在清理之前增加一些自定义的操作。
+
+```lua
+target("test")
+ before_clean(function (target)
+ print("")
+ end)
+```
+
+##### target:before_package
+
+###### 在打包之前执行一些自定义脚本
+
+并不会覆盖默认的打包操作,只是在打包之前增加一些自定义的操作。
+
+```lua
+target("test")
+ before_package(function (target)
+ print("")
+ end)
+```
+
+##### target:before_install
+
+###### 在安装之前执行一些自定义脚本
+
+并不会覆盖默认的安装操作,只是在安装之前增加一些自定义的操作。
+
+```lua
+target("test")
+ before_install(function (target)
+ print("")
+ end)
+```
+
+##### target:before_uninstall
+
+###### 在卸载之前执行一些自定义脚本
+
+并不会覆盖默认的卸载操作,只是在卸载之前增加一些自定义的操作。
+
+```lua
+target("test")
+ before_uninstall(function (target)
+ print("")
+ end)
+```
+
+##### target:before_run
+
+###### 在运行之前执行一些自定义脚本
+
+并不会覆盖默认的运行操作,只是在运行之前增加一些自定义的操作。
+
+```lua
+target("test")
+ before_run(function (target)
+ print("")
+ end)
+```
+
+##### target:after_build
+
+###### 在构建之后执行一些自定义脚本
+
+并不会覆盖默认的构建操作,只是在构建之后增加一些自定义的操作。
+
+例如,对于ios的越狱开发,构建完程序后,需要用`ldid`进行签名操作
+
+```lua
+target("test")
+ after_build(function (target)
+ os.run("ldid -S %s", target:targetfile())
+ end)
+```
+
+##### target:after_clean
+
+###### 在清理之后执行一些自定义脚本
+
+并不会覆盖默认的清理操作,只是在清理之后增加一些自定义的操作。
+
+一般可用于清理编译某target自动生成的一些额外的临时文件,这些文件xmake默认的清理规则可能没有清理到,例如:
+
+```lua
+target("test")
+ after_clean(function (target)
+ os.rm("$(buildir)/otherfiles")
+ end)
+```
+
+##### target:after_package
+
+###### 在打包之后执行一些自定义脚本
+
+并不会覆盖默认的打包操作,只是在打包之后增加一些自定义的操作。
+
+```lua
+target("test")
+ after_package(function (target)
+ print("")
+ end)
+```
+
+##### target:after_install
+
+###### 在安装之后执行一些自定义脚本
+
+并不会覆盖默认的安装操作,只是在安装之后增加一些自定义的操作。
+
+```lua
+target("test")
+ after_install(function (target)
+ print("")
+ end)
+```
+##### target:after_uninstall
+
+###### 在卸载之后执行一些自定义脚本
+
+并不会覆盖默认的卸载操作,只是在卸载之后增加一些自定义的操作。
+
+```lua
+target("test")
+ after_uninstall(function (target)
+ print("")
+ end)
+```
+
+##### target:after_run
+
+###### 在运行之后执行一些自定义脚本
+
+并不会覆盖默认的运行操作,只是在运行之后增加一些自定义的操作。
+
+```lua
+target("test")
+ after_run(function (target)
+ print("")
+ end)
+```
+
+##### target:set_config_h
+
+###### 设置自动生成的配置头文件路径
+
+<p class="warning">
+2.1.5版本之后,此接口已废弃,请使用[set_config_header](#targetset_config_header)。
+</p>
+
+如果你想在xmake配置项目成功后,或者自动检测某个选项通过后,把检测的结果写入配置头文件,那么需要调用这个接口来启用自动生成`config.h`文件。
+
+使用方式例如:
+
+```lua
+target("test")
+
+ -- 启用并设置需要自动生成的config.h文件路径
+ set_config_h("$(buildir)/config.h")
+
+ -- 设置自动检测生成的宏开关的名字前缀
+ set_config_h_prefix("TB_CONFIG")
+```
+
+当这个target中通过下面的这些接口,对这个target添加了相关的选项依赖、包依赖、接口依赖后,如果某依赖被启用,那么对应的一些宏定义配置,会自动写入被设置的`config.h`文件中去。
+
+* [add_options](#targetadd_options)
+* [add_packages](#targetadd_packages)
+* [add_cfuncs](#targetadd_cfuncs)
+* [add_cxxfuncs](#targetadd_cxxfuncs)
+
+这些接口,其实底层都用到了[option](#option)选项中的一些检测设置,例如:
+
+```lua
+option("wchar")
+
+ -- 添加对wchar_t类型的检测
+ add_ctypes("wchar_t")
+
+ -- 如果检测通过,自动生成 TB_CONFIG_TYPE_HAVE_WCHAR的宏开关到config.h
+ add_defines_h("$(prefix)_TYPE_HAVE_WCHAR")
+
+target("test")
+
+ -- 启用头文件自动生成
+ set_config_h("$(buildir)/config.h")
+ set_config_h_prefix("TB_CONFIG")
+
+ -- 添加对wchar选项的依赖关联,只有加上这个关联,wchar选项的检测结果才会写入指定的config.h中去
+ add_options("wchar")
+```
+
+##### target:set_config_h_prefix
+
+###### 设置自动生成的头文件中宏定义命名前缀
+
+<p class="warning">
+2.1.5版本之后,此接口已废弃,请使用[set_config_header](#targetset_config_header)。
+</p>
+
+具体使用见:[set_config_h](#targetset_config_h)
+
+如果设置了:
+
+```lua
+target("test")
+ set_config_h_prefix("TB_CONFIG")
+```
+
+那么,选项中`add_defines_h("$(prefix)_TYPE_HAVE_WCHAR")`的$(prefix)会自动被替换成新的前缀值。
+
+##### target:set_config_header
+
+###### 设置自动生成的配置头文件路径和前缀
+
+此接口是[set_config_h](#targetset_config_h)和[set_config_h_prefix](#targetset_config_h_prefix)的升级版本,2.1.5之后支持。
+
+如果你想在xmake配置项目成功后,或者自动检测某个选项通过后,把检测的结果写入配置头文件,那么需要调用这个接口来启用自动生成`config.h`文件。
+
+使用方式例如:
+
+```lua
+target("test")
+ set_config_header("$(buildir)/config.h", {prefix = "TB_CONFIG"})
+```
+
+上面的代码,启用并设置需要自动生成的config.h文件路径,并且设置自动检测生成的宏开关的名字前缀:`TB_CONFIG`, 当然这个前缀的设置是可选的。
+
+```lua
+target("test")
+ set_config_header("$(buildir)/config.h")
+```
+
+如果不设置前缀,将会自动根据target名生成一个唯一字串。
+
+当这个target中通过下面的这些接口,对这个target添加了相关的选项依赖、包依赖、接口依赖后,如果某依赖被启用,那么对应的一些宏定义配置,会自动写入被设置的`config.h`文件中去。
+
+* [add_options](#targetadd_options)
+* [add_packages](#targetadd_packages)
+* [add_cfuncs](#targetadd_cfuncs)
+* [add_cxxfuncs](#targetadd_cxxfuncs)
+
+这些接口,其实底层都用到了[option](#option)选项中的一些检测设置,例如:
+
+```lua
+option("wchar")
+
+ -- 添加对wchar_t类型的检测
+ add_ctypes("wchar_t")
+
+ -- 如果检测通过,自动生成 TB_CONFIG_TYPE_HAVE_WCHAR的宏开关到config.h
+ add_defines_h("$(prefix)_TYPE_HAVE_WCHAR")
+
+target("test")
+
+ -- 启用头文件自动生成
+ set_config_header("$(buildir)/config.h", {prefix = "TB_CONFIG"})
+
+ -- 添加对wchar选项的依赖关联,只有加上这个关联,wchar选项的检测结果才会写入指定的config.h中去
+ add_options("wchar")
+```
+
+##### target:set_pcheader
+
+###### 设置c预编译头文件
+
+xmake支持通过预编译头文件去加速c程序编译,目前支持的编译器有:gcc, clang和msvc。
+
+使用方式如下:
+
+```lua
+target("test")
+ set_pcheader("header.h")
+```
+
+##### target:set_pcxxheader
+
+###### 设置c++预编译头文件
+
+xmake支持通过预编译头文件去加速c++程序编译,目前支持的编译器有:gcc, clang和msvc。
+
+使用方式如下:
+
+```lua
+target("test")
+ set_pcxxheader("header.h")
+```
+
+##### target:add_deps
+
+###### 添加子工程目标依赖
+
+添加当前目标的依赖目标,编译的时候,会去优先编译依赖的目标,然后再编译当前目标。。。
+
+```lua
+target("test1")
+ set_kind("static")
+ set_files("*.c")
+
+target("test2")
+ set_kind("static")
+ set_files("*.c")
+
+target("demo")
+
+ -- 添加依赖目标:test1, test2
+ add_deps("test1", "test2")
+
+ -- 链接libtest1.a,libtest2.a
+ add_links("test1", "test2")
+```
+
+上面的例子,在编译目标demo的时候,需要先编译test1, test2目标,因为demo会去用到他们
+
+<p class="tip">
+2.1.5版本后,target会自动继承依赖目标中的配置和属性,不再需要额外调用`add_links`, `add_includedirs`和`add_linkdirs`等接口去关联依赖目标了。
+</p>
+
+2.1.5版本之后,上述代码可简化为:
+
+```lua
+target("test1")
+ set_kind("static")
+ set_files("*.c")
+
+target("test2")
+ set_kind("static")
+ set_files("*.c")
+
+target("demo")
+ add_deps("test1", "test2") -- 会自动链接依赖目标
+```
+
+并且继承关系是支持级联的,例如:
+
+```lua
+target("library1")
+ set_kind("static")
+ add_files("*.c")
+ add_headers("inc1/*.h")
+
+target("library2")
+ set_kind("static")
+ add_deps("library1")
+ add_files("*.c")
+ add_headers("inc2/*.h")
+
+target("test")
+ set_kind("binary")
+ add_deps("library2")
+```
+
+如果我们还是想以前那样,并不想继承依赖target的任何配置,如何操作呢?这个在2.1.6版本中也对其进行了支持,通过:
+
+```lua
+add_deps("dep1", "dep2", {inherit = false})
+```
+
+通过显示设置inherit配置,来告诉xmake,这两个依赖的配置是否需要被继承,如果不设置,默认就是启用继承的。
+
+##### target:add_links
+
+###### 添加链接库名
+
+为当前目标添加链接库,一般这个要与[add_linkdirs](#targetadd_linkdirs)配对使用。
+
+```lua
+target("demo")
+
+ -- 添加对libtest.a的链接,相当于 -ltest
+ add_links("test")
+
+ -- 添加链接搜索目录
+ add_linkdirs("$(buildir)/lib")
+```
+
+##### target:add_files
+
+###### 添加源代码文件
+
+用于添加目标工程的源文件,甚至库文件,目前支持的一些文件类型:
+
+| 支持的源文件类型 | 描述 |
+| ------------------ | ---------------------------------- |
+| .c/.cpp/.cc/.cxx | c++文件 |
+| .s/.S/.asm | 汇编文件 |
+| .m/.mm | objc文件 |
+| .swift | swift文件 |
+| .go | golang文件 |
+| .o/.obj | 对象文件 |
+| .a/.lib | 静态库文件,会自动合并库到目标程序 |
+| .rc | msvc的资源文件 |
+
+其中通配符`*`表示匹配当前目录下文件,而`**`则匹配多级目录下的文件。
+
+例如:
+
+```lua
+add_files("src/test_*.c")
+add_files("src/xxx/**.cpp")
+add_files("src/asm/*.S", "src/objc/**/hello.m")
+```
+
+`add_files`的使用其实是相当灵活方便的,其匹配模式借鉴了premake的风格,但是又对其进行了改善和增强。
+
+使得不仅可以匹配文件,还有可以在添加文件同时,过滤排除指定模式的一批文件。
+
+例如:
+
+```lua
+-- 递归添加src下的所有c文件,但是不包括src/impl/下的所有c文件
+add_files("src/**.c|impl/*.c")
+
+-- 添加src下的所有cpp文件,但是不包括src/test.cpp、src/hello.cpp以及src下所有带xx_前缀的cpp文件
+add_files("src/*.cpp|test.cpp|hello.cpp|xx_*.cpp")
+```
+
+其中分隔符`|`之后的都是需要排除的文件,这些文件也同样支持匹配模式,并且可以同时添加多个过滤模式,只要中间用`|`分割就行了。。
+
+添加文件的时候支持过滤一些文件的一个好处就是,可以为后续根据不同开关逻辑添加文件提供基础。
+
+<p class="tip">
+为了使得描述上更加的精简,`|`之后的过滤描述都是基于起一个模式:`src/*.cpp` 中`*`之前的目录为基础的。
+所以上面的例子后面过滤的都是在src下的文件,这个是要注意的。
+</p>
+
+2.1.6版本之后,对`add_files`进行了改进,支持基于files更细粒度的编译选项控制,例如:
+
+```lua
+target("test")
+ add_defines("TEST1")
+ add_files("src/*.c")
+ add_files("test/*.c", "test2/test2.c", {defines = "TEST2", languages = "c99", includedirs = ".", cflags = "-O0"})
+```
+
+可以在`add_files`的最后一个参数,传入一个配置table,去控制指定files的编译选项,里面的配置参数跟target的一致,并且这些文件还会继承target的通用配置`-DTEST1`。
+
+##### target:add_headers
+
+###### 添加安装的头文件
+
+安装指定的头文件到build目录,如果设置了[set_headerdir](#targetset_headerdir), 则输出到指定目录。
+
+安装规则的语法跟[add_files](#targetadd_files)类似,例如:
+
+```lua
+ -- 安装tbox目录下所有的头文件(忽略impl目录下的文件),并且按()指定部分作为相对路径,进行安装
+ add_headers("../(tbox/**.h)|**/impl/**.h")
+```
+
+##### target:add_linkdirs
+
+###### 添加链接库搜索目录
+
+设置链接库的搜索目录,这个接口的使用方式如下:
+
+```lua
+target("test")
+ add_linkdirs("$(buildir)/lib")
+```
+
+此接口相当于gcc的`-Lxxx`链接选项。
+
+一般他是与[add_links](#targetadd_links)配合使用的,当然也可以直接通过[add_ldflags](#targetadd_ldflags)或者[add_shflags](#targetadd_shflags)接口来添加,也是可以的。
+
+<p class="tip">
+如果不想在工程中写死,可以通过:`xmake f --linkdirs=xxx`或者`xmake f --ldflags="-L/xxx"`的方式来设置,当然这种手动设置的目录搜索优先级更高。
+</p>
+
+##### target:add_rpathdirs
+
+###### 添加程序运行时动态库的加载搜索目录
+
+通过[add_linkdirs](#targetadd_linkdirs)设置动态库的链接搜索目录后,程序被正常链接,但是在linux平台想要正常运行编译后的程序,会报加载动态库失败。
+
+因为没找到动态库的加载目录,想要正常运行依赖动态库的程序,需要设置`LD_LIBRARY_PATH`环境变量,指定需要加载的动态库目录。
+
+但是这种方式是全局的,影响太广,更好的方式是通过`-rpath=xxx`的链接器选项,在链接程序的时候设置好需要加载的动态库搜索路径,而xmake对其进行了封装,通过`add_rpathdirs`更好的处理跨平台问题。
+
+具体使用如下:
+
+```lua
+target("test")
+ set_kind("binary")
+ add_linkdirs("$(buildir)/lib")
+ add_rpathdirs("$(buildir)/lib")
+```
+
+只需要在链接的时候,在设置下rpath目录就好了,虽然也可以通过`add_ldflags("-Wl,-rpath=xxx")`达到相同的目的,但是这个接口更加通用。
+
+内部会对不同平台进行处理,像在macOS下,是不需要`-rpath`设置的,也是可以正常加载运行程序,因此针对这个平台,xmake内部会直接忽略器设置,避免链接报错。
+
+而在为dlang程序进行动态库链接时,xmake会自动处理成`-L-rpath=xxx`来传入dlang的链接器,这样就避免了直接使用`add_ldflags`需要自己判断和处理不同平台和编译器问题。
+
+2.1.7版本对这个接口进行了改进,支持:`@loader_path`, `@executable_path` 和 `$ORIGIN`的内置变量,来指定程序的加载目录,它们的效果基本上是一样的,主要是为了同时兼容macho, elf。
+
+例如:
+
+```lua
+target("test")
+ set_kind("binary")
+ add_linkdirs("$(buildir)/lib")
+ add_rpathdirs("@loader_path/lib")
+```
+
+指定test程序加载当前执行目录下`lib/*.[so|dylib]`的动态库文件,这将有助于提升程序的可移植性,不用写死绝对路径和相对路径,导致程序和目录切换引起程序加载动态库失败。
+
+##### target:add_includedirs
+
+###### 添加头文件搜索目录
+
+设置头文件的搜索目录,这个接口的使用方式如下:
+
+```lua
+target("test")
+ add_includedirs("$(buildir)/include")
+```
+
+当然也可以直接通过[add_cxflags](#targetadd_cxflags)或者[add_mxflags](#targetadd_mxflags)等接口来设置,也是可以的。
+
+<p class="tip">
+如果不想在工程中写死,可以通过:`xmake f --includedirs=xxx`或者`xmake f --cxflags="-I/xxx"`的方式来设置,当然这种手动设置的目录搜索优先级更高。
+</p>
+
+##### target:add_defines
+
+###### 添加宏定义
+
+```lua
+add_defines("DEBUG", "TEST=0", "TEST2=\"hello\"")
+```
+
+相当于设置了编译选项:
+
+```
+-DDEBUG -DTEST=0 -DTEST2=\"hello\"
+```
+
+##### target:add_undefines
+
+###### 取消宏定义
+
+```lua
+add_undefines("DEBUG")
+```
+
+相当于设置了编译选项:`-UDEBUG`
+
+在代码中相当于:`#undef DEBUG`
+
+##### target:add_defines_h
+
+###### 添加宏定义到头文件
+
+添加宏定义到`config.h`配置文件,`config.h`的设置,可参考[set_config_h](#targetset_config_h)接口。
+
+##### target:add_undefines_h
+
+###### 取消宏定义到头文件
+
+在`config.h`配置文件中通过`undef`禁用宏定义,`config.h`的设置,可参考[set_config_h](#targetset_config_h)接口。
+
+##### target:add_cflags
+
+###### 添加c编译选项
+
+仅对c代码添加编译选项
+
+```lua
+add_cflags("-g", "-O2", "-DDEBUG")
+```
+
+<p class="warning">
+所有选项值都基于gcc的定义为标准,如果其他编译器不兼容(例如:vc),xmake会自动内部将其转换成对应编译器支持的选项值。
+用户无需操心其兼容性,如果其他编译器没有对应的匹配值,那么xmake会自动忽略器设置。
+</p>
+
+##### target:add_cxflags
+
+###### 添加c/c++编译选项
+
+同时对c/c++代码添加编译选项
+
+##### target:add_cxxflags
+
+###### 添加c++编译选项
+
+仅对c++代码添加编译选项
+
+##### target:add_mflags
+
+###### 添加objcc编译选项
+
+仅对objc代码添加编译选项
+
+```lua
+add_mflags("-g", "-O2", "-DDEBUG")
+```
+
+##### target:add_mxflags
+
+###### 添加objc/objc++编译选项
+
+同时对objc/objc++代码添加编译选项
+
+```lua
+add_mxflags("-framework CoreFoundation")
+```
+
+##### target:add_mxxflags
+
+###### 添加objc++编译选项
+
+仅对objc++代码添加编译选项
+
+```lua
+add_mxxflags("-framework CoreFoundation")
+```
+
+##### target:add_scflags
+
+###### 添加swift编译选项
+
+对swift代码添加编译选项
+
+```lua
+add_scflags("xxx")
+```
+
+##### target:add_asflags
+
+###### 添加汇编编译选项
+
+对汇编代码添加编译选项
+
+```lua
+add_asflags("xxx")
+```
+
+##### target:add_gcflags
+
+###### 添加go编译选项
+
+对golang代码添加编译选项
+
+```lua
+add_gcflags("xxx")
+```
+
+##### target:add_dcflags
+
+###### 添加dlang编译选项
+
+对dlang代码添加编译选项
+
+```lua
+add_dcflags("xxx")
+```
+
+##### target:add_rcflags
+
+###### 添加rust编译选项
+
+对rust代码添加编译选项
+
+```lua
+add_rcflags("xxx")
+```
+
+##### target:add_ldflags
+
+###### 添加链接选项
+
+添加静态链接库选项
+
+```lua
+add_ldflags("-L/xxx", "-lxxx")
+```
+
+##### target:add_arflags
+
+###### 添加静态库归档选项
+
+影响对静态库的生成
+
+```lua
+add_arflags("xxx")
+```
+##### target:add_shflags
+
+###### 添加动态库链接选项
+
+影响对动态库的生成
+
+```lua
+add_shflags("xxx")
+```
+
+##### target:add_cfunc
+
+###### 添加单个c库函数检测
+
+与[add_cfuncs](#targetadd_cfuncs)类似,只是仅对单个函数接口进行设置,并且仅对`target`域生效,`option`中不存在此接口。
+
+此接口的目的主要是为了在`config.h`中更加高度定制化的生成宏开关,例如:
+
+```lua
+target("demo")
+
+ -- 设置和启用config.h
+ set_config_h("$(buildir)/config.h")
+ set_config_h_prefix("TEST")
+
+ -- 仅通过参数一设置模块名前缀
+ add_cfunc("libc", nil, nil, {"sys/select.h"}, "select")
+
+ -- 通过参数三,设置同时检测链接库:libpthread.a
+ add_cfunc("pthread", nil, "pthread", "pthread.h", "pthread_create")
+
+ -- 通过参数二设置接口别名
+ add_cfunc(nil, "PTHREAD", nil, "pthread.h", "pthread_create")
+```
+
+生成的结果如下:
+
+```c
+#ifndef TEST_H
+#define TEST_H
+
+// 宏命名规则:$(prefix)前缀 _ 模块名(如果非nil)_ HAVE _ 接口名或者别名 (大写)
+#define TEST_LIBC_HAVE_SELECT 1
+#define TEST_PTHREAD_HAVE_PTHREAD_CREATE 1
+#define TEST_HAVE_PTHREAD 1
+
+#endif
+```
+
+如果要更加灵活的函数检测,可以通过[lib.detect.has_cfuncs](#detect-has_cfuncs)在自定义脚本中实现。
+
+##### target:add_cxxfunc
+
+###### 添加单个c++库函数检测
+
+与[add_cfunc](#targetadd_cfunc)类似,只是检测的函数接口是c++函数。
+
+##### target:add_cfuncs
+
+###### 添加c库函数检测
+
+<p class="warning">
+此接口是`target`和`option`共用的接口,但是接口行为稍有不同。
+</p>
+
+| 接口域 | 描述 | 例子 |
+| ------ | ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
+| target | 头文件、链接库和函数接口同时指定 | `add_cfuncs("libc", nil, {"signal.h", "setjmp.h"}, "signal", "setjmp", "sigsetjmp{sigjmp_buf buf; sigsetjmp(buf, 0);}", "kill")` |
+| option | 仅指定函数接口,头文件依赖[add_cincludes](#targetadd_cincludes)等独立接口 | `add_cincludes("setjmp.h")` `add_cfuncs("sigsetjmp")` |
+
+对于`option`,这个接口的使用很简单,跟[add_cincludes](#targetadd_cincludes)类似,例如:
+
+```lua
+option("setjmp")
+ set_default(false)
+ add_cincludes("setjmp.h")
+ add_cfuncs("sigsetjmp", "setjmp")
+ add_defines("HAVE_SETJMP")
+
+target("test")
+ add_options("setjmp")
+```
+
+此选项检测是否存在`setjmp`的一些接口,如果检测通过那么`test`目标程序将会加上`HAVE_SETJMP`的宏定义。
+
+<p class="warning">
+需要注意的是,在`option`中使用此接口检测依赖函数,需要同时使用独立的[add_cincludes](#targetadd_cincludes)增加头文件搜索路径,指定[add_links](#targetadd_links)链接库(可选),否则检测不到指定函数。
+<br><br>
+并且某些头文件接口是通过宏开关分别定义的,那么检测的时候最好通过[add_defines](#targetadd_defines)带上依赖的宏开关。
+</p>
+
+对于`target`,此接口可以同时设置:依赖的头文件、依赖的链接模块、依赖的函数接口,保证检测环境的完整性,例如:
+
+```lua
+target("test")
+
+ -- 添加libc库接口相关检测
+ -- 第一个参数:模块名,用于最后的宏定义前缀生成
+ -- 第二个参数:链接库
+ -- 第三个参数:头文件
+ -- 之后的都是函数接口列表
+ add_cfuncs("libc", nil, {"signal.h", "setjmp.h"}, "signal", "setjmp", "sigsetjmp{sigjmp_buf buf; sigsetjmp(buf, 0);}", "kill")
+
+ -- 添加pthread库接口相关检测,同时指定需要检测`libpthread.a`链接库是否存在
+ add_cfuncs("posix", "pthread", "pthread.h", "pthread_mutex_init",
+ "pthread_create",
+ "pthread_setspecific",
+ "pthread_getspecific",
+ "pthread_key_create",
+ "pthread_key_delete")
+```
+
+设置`test`目标,依赖这些接口,构建时会预先检测他们,并且如果通过[set_config_h](#targetset_config_h)接口设置的自动生成头文件:`config.h`
+
+那么,检测结果会自动加到对应的`config.h`上去,这也是`option`没有的功能,例如:
+
+```c
+#define TB_CONFIG_LIBC_HAVE_SIGNAL 1
+#define TB_CONFIG_LIBC_HAVE_SETJMP 1
+#define TB_CONFIG_LIBC_HAVE_SIGSETJMP 1
+#define TB_CONFIG_LIBC_HAVE_KILL 1
+
+#define TB_CONFIG_POSIX_HAVE_PTHREAD_MUTEX_INIT 1
+#define TB_CONFIG_POSIX_HAVE_PTHREAD_CREATE 1
+#define TB_CONFIG_POSIX_HAVE_PTHREAD_SETSPECIFIC 1
+#define TB_CONFIG_POSIX_HAVE_PTHREAD_GETSPECIFIC 1
+#define TB_CONFIG_POSIX_HAVE_PTHREAD_KEY_CREATE 1
+#define TB_CONFIG_POSIX_HAVE_PTHREAD_KEY_DELETE 1
+```
+
+由于,不同头文件中,函数的定义方式不完全相同,例如:宏函数、静态内联函数、extern函数等。
+
+要想完全检测成功,检测语法上需要一定程度的灵活性,下面是一些语法规则:
+
+| 检测语法 | 例子 |
+| ------------- | ----------------------------------------------- |
+| 纯函数名 | `sigsetjmp` |
+| 单行调用 | `sigsetjmp((void*)0, 0)` |
+| 函数块调用 | `sigsetjmp{sigsetjmp((void*)0, 0);}` |
+| 函数块 + 变量 | `sigsetjmp{int a = 0; sigsetjmp((void*)a, a);}` |
+
+##### target:add_cxxfuncs
+
+###### 添加c++库函数检测
+
+与[add_cfuncs](#targetadd_cfuncs)类似,只是检测的函数接口是c++函数。
+
+##### target:add_options
+
+###### 添加关联选项
+
+这个接口跟[set_options](#targetset_options)类似,唯一的区别就是,此处是追加选项,而[set_options](#targetset_options)每次设置会覆盖先前的设置。
+
+##### target:add_packages
+
+###### 添加包依赖
+
+在target作用域中,添加集成包依赖,例如:
+
+```lua
+target("test")
+ add_packages("zlib", "polarssl", "pcre", "mysql")
+```
+
+这样,在编译test目标时,如果这个包存在的,将会自动追加包里面的宏定义、头文件搜索路径、链接库目录,也会自动链接包中所有库。
+
+用户不再需要自己单独调用[add_links](#targetadd_links),[add_includedirs](#targetadd_includedirs), [add_ldflags](#targetadd_ldflags)等接口,来配置依赖库链接了。
+
+对于如何设置包搜索目录,可参考:[add_packagedirs](#targetadd_packagedirs) 接口
+
+##### target:add_languages
+
+###### 添加语言标准
+
+与[set_languages](#targetset_languages)类似,唯一区别是这个接口不会覆盖掉之前的设置,而是追加设置。
+
+##### target:add_vectorexts
+
+###### 添加向量扩展指令
+
+添加扩展指令优化选项,目前支持以下几种扩展指令集:
+
+```lua
+add_vectorexts("mmx")
+add_vectorexts("neon")
+add_vectorexts("avx", "avx2")
+add_vectorexts("sse", "sse2", "sse3", "ssse3")
+```
+
+<p class="tip">
+如果当前设置的指令集编译器不支持,xmake会自动忽略掉,所以不需要用户手动去判断维护,只需要将你需要的指令集全部设置上就行了。
+</p>
+
+##### target:add_frameworks
+
+###### 添加链接框架
+
+目前主要用于`ios`和`macosx`平台的`objc`和`swift`程序,例如:
+
+```lua
+target("test")
+ add_frameworks("Foundation", "CoreFoundation")
+```
+
+当然也可以使用[add_mxflags](#targetadd_mxflags)和[add_ldflags](#targetadd_ldflags)来设置,不过比较繁琐,不建议这样设置。
+
+```lua
+target("test")
+ add_mxflags("-framework Foundation", "-framework CoreFoundation")
+ add_ldflags("-framework Foundation", "-framework CoreFoundation")
+```
+
+如果不是这两个平台,这些设置将会被忽略。
+
+##### target:add_frameworkdirs
+
+###### 添加链接框架搜索目录
+
+对于一些第三方framework,那么仅仅通过[add_frameworks](#targetadd_frameworks)是没法找到的,还需要通过这个接口来添加搜索目录。
+
+```lua
+target("test")
+ add_frameworks("MyFramework")
+ add_frameworkdirs("/tmp/frameworkdir", "/tmp/frameworkdir2")
+```
+
+#### 选项定义
+
+定义和设置选项开关,每个`option`对应一个选项,可用于自定义编译配置选项、开关设置。
+
+<p class="tip">
+除了`target`以外的所有域接口,例如`option`,`task`等的接口,默认不能放置在外面的全局作用域中的(除非部分跟target共用的接口除外)。
+如果要设置值影响所有`option`,`task`等选项,可以通过匿名全局域来设置。
+</p>
+
+例如:
+
+```lua
+-- 进入option的匿名全局域,里面的设置会同时影响test和test2选项
+option()
+ add_defines("DEBUG")
+
+option("test")
+ -- ...
+ -- 尽量保持缩进,因为这个之后的所有设置,都是针对test选项的
+
+option("test2")
+ -- ...
+```
+
+<p class="tip">
+`option`域是可以重复进入来实现分离设置的,如果要显示离开当前选项的作用域设置,可以手动调用[option_end](#option_end)接口。
+</p>
+
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------------- | -------------------------------------------- | -------- |
+| [option](#option) | 定义选项 | >= 2.0.1 |
+| [option_end](#option_end) | 结束定义选项 | >= 2.1.1 |
+| [add_deps](#optionadd_deps) | 添加选项依赖 | >= 2.1.5 |
+| [before_check](#optionbefore_check) | 选项检测之前执行此脚本 | >= 2.1.5 |
+| [on_check](#optionon_check) | 自定义选项检测脚本 | >= 2.1.5 |
+| [after_check](#optionafter_check) | 选项检测之后执行此脚本 | >= 2.1.5 |
+| [set_default](#optionset_default) | 设置默认值 | >= 2.0.1 |
+| [set_showmenu](#optionset_showmenu) | 设置是否启用菜单显示 | >= 1.0.1 |
+| [set_category](#optionset_category) | 设置选项分类,仅用于菜单显示 | >= 1.0.1 |
+| [set_description](#optionset_description) | 设置菜单显示描述 | >= 1.0.1 |
+| [add_links](#optionadd_links) | 添加链接库检测 | >= 1.0.1 |
+| [add_linkdirs](#optionadd_linkdirs) | 添加链接库检测需要的搜索目录 | >= 1.0.1 |
+| [add_rpathdirs](#optionadd_rpathdirs) | 添加运行时候动态链接库搜索目录 | >= 2.1.3 |
+| [add_cincludes](#optionadd_cincludes) | 添加c头文件检测 | >= 1.0.1 |
+| [add_cxxincludes](#optionadd_cxxincludes) | 添加c++头文件检测 | >= 1.0.1 |
+| [add_ctypes](#optionadd_ctypes) | 添加c类型检测 | >= 1.0.1 |
+| [add_cxxtypes](#optionadd_cxxtypes) | 添加c++类型检测 | >= 1.0.1 |
+| [add_csnippet](#optionadd_csnippet) | 添加c代码片段检测 | >= 2.1.5 |
+| [add_cxxsnippet](#optionadd_cxxsnippet) | 添加c++代码片段检测 | >= 2.1.5 |
+| [set_warnings](#targetset_warnings) | 设置警告级别 | >= 1.0.1 |
+| [set_optimize](#targetset_optimize) | 设置优化级别 | >= 1.0.1 |
+| [set_languages](#targetset_languages) | 设置代码语言标准 | >= 1.0.1 |
+| [add_includedirs](#targetadd_includedirs) | 添加头文件搜索目录 | >= 1.0.1 |
+| [add_defines](#targetadd_defines) | 添加宏定义 | >= 1.0.1 |
+| [add_undefines](#targetadd_undefines) | 取消宏定义 | >= 1.0.1 |
+| [add_defines_h](#targetadd_defines_h) | 添加宏定义到头文件 | >= 1.0.1 |
+| [add_undefines_h](#targetadd_undefines_h) | 取消宏定义到头文件 | >= 1.0.1 |
+| [add_cflags](#targetadd_cflags) | 添加c编译选项 | >= 1.0.1 |
+| [add_cxflags](#targetadd_cxflags) | 添加c/c++编译选项 | >= 1.0.1 |
+| [add_cxxflags](#targetadd_cxxflags) | 添加c++编译选项 | >= 1.0.1 |
+| [add_mflags](#targetadd_mflags) | 添加objc编译选项 | >= 2.0.1 |
+| [add_mxflags](#targetadd_mxflags) | 添加objc/objc++编译选项 | >= 2.0.1 |
+| [add_mxxflags](#targetadd_mxxflags) | 添加objc++编译选项 | >= 2.0.1 |
+| [add_scflags](#targetadd_scflags) | 添加swift编译选项 | >= 2.1.1 |
+| [add_asflags](#targetadd_asflags) | 添加汇编编译选项 | >= 2.1.1 |
+| [add_gcflags](#targetadd_gcflags) | 添加go编译选项 | >= 2.1.1 |
+| [add_dcflags](#targetadd_dcflags) | 添加dlang编译选项 | >= 2.1.1 |
+| [add_rcflags](#targetadd_rcflags) | 添加rust编译选项 | >= 2.1.1 |
+| [add_ldflags](#targetadd_ldflags) | 添加链接选项 | >= 2.1.1 |
+| [add_arflags](#targetadd_arflags) | 添加静态库归档选项 | >= 2.1.1 |
+| [add_shflags](#targetadd_shflags) | 添加动态库链接选项 | >= 2.0.1 |
+| [add_cfuncs](#targetadd_cfuncs) | 添加c库函数检测 | >= 1.0.1 |
+| [add_cxxfuncs](#targetadd_cxxfuncs) | 添加c++库函数接口 | >= 1.0.1 |
+| [add_languages](#targetadd_languages) | 添加语言标准 | >= 2.0.1 |
+| [add_vectorexts](#targetadd_vectorexts) | 添加向量扩展指令 | >= 2.0.1 |
+| [add_frameworks](#targetadd_frameworks) | 添加链接框架 | >= 2.1.1 |
+| [add_frameworkdirs](#targetadd_frameworkdirs) | 添加链接框架 | >= 2.1.5 |
+
+| 废弃接口 | 描述 | 支持版本 |
+| ----------------------------------------------------- | -------------------------------------------- | ---------------- |
+| [add_bindings](#optionadd_bindings) | 添加正向关联选项,同步启用和禁用 | >= 2.0.1 < 2.1.5 |
+| [add_rbindings](#optionadd_rbindings) | 添加逆向关联选项,同步启用和禁用 | >= 2.0.1 < 2.1.5 |
+| [add_defines_if_ok](#optionadd_defines_if_ok) | 如果检测选项通过,则添加宏定义 | >= 1.0.1 < 2.1.5 |
+| [add_defines_h_if_ok](#optionadd_defines_h_if_ok) | 如果检测选项通过,则添加宏定义到配置头文件 | >= 1.0.1 < 2.1.5 |
+| [add_undefines_if_ok](#optionadd_undefines_if_ok) | 如果检测选项通过,则取消宏定义 | >= 1.0.1 < 2.1.5 |
+| [add_undefines_h_if_ok](#optionadd_undefines_h_if_ok) | 如果检测选项通过,则在配置头文件中取消宏定义 | >= 1.0.1 < 2.1.5 |
+
+##### option
+
+###### 定义选项
+
+定义和设置选项开关,可用于自定义编译配置选项、开关设置。
+
+例如,定义一个是否启用test的选项:
+
+```lua
+option("test")
+ set_default(false)
+ set_showmenu(true)
+ add_defines("-DTEST")
+```
+
+然后关联到指定的target中去:
+
+```lua
+target("demo")
+ add_options("test")
+```
+
+这样,一个选项就算定义好了,如果这个选项被启用,那么编译这个target的时候,就会自动加上`-DTEST`的宏定义。
+
+```lua
+# 手动启用这个选项
+$ xmake f --test=y
+$ xmake
+```
+
+##### option_end
+
+###### 结束定义选项
+
+这是一个可选api,显示离开选项作用域,用法和[target_end](#target_end)类似。
+
+##### option:add_deps
+
+###### 添加选项依赖
+
+通过设置依赖,可以调整选项的检测顺序,一般用于[on_check](#optionon_check)等检测脚本的调用时机。
+
+```lua
+option("small")
+ set_default(true)
+ on_check(function (option)
+ -- ...
+ end)
+
+option("test")
+ add_deps("small")
+ set_default(true)
+ on_check(function (option)
+ if option:dep("small"):enabled() then
+ option:enable(false)
+ end
+ end)
+```
+
+当依赖的small选项检测完成后,通过判断small选项的状态,来控制test的选项状态。
+
+##### option:before_check
+
+###### 选项检测之前执行此脚本
+
+例如:在检测之前,通过[find_package](#detect-find_package)来查找包,将`links`, `includedirs`和`linkdirs`等信息添加到option中去,
+然后开始选项检测,通过后就会自动链接到target上。
+
+```lua
+option("zlib")
+ before_check(function (option)
+ import("lib.detect.find_package")
+ option:add(find_package("zlib"))
+ end)
+```
+
+##### option:on_check
+
+###### 自定义选项检测脚本
+
+此脚本会覆盖内置的选项检测逻辑。
+
+```lua
+option("test")
+ add_deps("small")
+ set_default(true)
+ on_check(function (option)
+ if option:dep("small"):enabled() then
+ option:enable(false)
+ end
+ end)
+```
+
+如果test依赖的选项通过,则禁用test选项。
+
+##### option:after_check
+
+###### 选项检测之后执行此脚本
+
+在选项检测完成后,执行此脚本做一些后期处理,也可以在此时重新禁用选项:
+
+```lua
+option("test")
+ add_deps("small")
+ add_links("pthread")
+ after_check(function (option)
+ option:enable(false)
+ end)
+```
+
+##### option:set_default
+
+###### 设置选项默认值
+
+在没有通过`xmake f --option=[y|n}`等命令修改选项值的时候,这个选项本身也是有个默认值的,可以通过这个接口来设置:
+
+```lua
+option("test")
+ -- 默认禁用这个选项
+ set_default(false)
+```
+
+选项的值不仅支持boolean类型,也可以是字符串类型,例如:
+
+```lua
+option("test")
+ set_default("value")
+```
+
+| 值类型 | 描述 | 配置 |
+| ------ | -------------------------------------- | -----------------------------------------------|
+| boolean | 一般用作参数开关,值范围:`true/false` | `xmake f --optionname=[y/n/yes/no/true/false]` |
+| string | 可以是任意字符串,一般用于模式判断 | `xmake f --optionname=value` |
+
+如果是`boolean`值的选项,可以通过[is_option](#is_option)来进行判断,选项是否被启用。
+
+如果是`string`类型的选项,可以在内建变量中直接使用,例如:
+
+```lua
+-- 定义一个路径配置选项,默认使用临时目录
+option("rootdir")
+ set_default("$(tmpdir)")
+ set_showmenu(true)
+
+target("test")
+ -- 添加指定选项目录中的源文件
+ add_files("$(rootdir)/*.c")
+```
+
+其中,`$(rootdir)` 就是自定义的选项内建变量,通过手动配置,可以动态修改它的值:
+
+```bash
+$ xmake f --rootdir=~/projectdir/src
+$ xmake
+```
+
+给这个`rootdir`选项指定一个其他的源码目录路径,然后编译。
+
+选项的检测行为:
+
+| default值 | 检测行为 |
+| ---------- | --------------------------------------------------------------------------------------------- |
+| 没有设置 | 优先手动配置修改,默认禁用,否则自动检测,可根据手动传入的值类型,自动切换boolean和string类型 |
+| false | 开关选项,不自动检测,默认禁用,可手动配置修改 |
+| true | 开关选项,不自动检测,默认启用,可手动配置修改 |
+| string类型 | 无开关状态,不自动检测,可手动配置修改,一般用于配置变量传递 |
+
+##### option:set_showmenu
+
+###### 设置是否启用菜单显示
+
+如果设置为`true`,那么在`xmake f --help`里面就会出现这个选项,也就能通过`xmake f --optionname=xxx`进行配置,否则只能在`xmake.lua`内部使用,无法手动配置修改。
+
+```lua
+option("test")
+ set_showmenu(true)
+```
+
+设置为启用菜单后,执行`xmake f --help`可以看到,帮助菜单里面多了一项:
+
+```
+Options:
+ ...
+
+ --test=TEST
+```
+
+##### option:set_category
+
+###### 设置选项分类,仅用于菜单显示
+
+这个是个可选配置,仅用于在帮助菜单中,进行分类显示选项,同一类别的选项,会在同一个分组里面显示,这样菜单看起来更加的美观。
+
+例如:
+
+```lua
+option("test1")
+ set_showmenu(true)
+ set_category("test")
+
+option("test2")
+ set_showmenu(true)
+ set_category("test")
+
+option("demo1")
+ set_showmenu(true)
+ set_category("demo")
+
+option("demo2")
+ set_showmenu(true)
+ set_category("demo")
+```
+
+这里四个选项分别归类于两个分组:`test`和`demo`,那么显示的布局类似这样:
+
+```bash
+Options:
+ ...
+
+ --test1=TEST1
+ --test2=TEST2
+
+ --demo1=DEMO1
+ --demo2=DEMO2
+```
+
+这个接口,仅仅是为了调整显示布局,更加美观而已,没其他用途。
+
+##### option:set_description
+
+###### 设置菜单显示描述
+
+设置选项菜单显示时,右边的描述信息,用于帮助用户更加清楚的知道这个选项的用途,例如:
+
+```lua
+option("test")
+ set_default(false)
+ set_showmenu(true)
+ set_description("Enable or disable test")
+```
+
+生成的菜单内容如下:
+
+```
+Options:
+ ...
+
+ --test=TEST Enable or disable test (default: false)
+```
+
+这个接口也支持多行显示,输出更加详细的描述信息,例如:
+
+```lua
+option("mode")
+ set_default("debug")
+ set_showmenu(true)
+ set_description("Set build mode"
+ " - debug"
+ " - release"
+ " - profile")
+```
+
+生成的菜单内容如下:
+
+```
+Options:
+ ...
+
+ --mode=MODE Set build mode (default: debug)
+ - debug
+ - release
+ - profile
+```
+
+看到这个菜单,用户就能清楚地知道,定义的这个`mode`选项的具体用处,以及如何使用了:
+
+```bash
+$ xmake f --mode=release
+```
+
+##### option:add_bindings
+
+###### 添加正向关联选项,同步启用和禁用
+
+<p class="tip">
+2.1.5版本之后已废弃,请用[add_deps](#optionadd_deps), [on_check](#optionon_check), [after_check](#optionafter_check)等接口代替。
+</p>
+
+绑定关联选项,例如我想在命令行中配置一个`smallest`的参数:`xmake f --smallest=y`
+
+这个时候,需要同时禁用多个其他的选项开关,来禁止编译多个模块,就是这个需求,相当于一个选项 与其他 多个选项之间 是有联动效应的。
+
+而这个接口就是用来设置需要正向绑定的一些关联选项,例如:
+
+```lua
+-- 定义选项开关: --smallest=y|n
+option("smallest")
+
+ -- 添加正向绑定,如果smallest被启用,下面的所有选项开关也会同步被启用
+ add_bindings("nozip", "noxml", "nojson")
+```
+
+##### option:add_rbindings
+
+###### 添加逆向关联选项,同步启用和禁用
+
+<p class="tip">
+2.1.5版本之后已废弃,请用[add_deps](#optionadd_deps), [on_check](#optionon_check), [after_check](#optionafter_check)等接口代替。
+</p>
+
+逆向绑定关联选项,被关联选项的开关状态是相反的。
+
+```lua
+-- 定义选项开关: --smallest=y|n
+option("smallest")
+
+ -- 添加反向绑定,如果smallest被启用,下面的所有模块全部禁用
+ add_rbindings("xml", "zip", "asio", "regex", "object", "thread", "network", "charset", "database")
+ add_rbindings("zlib", "mysql", "sqlite3", "openssl", "polarssl", "pcre2", "pcre", "base")
+```
+
+<p class="warning">
+需要注意的是,命令行配置是有顺序的,你可以先通过启用smallest禁用所有模块,然后添加其他选项,逐一启用。
+</p>
+
+例如:
+
+```bash
+-- 禁用所有模块,然后仅仅启用xml和zip模块
+$ xmake f --smallest=y --xml=y --zip=y
+```
+
+##### option:add_links
+
+###### 添加链接库检测
+
+如果指定的链接库检测通过,此选项将被启用,并且对应关联的target会自动加上此链接,例如:
+
+```lua
+option("pthread")
+ set_default(false)
+ add_links("pthread")
+ add_linkdirs("/usr/local/lib")
+
+target("test")
+ add_options("pthread")
+```
+
+如果检测通过,`test`目标编译的时候就会自动加上:`-L/usr/local/lib -lpthread` 编译选项
+
+
+##### option:add_linkdirs
+
+###### 添加链接库检测时候需要的搜索目录
+
+这个是可选的,一般系统库不需要加这个,也能检测通过,如果确实没找到,可以自己追加搜索目录,提高检测通过率。具体使用见:[add_links](#optionadd_links)
+
+##### option:add_rpathdirs
+
+###### 添加程序运行时动态库的加载搜索目录
+
+在选项通过检测后,会自动添加到对应的target上去,具体使用见:[target.add_rpathdirs](#targetadd_rpathdirs)。
+
+##### option:add_cincludes
+
+###### 添加c头文件检测
+
+如果c头文件检测通过,此选项将被启用,例如:
+
+```lua
+option("pthread")
+ set_default(false)
+ add_cincludes("pthread.h")
+ add_defines("ENABLE_PTHREAD")
+
+target("test")
+ add_options("pthread")
+```
+
+此选项检测是否存在`pthread.h`的头文件,如果检测通过那么`test`目标程序将会加上`ENABLE_PTHREAD`的宏定义。
+
+如果想要更加灵活的检测,可以通过[lib.detect.has_cincludes](#detect-has_cincludes)在[option.on_check](#optionon_check)中去实现。
+
+##### option:add_cxxincludes
+
+###### 添加c++头文件检测
+
+与[add_cincludes](#optionadd_cincludes)类似,只是检测的头文件类型是c++头文件。
+
+##### option:add_ctypes
+
+###### 添加c类型检测
+
+如果c类型检测通过,此选项将被启用,例如:
+
+```lua
+option("wchar")
+ set_default(false)
+ add_cincludes("wchar_t")
+ add_defines("HAVE_WCHAR")
+
+target("test")
+ add_options("wchar")
+```
+
+此选项检测是否存在`wchar_t`的类型,如果检测通过那么`test`目标程序将会加上`HAVE_WCHAR`的宏定义。
+
+如果想要更加灵活的检测,可以通过[lib.detect.has_ctypes](#detect-has_ctypes)在[option.on_check](#optionon_check)中去实现。
+
+##### option:add_cxxtypes
+
+###### 添加c++类型检测
+
+与[add_ctypes](#optionadd_ctypes)类似,只是检测的类型是c++类型。
+
+##### option:add_csnippet
+
+###### 添加c代码片段检测
+
+如果现有的[add_ctypes](#optionadd_ctypes), [add_cfuncs](#optionadd_cfuncs)等不能满足当前的检测需求,
+可以用这个接口实现更加定制化检测一些编译器特性检测,具体见: [add_cxxsnippet](#optionadd_cxxsnippet)。
+
+##### option:add_cxxsnippet
+
+###### 添加c++代码片段检测
+
+可以用这个接口实现更加定制化检测一些编译器特性检测,尤其是c++的各种特性的检测支持,例如:
+
+```lua
+option("constexpr")
+ add_cxxsnippet("constexpr int f(int x) { int sum=0; for (int i=0; i<=x; ++i) sum += i; return sum; } constexpr int x = f(5); static_assert(x == 15);")
+```
+
+上述代码,实现对c++的constexpr特性的检测,如果检测通过,则启用constexpr选项,当然这里只是个例子。
+
+对于编译器特性的检测,有更加方便高效的检测模块,提供更强大的检测支持,具体见:[compiler.has_features](#compiler-has_features)和[detect.check_cxsnippets](#detect-check_cxsnippets)
+
+如果想要更加灵活的检测,可以通过[lib.detect.check_cxsnippets](#detect-check_cxsnippets)在[option.on_check](#optionon_check)中去实现。
+
+##### option:add_defines_if_ok
+
+###### 如果检测选项通过,则添加宏定义
+
+<p class="tip">
+2.1.5版本之后已废弃,请用[add_defines](#targetadd_defines)接口代替。
+</p>
+
+检测选项通过后才会被设置,具体使用见[add_cincludes](#optionadd_cincludes)中的例子。
+
+##### option:add_defines_h_if_ok
+
+###### 如果检测选项通过,则添加宏定义到配置头文件
+
+<p class="tip">
+2.1.5版本之后已废弃,请用[add_defines_h](#targetadd_defines_h)接口代替。
+</p>
+
+跟[add_defines_if_ok](#optionadd_defines_if_ok)类似,只是检测通过后,会在`config.h`头文件中自动加上被设置的宏定义。
+
+例如:
+
+```lua
+option("pthread")
+ set_default(false)
+ add_cincludes("pthread.h")
+ add_defines_h_if_ok("ENABLE_PTHREAD")
+
+target("test")
+ add_options("pthread")
+```
+
+通过后,会在`config.h`中加上:
+
+```c
+#define ENABLE_PTHREAD 1
+```
+
+具体`config.h`如何设置,见:[set_config_h](#targetset_config_h)
+
+##### option:add_undefines_if_ok
+
+###### 如果检测选项通过,则取消宏定义
+
+<p class="tip">
+2.1.5版本之后已废弃,请用[add_undefines](#targetadd_undefines)接口代替。
+</p>
+
+跟[add_defines_if_ok](#optionadd_defines_if_ok)类似,只是检测通过后,取消被设置的宏定义。
+
+##### option:add_undefines_h_if_ok
+
+###### 如果检测选项通过,则在配置头文件中取消宏定义
+
+<p class="tip">
+2.1.5版本之后已废弃,请用[add_undefines_h](#targetadd_undefines_h)接口代替。
+</p>
+
+跟[add_defines_h_if_ok](#optionadd_defines_h_if_ok)类似,只是检测通过后,会在`config.h`中取消被设置的宏定义。
+
+```c
+#undef DEFINED_MACRO
+```
+
+具体`config.h`如何设置,见:[set_config_h](#targetset_config_h)
+
+#### 插件任务
+
+xmake可以实现自定义任务或者插件,其两者的核心就是`task`任务,其两者实际上是一样的,xmake的插件都是用`task`实现的。
+
+本质上都是任务,只是[set_category](#taskset_category)分类不同而已。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [task](#task) | 定义插件或者任务 | >= 2.0.1 |
+| [task_end](#task_end) | 结束定义插件或任务 | >= 2.1.1 |
+| [set_menu](#taskset_menu) | 设置任务菜单 | >= 2.0.1 |
+| [set_category](#taskset_category) | 设置任务类别 | >= 2.0.1 |
+| [on_run](#taskon_run) | 设置任务运行脚本 | >= 2.0.1 |
+
+##### task
+
+###### 定义插件或者任务
+
+`task`域用于描述一个自定义的任务实现,与[target](#target)和[option](#option)同级。
+
+例如,这里定义一个最简单的任务:
+
+```lua
+task("hello")
+
+ -- 设置运行脚本
+ on_run(function ()
+ print("hello xmake!")
+ end)
+```
+
+这个任务只需要打印`hello xmake!`,那如何来运行呢?
+
+由于这里没有使用[set_menu](#taskset_menu)设置菜单,因此这个任务只能再`xmake.lua`的自定义脚本或者其他任务内部调用,例如:
+
+```lua
+target("test")
+
+ after_build(function (target)
+
+ -- 导入task模块
+ import("core.project.task")
+
+ -- 运行hello任务
+ task.run("hello")
+ end)
+```
+
+在构建完`test`目标后运行`hello`任务。
+
+##### task_end
+
+###### 结束定义插件或任务
+
+这是一个可选api,显示离开选项作用域,用法和[target_end](#target_end)类似。
+
+##### task:set_menu
+
+###### 设置任务菜单
+
+通过设置一个菜单,这个任务就可以开放给用户自己通过命令行手动调用,菜单的设置如下:
+
+```lua
+task("echo")
+
+ -- 设置运行脚本
+ on_run(function ()
+
+ -- 导入参数选项模块
+ import("core.base.option")
+
+ -- 初始化颜色模式
+ local modes = ""
+ for _, mode in ipairs({"bright", "dim", "blink", "reverse"}) do
+ if option.get(mode) then
+ modes = modes .. " " .. mode
+ end
+ end
+
+ -- 获取参数内容并且显示信息
+ cprint("${%s%s}%s", option.get("color"), modes, table.concat(option.get("contents") or {}, " "))
+ end)
+
+ -- 设置插件的命令行选项,这里没有任何参数选项,仅仅显示插件描述
+ set_menu {
+ -- 设置菜单用法
+ usage = "xmake echo [options]"
+
+ -- 设置菜单描述
+ , description = "Echo the given info!"
+
+ -- 设置菜单选项,如果没有选项,可以设置为{}
+ , options =
+ {
+ -- 设置k模式作为key-only型bool参数
+ {'b', "bright", "k", nil, "Enable bright." }
+ , {'d', "dim", "k", nil, "Enable dim." }
+ , {'-', "blink", "k", nil, "Enable blink." }
+ , {'r', "reverse", "k", nil, "Reverse color." }
+
+ -- 菜单显示时,空白一行
+ , {}
+
+ -- 设置kv作为key-value型参数,并且设置默认值:black
+ , {'c', "color", "kv", "black", "Set the output color."
+ , " - red"
+ , " - blue"
+ , " - yellow"
+ , " - green"
+ , " - magenta"
+ , " - cyan"
+ , " - white" }
+
+ -- 设置`vs`作为values多值型参数,还有`v`单值类型
+ -- 一般放置在最后,用于获取可变参数列表
+ , {}
+ , {nil, "contents", "vs", nil, "The info contents." }
+ }
+ }
+```
+
+定义完这个任务后,执行`xmake --help`,就会多出一个任务项来:
+
+```
+Tasks:
+
+ ...
+
+ echo Echo the given info!
+```
+
+如果通过[set_category](#taskset_category)设置分类为`plugin`,那么这个任务就是一个插件了:
+
+```
+Plugins:
+
+ ...
+
+ echo Echo the given info!
+```
+
+想要手动运行这个任务,可以执行:
+
+```bash
+$ xmake echo hello xmake!
+```
+
+就行了,如果要看这个任务定义的菜单,只需要执行:`xmake echo [-h|--help]`,显示结果如下:
+
+```bash
+Usage: $xmake echo [options]
+
+Echo the given info!
+
+Options:
+ -v, --verbose Print lots of verbose information.
+ --backtrace Print backtrace information for debugging.
+ --profile Print performance data for debugging.
+ --version Print the version number and exit.
+ -h, --help Print this help message and exit.
+
+ -F FILE, --file=FILE Read a given xmake.lua file.
+ -P PROJECT, --project=PROJECT Change to the given project directory.
+ Search priority:
+ 1. The Given Command Argument
+ 2. The Envirnoment Variable: XMAKE_PROJECT_DIR
+ 3. The Current Directory
+
+ -b, --bright Enable bright.
+ -d, --dim Enable dim.
+ --, --blink Enable blink.
+ -r, --reverse Reverse color.
+
+ -c COLOR, --color=COLOR Set the output color. (default: black)
+ - red
+ - blue
+ - yellow
+ - green
+ - magenta
+ - cyan
+ - white
+
+ contents ... The info contents.
+```
+
+<p class="tip">
+其中菜单最开头的部分选项,是xmake内置的常用选项,基本上每个任务都会用到,不需要自己额外定义,简化菜单定义。
+</p>
+
+下面,我们来实际运行下这个任务,例如我要显示红色的`hello xmake!`,只需要:
+
+```bash
+$ xmake echo -c red hello xmake!
+```
+
+也可以使用选项全名,并且加上高亮:
+
+```bash
+$ xmake echo --color=red --bright hello xmake!
+```
+
+最后面的可变参数列表,在`run`脚本中通过`option.get("contents")`获取,返回的是一个`table`类型的数组。
+
+##### task:set_category
+
+###### 设置任务类别
+
+仅仅用于菜单的分组显示,当然插件默认会用`plugin`,内置任务默认会用:`action`,但也仅仅只是个约定。
+
+<p class="tips">
+你可以使用任何自己定义的名字,相同名字会分组归类到一起显示,如果设置为`plugin`,就会显示到xmake的Plugins分组中去。
+</p>
+
+例如:
+
+```lua
+Plugins:
+ l, lua Run the lua script.
+ m, macro Run the given macro.
+ doxygen Generate the doxygen document.
+ project Generate the project file.
+ hello Hello xmake!
+ app2ipa Generate .ipa file from the given .app
+ echo Echo the given info!
+```
+
+如果没有调用这个接口设置分类,默认使用`Tasks`分组显示,代表普通任务。
+
+##### task:on_run
+
+###### 设置任务运行脚本
+
+可以有两种设置方式,最简单的就是设置内嵌函数:
+
+```lua
+task("hello")
+
+ on_run(function ()
+ print("hello xmake!")
+ end)
+```
+
+这种对于小任务很方便,也很简洁,但是对于大型任务就不太适用了,例如插件等,需要复杂的脚本支持。
+
+这个时候就需要独立的模块文件来设置运行脚本,例如:
+
+```lua
+task("hello")
+ on_run("main")
+```
+
+这里的`main`设置为脚本运行主入口模块,文件名为`main.lua`,放在定义`task`的`xmake.lua`的同目录下,当然你可以起其他文件名。
+
+目录结构如下:
+
+```
+projectdir
+ - xmake.lua
+ - main.lua
+```
+
+`main.lua`里面内容如下:
+
+```lua
+function main(...)
+ print("hello xmake!")
+end
+```
+
+就是一个简单的带`main`主函数的脚本文件,你可以通过[import](#import)导入各种扩展模块,实现复杂功能,例如:
+
+```lua
+-- 导入参数选项模块
+import("core.base.option")
+
+-- 入口函数
+function main(...)
+
+ -- 获取参数内容
+ print("color: %s", option.get("color"))
+end
+```
+
+你也可以在当前目录下,创建多个自定义的模块文件,通过[import](#import)导入后使用,例如:
+
+```
+projectdir
+ - xmake.lua
+ - main.lua
+ - module.lua
+```
+
+`module.lua`的内容如下:
+
+```lua
+-- 定义一个导出接口
+function hello()
+ print("hello xmake!")
+end
+```
+
+<p class="tip">
+私有接口,通过`_hello`带下滑线前缀命名,这样导入的模块就不会包含此接口,只在模块自身内部使用。
+</p>
+
+然后在`main.lua`进行调用:
+
+
+```lua
+import("module")
+
+function main(...)
+ module.hello()
+end
+```
+
+更多模块介绍见:[内置模块](#内置模块)和[扩展模块](扩展模块)
+
+其中,`main(...)`中参数,是通过`task.run`指定的,例如:
+
+```lua
+task.run("hello", {color="red"}, arg1, arg2, arg3)
+```
+
+里面的`arg1, arg2`这些就是传入`hello`任务`main(...)`入口的参数列表,而`{color="red"}`用来指定任务菜单中的参数选项。
+
+更加详细的`task.run`描述,见:[task.run](#task-run)
+
+#### 平台扩展
+
+xmake除了内置的一些构建平台,还可以自己扩展自定义构建平台,可以将自己实现的平台放置在以下目录即可, xmake会自动检测并且加载他们:
+
+| 平台目录 | 描述 |
+| --------------------------- | ------------------------------------ |
+| projectdir/.xmake/platforms | 当前工程的平台目录, 只对当前工程有效 |
+| globaldir/.xmake/platforms | 全局配置的平台目录,当前主机全局有效 |
+| installdir/xmake/platforms | xmake安装后内置的平台目录 |
+
+用户可根据不同需求,将自定义的平台放置在对应的目录中。
+
+<p class="warning">
+平台的扩展定义,尽量不要放到工程`xmake.lua`中去,新建一个单独的平台目录放置相关描述实现。
+</p>
+
+平台描述的目录结构:
+
+```
+platforms
+
+ - myplat1
+ - xmake.lua
+
+ - myplat2
+ - xmake.lua
+```
+
+其中`xmake.lua`为每个平台的主描述文件,相当于入口描述。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [platform](#platform) | 定义平台 | >= 2.0.1 |
+| [platform_end](#platform_end) | 结束定义平台 | >= 2.1.1 |
+| [set_os](#platformset_os) | 设置平台系统 | >= 2.0.1 |
+| [set_menu](#platformset_menu) | 设置平台菜单 | >= 2.0.1 |
+| [set_hosts](#platformset_hosts) | 设置平台支持的主机环境 | >= 2.0.1 |
+| [set_archs](#platformset_archs) | 设置平台支持的架构环境 | >= 2.0.1 |
+| [set_tooldirs](#platformset_tooldirs) | 设置平台工具的搜索目录 | >= 2.0.1 |
+| [on_load](#platformon_load) | 设置加载平台环境配置脚本 | >= 2.0.1 |
+| [on_check](#platformon_check) | 设置平台工具的检测脚本 | >= 2.0.1 |
+| [on_install](#platformon_install) | 设置平台相关的工程目标安装脚本 | >= 2.0.5 |
+| [on_uninstall](#platformon_uninstall) | 设置平台相关的工程目标卸载脚本 | >= 2.0.5 |
+
+##### platform
+
+###### 定义平台
+
+自定义一个平台域,例如:
+
+```lua
+platform("iphoneos")
+
+ -- 设置操作系统
+ set_os("ios")
+
+ -- 设置主机环境
+ set_hosts("macosx")
+
+ -- 设置支持的架构
+ set_archs("armv7", "armv7s", "arm64", "i386", "x86_64")
+
+ -- 设置gcc, clang等平台相关工具的搜索目录
+ set_tooldirs("/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin")
+
+ -- 设置gcc,clang等工具的检测脚本文件
+ on_check("check")
+
+ -- 设置平台初始化加载脚本文件,如果实现不复杂的话,可以使用内嵌函数
+ on_load("load")
+
+ -- 设置平台的帮助菜单
+ set_menu {
+ config =
+ {
+ {}
+ , {nil, "xcode_dir", "kv", "auto", "the xcode application directory" }
+ , {nil, "xcode_sdkver", "kv", "auto", "the sdk version for xcode" }
+ , {nil, "target_minver", "kv", "auto", "the target minimal version" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ }
+
+ , global =
+ {
+ {}
+ , {nil, "xcode_dir", "kv", "auto", "the xcode application directory" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ }
+ }
+
+```
+
+<p class="warning">
+是在`platforms`目录相关平台的`xmake.lua`中编写,而不是在工程目录的`xmake.lua`中。
+</p>
+
+##### platform_end
+
+###### 结束定义平台
+
+这是一个可选api,显示离开选项作用域,用法和[target_end](#target_end)类似。
+
+##### set_os
+
+###### 设置平台系统
+
+设置目标平台的操作系统,例如:`ios`, `android`, `linux`, `windows` 等
+
+```lua
+platform("iphoneos")
+ set_os("ios")
+```
+
+这个一般用于在自定义脚本和插件开发中,[core.platform.platform](#core-platform-platform)模块中进行访问,获取当前平台的操作系统。
+
+##### set_menu
+
+###### 设置平台菜单
+
+先给个设置的例子:
+
+```lua
+platform("iphoneos")
+ ...
+
+ -- 设置平台的帮助菜单
+ set_menu {
+ config =
+ {
+ {}
+ , {nil, "xcode_dir", "kv", "auto", "the xcode application directory" }
+ , {nil, "xcode_sdkver", "kv", "auto", "the sdk version for xcode" }
+ , {nil, "target_minver", "kv", "auto", "the target minimal version" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ }
+
+ , global =
+ {
+ {}
+ , {nil, "xcode_dir", "kv", "auto", "the xcode application directory" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ }
+ }
+```
+
+其中`config`组用来设置:`xmake f --help`中的本地工程菜单,`global`用来设置:`xmake g --help`全局平台配置中的菜单。
+
+具体设置格式可参考:[task:set_menu](#taskset_menu)。
+
+##### set_hosts
+
+###### 设置平台支持的主机环境
+
+用来设置当前目标平台支持主机构建环境,例如`iphoneos`平台可以在`macosx`主机系统上构建,那么可以设置为:
+
+```lua
+platform("iphoneos")
+ set_hosts("macosx")
+```
+
+而`android`平台可以同时在`linux`, "macosx", `windows`主机环境中构建,那么可以设置为:
+
+```lua
+platform("android")
+ set_hosts("linux", "macosx", "windows")
+```
+
+##### set_archs
+
+###### 设置平台支持的架构环境
+
+用来设置当前目标平台支持的编译架构环境,例如`iphoneos`平台可以构建`armv7`, `armv7s`, `arm64`, `i386`, `x86_64`等架构,那么可以设置为:
+
+```lua
+platform("iphoneos")
+ set_archs("armv7", "armv7s", "arm64", "i386", "x86_64")
+```
+
+配置好架构后,执行:`xmake f -h`,就会在对应arch参数描述,自动显示设置的架构列表:
+
+```
+ -a ARCH, --arch=ARCH Compile for the given architecture. (default: auto)
+ - android: armv5te armv6 armv7-a armv8-a arm64-v8a
+ - iphoneos: armv7 armv7s arm64 i386 x86_64
+ - linux: i386 x86_64
+ - macosx: i386 x86_64
+ - mingw: i386 x86_64
+ - watchos: armv7k i386
+ - windows: x86 x64 amd64 x86_amd64
+```
+
+##### set_tooldirs
+
+###### 设置平台工具的搜索目录
+
+xmake会自动检测当前平台支持的一些构建工具是否存在,例如编译器、链接器等,如果要提高检测通过率,可以在平台配置的时候,设置一些工具环境搜索目录,例如:
+
+```lua
+platform("linux")
+
+ -- 在linux下检测这些目录环境
+ set_tooldirs("/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin")
+```
+
+##### on_load
+
+###### 设置加载平台环境配置脚本
+
+一般用于在平台刚加载时,设置一些基本配置:生成目标文件命名格式、平台相关编译选项等
+
+```lua
+platform("windows")
+
+ -- on load
+ on_load(function ()
+
+ -- init the file formats
+ _g.formats = {}
+ _g.formats.static = {"", ".lib"}
+ _g.formats.object = {"", ".obj"}
+ _g.formats.shared = {"", ".dll"}
+ _g.formats.binary = {"", ".exe"}
+ _g.formats.symbol = {"", ".pdb"}
+
+ -- init flags for dlang
+ local dc_archs = { x86 = "-m32", x64 = "-m64", amd64 = "-m64", x86_amd64 = "-m64" }
+ _g.dcflags = { dc_archs[arch] or "" }
+ _g["dc-shflags"] = { dc_archs[arch] or "" }
+ _g["dc-ldflags"] = { dc_archs[arch] or "" }
+
+ -- ok
+ return _g
+ end)
+```
+
+如果加载逻辑比较复杂,可以独立成单独`init.lua`文件,然后设置为:
+
+```lua
+platform("xxxx")
+ on_load("init")
+```
+
+通过这种方式,会自动加载平台脚本目录下对应的`init.lua`文件,调用`function main() end`函数入口,完成复杂加载逻辑。
+
+##### on_check
+
+###### 设置平台工具的检测脚本
+
+由于每个平台检测的工具非常多,脚本比较复杂,一般直接独立成`check.lua`文件来实现检测逻辑,例如:
+
+```lua
+platform("xxx")
+ on_check("check")
+```
+
+具体的检测代码入口如下:
+
+```lua
+-- check it
+function main(kind)
+
+ -- init the check list of config
+ _g.config =
+ {
+ __check_arch
+ , checker.check_ccache
+ , _check_toolchains
+ }
+
+ -- init the check list of global
+ _g.global =
+ {
+ checker.check_ccache
+ , _check_ndk_sdkver
+ }
+
+ -- check it
+ checker.check(kind, _g)
+end
+```
+
+具体实现这里就不介绍了,可以参考xmake源码目录下的`platforms`平台配置代码: [check.lua](https://github.com/tboox/xmake/blob/master/xmake/platforms/macosx/check.lua)
+
+##### on_install
+
+###### 设置目标工程在指定平台的安装脚本
+
+具体实现逻辑见xmake源码:[install.lua](https://github.com/tboox/xmake/blob/master/xmake/platforms/macosx/install.lua)
+
+##### on_uninstall
+
+###### 设置目标工程在指定平台的卸载脚本
+
+具体实现逻辑见xmake源码:[uninstall.lua](https://github.com/tboox/xmake/blob/master/xmake/platforms/macosx/uninstall.lua)
+
+#### 语言扩展
+
+有待后续完善。。
+
+#### 工程模板
+
+##### template
+##### set_description
+##### set_projectdir
+##### add_macros
+##### add_macrofiles
+
+#### 内置变量
+
+xmake提供了 `$(varname)` 的语法,来支持内置变量的获取,例如:
+
+```lua
+add_cxflags("-I$(buildir)")
+```
+
+它将会在在实际编译的时候,将内置的 `buildir` 变量转换为实际的构建输出目录:`-I./build`
+
+一般内置变量可用于在传参时快速获取和拼接变量字符串,例如:
+
+```lua
+target("test")
+
+ -- 添加工程源码目录下的源文件
+ add_files("$(projectdir)/src/*.c")
+
+ -- 添加构建目录下的头文件搜索路径
+ add_includedirs("$(buildir)/inc")
+```
+
+也可以在自定义脚本的模块接口中使用,例如:
+
+```lua
+target("test")
+ on_run(function (target)
+ -- 复制当前脚本目录下的头文件到输出目录
+ os.cp("$(scriptdir)/xxx.h", "$(buildir)/inc")
+ end)
+```
+
+所有的内置变量,也可以通过[val](#val)接口,来获取他们的值。
+
+这种使用内置变量的方式,使得描述编写更加的简洁易读,下面是一些xmake内置的变量,可以直接获取:
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [$(os)](#var-os) | 获取当前编译平台的操作系统 | >= 2.0.1 |
+| [$(host)](#var-host) | 获取本机操作系统 | >= 2.0.1 |
+| [$(tmpdir)](#var-tmpdir) | 获取临时目录 | >= 2.0.1 |
+| [$(curdir)](#var-curdir) | 获取当前目录 | >= 2.0.1 |
+| [$(buildir)](#var-buildir) | 获取构建输出目录 | >= 2.0.1 |
+| [$(scriptdir)](#var-scriptdir) | 获取工程描述脚本目录 | >= 2.1.1 |
+| [$(globaldir)](#var-globaldir) | 获取全局配置目录 | >= 2.0.1 |
+| [$(configdir)](#var-configdir) | 获取本地工程配置目录 | >= 2.0.1 |
+| [$(programdir)](#var-programdir) | xmake安装脚本目录 | >= 2.1.5 |
+| [$(projectdir)](#var-projectdir) | 获取工程根目录 | >= 2.0.1 |
+| [$(shell)](#var-shell) | 执行外部shell命令 | >= 2.0.1 |
+| [$(env)](#var-env) | 获取外部环境变量 | >= 2.1.5 |
+| [$(reg)](#var-reg) | 获取windows注册表配置项的值 | >= 2.1.5 |
+
+当然这种变量模式,也是可以扩展的,默认通过`xmake f --var=val`命令,配置的参数都是可以直接获取,例如:
+
+```lua
+target("test")
+ add_defines("-DTEST=$(var)")
+```
+
+<p class="tip">
+所有`xmake f --xxx=...`配置的参数值,都是可以通过内置变量获取到,例如:`xmake f --arch=x86`对应`$(arch)`,其他的还有`$(plat)`, `$(mode)`等等。
+具体有哪些参数,可以通过:`xmake f -h`才查看。
+</p>
+
+既然支持直接从配置选项中获取,那么当然也就能很方便的扩展自定义的选项,来获取自定义的变量了,具体如何自定义选项见:[option](#option)
+
+##### var.$(os)
+
+###### 获取当前编译平台的操作系统
+
+如果当前编译的是iphoneos,那么这个值就是:`ios`,以此类推。
+
+##### var.$(host)
+
+###### 获取本机操作系统
+
+指的是当前本机环境的主机系统,如果你是在macOS上编译,那么系统就是:`macosx`
+
+##### var.$(tmpdir)
+
+###### 获取临时目录
+
+一般用于临时存放一些非永久性文件。
+
+##### var.$(curdir)
+
+###### 获取当前目录
+
+一般默认是执行`xmake`命令时的工程根目录,当然如果通过[os.cd](#os-cd)改变了目录的话,这个值也会一起改变。
+
+##### var.$(buildir)
+
+###### 获取当前的构建输出目录
+
+默认一般为当前工程根目录下的:`./build`目录,也可以通过执行:`xmake f -o /tmp/build`命令来修改默认的输出目录。
+
+##### var.$(scriptdir)
+
+###### 获取当前工程描述脚本的目录
+
+也就是对应`xmake.lua`所在的目录路径。
+
+##### var.$(globaldir)
+
+###### 全局配置目录
+
+xmake的`xmake g|global`全局配置命令,数据存储的目录路径,在里面可以放置一些自己的插件、平台脚本。
+
+默认为:`~/.config`
+
+##### var.$(configdir)
+
+###### 当前工程配置目录
+
+当前工程的配置存储目录,也就是`xmake f|config`配置命令的存储目录,默认为:`projectdir/.config`
+
+##### var.$(programdir)
+
+###### xmake安装脚本目录
+
+也就是`XMAKE_PROGRAM_DIR`环境变量所在目录,我们也可以通过设置这个环境量,来修改xmake的加载脚本,实现版本切换。
+
+##### var.$(projectdir)
+
+###### 工程根目录
+
+也就是`xmake -P xxx`命令中指定的目录路径,默认不指定就是`xmake`命令执行时的当前目录,一般用于定位工程文件。
+
+##### var.$(shell)
+
+###### 执行外部shell命令
+
+除了内置的变量处理,xmake还支持原生shell的运行,来处理一些xmake内置不支持的功能
+
+例如,现在有个需求,我想用在编译linux程序时,调用`pkg-config`获取到实际的第三方链接库名,可以这么做:
+
+```lua
+target("test")
+ set_kind("binary")
+ if is_plat("linux") then
+ add_ldflags("$(shell pkg-config --libs sqlite3)")
+ end
+```
+
+当然,xmake有自己的自动化第三库检测机制,一般情况下不需要这么麻烦,而且lua自身的脚本化已经很不错了。。
+
+但是这个例子可以说明,xmake是完全可以通过原生shell,来与一些第三方的工具进行配合使用。。
+
+##### var.$(env)
+
+###### 获取外部环境变量
+
+例如,可以通过获取环境变量中的路径:
+
+```lua
+target("test")
+ add_includedirs("$(env PROGRAMFILES)/OpenSSL/inc")
+```
+
+##### var.$(reg)
+
+###### 获取windows注册表配置项的值
+
+通过 `regpath; name` 的方式获取注册表中某个项的值:
+
+```lua
+print("$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name)")
+```
+
+#### 内置模块
+
+在自定义脚本、插件脚本、任务脚本、平台扩展、模板扩展等脚本代码中使用,也就是在类似下面的代码块中,可以使用这些模块接口:
+
+```lua
+on_run(function (target)
+ print("hello xmake!")
+end)
+```
+
+<p class="warning">
+为了保证外层的描述域尽可能简洁、安全,一般不建议在这个域使用接口和模块操作api,因此大部分模块接口只能再脚本域使用,来实现复杂功能。</br>
+当然少部分只读的内置接口还是可以在描述域使用的,具体见下表:
+</p>
+
+| 接口 | 描述 | 可使用域 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------------------------- | -------- |
+| [val](#val) | 获取内置变量的值 | 脚本域 | >= 2.1.5 |
+| [import](#import) | 导入扩展摸块 | 脚本域 | >= 2.0.1 |
+| [inherit](#inherit) | 导入并继承基类模块 | 脚本域 | >= 2.0.1 |
+| [ifelse](#ifelse) | 类似三元条件判断 | 描述域、脚本域 | >= 2.0.1 |
+| [try-catch-finally](#try-catch-finally) | 异常捕获 | 脚本域 | >= 2.0.1 |
+| [pairs](#pairs) | 用于遍历字典 | 描述域、脚本域 | >= 2.0.1 |
+| [ipairs](#ipairs) | 用于遍历数组 | 描述域、脚本域 | >= 2.0.1 |
+| [print](#print) | 换行打印终端日志 | 描述域、脚本域 | >= 2.0.1 |
+| [printf](#printf) | 无换行打印终端日志 | 脚本域 | >= 2.0.1 |
+| [cprint](#cprint) | 换行彩色打印终端日志 | 脚本域 | >= 2.0.1 |
+| [cprintf](#cprintf) | 无换行彩色打印终端日志 | 脚本域 | >= 2.0.1 |
+| [format](#format) | 格式化字符串 | 描述域、脚本域 | >= 2.0.1 |
+| [vformat](#vformat) | 格式化字符串,支持内置变量转义 | 脚本域 | >= 2.0.1 |
+| [raise](#raise) | 抛出异常中断程序 | 脚本域 | >= 2.0.1 |
+| [os](#os) | 系统操作模块 | 部分只读操作描述域、脚本域 | >= 2.0.1 |
+| [io](#io) | 文件操作模块 | 脚本域 | >= 2.0.1 |
+| [path](#path) | 路径操作模块 | 描述域、脚本域 | >= 2.0.1 |
+| [table](#table) | 数组和字典操作模块 | 描述域、脚本域 | >= 2.0.1 |
+| [string](#string) | 字符串操作模块 | 描述域、脚本域 | >= 2.0.1 |
+| [process](#process) | 进程操作模块 | 脚本域 | >= 2.0.1 |
+| [coroutine](#coroutine) | 协程操作模块 | 脚本域 | >= 2.0.1 |
+
+在描述域使用接口调用的实例如下,一般仅用于条件控制:
+
+```lua
+-- 扫描当前xmake.lua目录下的所有子目录,以每个目录的名字定义一个task任务
+for _, taskname in ipairs(os.dirs("*"), path.basename) do
+ task(taskname)
+ on_run(function ()
+ end)
+end
+```
+
+上面所说的脚本域、描述域主要是指:
+
+```lua
+-- 描述域
+target("test")
+
+ -- 描述域
+ set_kind("static")
+ add_files("src/*.c")
+
+ on_run(function (target)
+ -- 脚本域
+ end)
+
+-- 描述域
+```
+
+##### val
+
+###### 获取内置变量的值
+
+[内置变量](#内置变量)可以通过此接口直接获取,而不需要再加`$()`的包裹,使用更加简单,例如:
+
+```lua
+print(val("host"))
+print(val("env PATH"))
+local s = val("shell echo hello")
+```
+
+而用[vformat](#vformat)就比较繁琐了:
+
+```lua
+local s = vformat("$(shell echo hello)")
+```
+
+不过`vformat`支持字符串参数格式化,更加强大, 所以应用场景不同。
+
+##### import
+
+###### 导入扩展摸块
+
+import的主要用于导入xmake的扩展类库以及一些自定义的类库模块,一般用于:
+
+* 自定义脚本([on_build](#targeton_build), [on_run](#targeton_run) ..)
+* 插件开发
+* 模板开发
+* 平台扩展
+* 自定义任务task
+
+导入机制如下:
+
+1. 优先从当前脚本目录下导入
+2. 再从扩展类库中导入
+
+导入的语法规则:
+
+基于`.`的类库路径规则,例如:
+
+导入core核心扩展模块
+
+```lua
+import("core.base.option")
+import("core.project")
+import("core.base.task") -- 2.1.5 以前是 core.project.task
+import("core")
+
+function main()
+
+ -- 获取参数选项
+ print(option.get("version"))
+
+ -- 运行任务和插件
+ task.run("hello")
+ project.task.run("hello")
+ core.base.task.run("hello")
+end
+```
+
+导入当前目录下的自定义模块:
+
+目录结构:
+
+```
+plugin
+ - xmake.lua
+ - main.lua
+ - modules
+ - hello1.lua
+ - hello2.lua
+```
+
+在main.lua中导入modules
+
+```lua
+import("modules.hello1")
+import("modules.hello2")
+```
+
+导入后就可以直接使用里面的所有公有接口,私有接口用`_`前缀标示,表明不会被导出,不会被外部调用到。。
+
+除了当前目录,我们还可以导入其他指定目录里面的类库,例如:
+
+```lua
+import("hello3", {rootdir = "/home/xxx/modules"})
+```
+
+为了防止命名冲突,导入后还可以指定的别名:
+
+```lua
+import("core.platform.platform", {alias = "p"})
+
+function main()
+
+ -- 这样我们就可以使用p来调用platform模块的plats接口,获取所有xmake支持的平台列表了
+ table.dump(p.plats())
+end
+```
+
+import不仅可以导入类库,还支持导入的同时作为继承导入,实现模块间的继承关系
+
+```lua
+import("xxx.xxx", {inherit = true})
+```
+
+这样导入的不是这个模块的引用,而是导入的这个模块的所有公有接口本身,这样就会跟当前模块的接口进行合并,实现模块间的继承。
+
+2.1.5版本新增两个新属性:`import("xxx.xxx", {try = true, anonymous = true})`
+
+try为true,则导入的模块不存在的话,仅仅返回nil,并不会抛异常后中断xmake.
+anonymous为true,则导入的模块不会引入当前作用域,仅仅在import接口返回导入的对象引用。
+
+##### inherit
+
+###### 导入并继承基类模块
+
+这个等价于[import](#import)接口的`inherit`模式,也就是:
+
+```lua
+import("xxx.xxx", {inherit = true})
+```
+
+用`inherit`接口的话,会更简洁些:
+
+```lu
+inherit("xxx.xxx")
+```
+
+使用实例,可以参看xmake的tools目录下的脚本:[clang.lua](#https://github.com/tboox/xmake/blob/master/xmake/tools/clang.lua)
+
+这个就是clang工具模块继承了gcc的部分实现。
+
+##### ifelse
+
+###### 类似三元条件判断
+
+由于lua没有内置的三元运算符,通过封装`ifelse`接口,实现更加简洁的条件选择:
+
+```lua
+local ok = ifelse(a == 0, "ok", "no")
+```
+
+##### try-catch-finally
+
+###### 异常捕获
+
+lua原生并没有提供try-catch的语法来捕获异常处理,但是提供了`pcall/xpcall`等接口,可在保护模式下执行lua函数。
+
+因此,可以通过封装这两个接口,来实现try-catch块的捕获机制。
+
+我们可以先来看下,封装后的try-catch使用方式:
+
+```lua
+try
+{
+ -- try 代码块
+ function ()
+ error("error message")
+ end,
+
+ -- catch 代码块
+ catch
+ {
+ -- 发生异常后,被执行
+ function (errors)
+ print(errors)
+ end
+ }
+}
+```
+
+上面的代码中,在try块内部认为引发了一个异常,并且抛出错误消息,在catch中进行了捕获,并且将错误消息进行输出显示。
+
+而finally的处理,这个的作用是对于`try{}`代码块,不管是否执行成功,都会执行到finally块中
+
+也就说,其实上面的实现,完整的支持语法是:`try-catch-finally`模式,其中catch和finally都是可选的,根据自己的实际需求提供
+
+例如:
+
+```lua
+try
+{
+ -- try 代码块
+ function ()
+ error("error message")
+ end,
+
+ -- catch 代码块
+ catch
+ {
+ -- 发生异常后,被执行
+ function (errors)
+ print(errors)
+ end
+ },
+
+ -- finally 代码块
+ finally
+ {
+ -- 最后都会执行到这里
+ function (ok, errors)
+ -- 如果try{}中存在异常,ok为true,errors为错误信息,否则为false,errors为try中的返回值
+ end
+ }
+}
+
+```
+
+或者只有finally块:
+
+```lua
+try
+{
+ -- try 代码块
+ function ()
+ return "info"
+ end,
+
+ -- finally 代码块
+ finally
+ {
+ -- 由于此try代码没发生异常,因此ok为true,errors为返回值: "info"
+ function (ok, errors)
+ end
+ }
+}
+```
+
+处理可以在finally中获取try里面的正常返回值,其实在仅有try的情况下,也是可以获取返回值的:
+
+```lua
+-- 如果没发生异常,result 为返回值:"xxxx",否则为nil
+local result = try
+{
+ function ()
+ return "xxxx"
+ end
+}
+```
+
+在xmake的自定义脚本、插件开发中,也是完全基于此异常捕获机制
+
+这样使得扩展脚本的开发非常的精简可读,省去了繁琐的`if err ~= nil then`返回值判断,在发生错误时,xmake会直接抛出异常进行中断,然后高亮提示详细的错误信息。
+
+例如:
+
+```lua
+target("test")
+ set_kind("binary")
+ add_files("src/*.c")
+
+ -- 在编译完ios程序后,对目标程序进行ldid签名
+ after_build(function (target))
+ os.run("ldid -S %s", target:targetfile())
+ end
+```
+
+只需要一行`os.run`就行了,也不需要返回值判断是否运行成功,因为运行失败后,xmake会自动抛异常,中断程序并且提示错误
+
+如果你想在运行失败后,不直接中断xmake,继续往下运行,可以自己加个try快就行了:
+
+```lua
+target("test")
+ set_kind("binary")
+ add_files("src/*.c")
+
+ after_build(function (target))
+ try
+ {
+ function ()
+ os.run("ldid -S %s", target:targetfile())
+ end
+ }
+ end
+```
+
+如果还想捕获出错信息,可以再加个catch:
+
+```lua
+target("test")
+ set_kind("binary")
+ add_files("src/*.c")
+
+ after_build(function (target))
+ try
+ {
+ function ()
+ os.run("ldid -S %s", target:targetfile())
+ end,
+ catch
+ {
+ function (errors)
+ print(errors)
+ end
+ }
+ }
+ end
+```
+
+不过一般情况下,在xmake中写自定义脚本,是不需要手动加try-catch的,直接调用各种api,出错后让xmake默认的处理程序接管,直接中断就行了。。
+
+##### pairs
+
+###### 用于遍历字典
+
+这个是lua原生的内置api,在xmake中,在原有的行为上对其进行了一些扩展,来简化一些日常的lua遍历代码。
+
+先看下默认的原生写法:
+
+```lua
+local t = {a = "a", b = "b", c = "c", d = "d", e = "e", f = "f"}
+
+for key, val in pairs(t) do
+ print("%s: %s", key, val)
+end
+```
+
+这对于通常的遍历操作就足够了,但是如果我们相对其中每个遍历出来的元素,获取其大写,我们可以这么写:
+
+```lua
+for key, val in pairs(t, function (v) return v:upper() end) do
+ print("%s: %s", key, val)
+end
+```
+
+甚至传入一些参数到第二个`function`中,例如:
+
+```lua
+for key, val in pairs(t, function (v, a, b) return v:upper() .. a .. b end, "a", "b") do
+ print("%s: %s", key, val)
+end
+```
+
+##### ipairs
+
+###### 用于遍历数组
+
+这个是lua原生的内置api,在xmake中,在原有的行为上对其进行了一些扩展,来简化一些日常的lua遍历代码。
+
+先看下默认的原生写法:
+
+```lua
+for idx, val in ipairs({"a", "b", "c", "d", "e", "f"}) do
+ print("%d %s", idx, val)
+end
+```
+
+扩展写法类似[pairs](#pairs)接口,例如:
+
+```lua
+for idx, val in ipairs({"a", "b", "c", "d", "e", "f"}, function (v) return v:upper() end) do
+ print("%d %s", idx, val)
+end
+
+for idx, val in ipairs({"a", "b", "c", "d", "e", "f"}, function (v, a, b) return v:upper() .. a .. b end, "a", "b") do
+ print("%d %s", idx, val)
+end
+```
+
+这样可以简化`for`块代码的逻辑,例如我要遍历指定目录,获取其中的文件名,但不包括路径,就可以通过这种扩展方式,简化写法:
+
+```lua
+for _, filename in ipairs(os.dirs("*"), path.filename) do
+ -- ...
+end
+```
+
+##### print
+
+###### 换行打印终端日志
+
+此接口也是lua的原生接口,xmake在原有行为不变的基础上也进行了扩展,同时支持:格式化输出、多变量输出。
+
+先看下原生支持的方式:
+
+```lua
+print("hello xmake!")
+print("hello", "xmake!", 123)
+```
+
+并且同时还支持扩展的格式化写法:
+
+```lua
+print("hello %s!", "xmake")
+print("hello xmake! %d", 123)
+```
+
+xmake会同时支持这两种写法,内部会去自动智能检测,选择输出行为。
+
+##### printf
+
+###### 无换行打印终端日志
+
+类似[print](#print)接口,唯一的区别就是不换行。
+
+##### cprint
+
+###### 换行彩色打印终端日志
+
+行为类似[print](#print),区别就是此接口还支持彩色终端输出,并且支持`emoji`字符输出。
+
+例如:
+
+```lua
+ cprint('${bright}hello xmake')
+ cprint('${red}hello xmake')
+ cprint('${bright green}hello ${clear}xmake')
+ cprint('${blue onyellow underline}hello xmake${clear}')
+ cprint('${red}hello ${magenta}xmake')
+ cprint('${cyan}hello ${dim yellow}xmake')
+```
+
+显示结果如下:
+
+![cprint_colors](http://tboox.org/static/img/xmake/cprint_colors.png)
+
+跟颜色相关的描述,都放置在 `${ }` 里面,可以同时设置多个不同的属性,例如:
+
+```
+ ${bright red underline onyellow}
+```
+
+表示:高亮红色,背景黄色,并且带下滑线
+
+所有这些描述,都会影响后面一整行字符,如果只想显示部分颜色的文字,可以在结束位置,插入`${clear}`清楚前面颜色描述
+
+例如:
+
+```
+ ${red}hello ${clear}xmake
+```
+
+这样的话,仅仅hello是显示红色,其他还是正常默认黑色显示。
+
+其他颜色属于,我这里就不一一介绍,直接贴上xmake代码里面的属性列表吧:
+
+```lua
+ colors.keys =
+ {
+ -- 属性
+ reset = 0 -- 重置属性
+ , clear = 0 -- 清楚属性
+ , default = 0 -- 默认属性
+ , bright = 1 -- 高亮
+ , dim = 2 -- 暗色
+ , underline = 4 -- 下划线
+ , blink = 5 -- 闪烁
+ , reverse = 7 -- 反转颜色
+ , hidden = 8 -- 隐藏文字
+
+ -- 前景色
+ , black = 30
+ , red = 31
+ , green = 32
+ , yellow = 33
+ , blue = 34
+ , magenta = 35
+ , cyan = 36
+ , white = 37
+
+ -- 背景色
+ , onblack = 40
+ , onred = 41
+ , ongreen = 42
+ , onyellow = 43
+ , onblue = 44
+ , onmagenta = 45
+ , oncyan = 46
+ , onwhite = 47
+```
+
+除了可以色彩高亮显示外,如果你的终端是在macosx下,lion以上的系统,xmake还可以支持emoji表情的显示哦,对于不支持系统,会
+忽略显示,例如:
+
+```lua
+ cprint("hello xmake${beer}")
+ cprint("hello${ok_hand} xmake")
+```
+
+上面两行代码,我打印了一个homebrew里面经典的啤酒符号,下面那行打印了一个ok的手势符号,是不是很炫哈。。
+
+![cprint_emoji](http://tboox.org/static/img/xmake/cprint_emoji.png)
+
+所有的emoji表情,以及xmake里面对应的key,都可以通过[emoji符号](http://www.emoji-cheat-sheet.com/)里面找到。。
+
+2.1.7版本支持24位真彩色输出,如果终端支持的话:
+
+```lua
+import("core.base.colors")
+if colors.truecolor() then
+ cprint("${255;0;0}hello")
+ cprint("${on;255;0;0}hello${clear} xmake")
+ cprint("${bright 255;0;0 underline}hello")
+ cprint("${bright on;255;0;0 0;255;0}hello${clear} xmake")
+end
+```
+
+xmake对于truecolor的检测支持,是通过`$COLORTERM`环境变量来实现的,如果你的终端支持truecolor,可以手动设置此环境变量,来告诉xmake启用truecolor支持。
+
+可以通过下面的命令来启用和测试:
+
+```bash
+$ export COLORTERM=truecolor
+$ xmake --version
+```
+
+##### cprintf
+
+###### 无换行彩色打印终端日志
+
+此接口类似[cprint](#cprint),区别就是不换行输出。
+
+##### format
+
+###### 格式化字符串
+
+如果只是想格式化字符串,不进行输出,可以使用这个接口,此接口跟[string.format](#string-format)接口等价,只是个接口名简化版。
+
+```lua
+local s = format("hello %s", xmake)
+```
+
+##### vformat
+
+###### 格式化字符串,支持内置变量转义
+
+此接口跟[format](#format)接口类似,只是增加对内置变量的获取和转义支持。
+
+```lua
+local s = vformat("hello %s $(mode) $(arch) $(env PATH)", xmake)
+```
+
+##### raise
+
+###### 抛出异常中断程序
+
+如果想在自定义脚本、插件任务中中断xmake运行,可以使用这个接口跑出异常,如果上层没有显示调用[try-catch](#try-catch-finally)捕获的话,xmake就会中断执行,并且显示出错信息。
+
+```lua
+if (errors) raise(errors)
+```
+
+如果在try块中抛出异常,就会在catch和finally中进行errors信息捕获,具体见:[try-catch](#try-catch-finally)
+
+##### os
+
+系统操作模块,属于内置模块,无需使用[import](#import)导入,可直接脚本域调用其接口。
+
+此模块也是lua的原生模块,xmake在其基础上进行了扩展,提供更多实用的接口。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [os.cp](#os-cp) | 复制文件或目录 | >= 2.0.1 |
+| [os.mv](#os-mv) | 移动重命名文件或目录 | >= 2.0.1 |
+| [os.rm](#os-rm) | 删除文件或目录树 | >= 2.0.1 |
+| [os.cd](#os-cd) | 进入指定目录 | >= 2.0.1 |
+| [os.rmdir](#os-rmdir) | 删除目录树 | >= 2.0.1 |
+| [os.mkdir](#os-mkdir) | 创建指定目录 | >= 2.0.1 |
+| [os.isdir](#os-isdir) | 判断目录是否存在 | >= 2.0.1 |
+| [os.isfile](#os-isfile) | 判断文件是否存在 | >= 2.0.1 |
+| [os.exists](#os-exists) | 判断文件或目录是否存在 | >= 2.0.1 |
+| [os.dirs](#os-dirs) | 遍历获取指定目录下的所有目录 | >= 2.0.1 |
+| [os.files](#os-files) | 遍历获取指定目录下的所有文件 | >= 2.0.1 |
+| [os.filedirs](#os-filedirs) | 遍历获取指定目录下的所有文件或目录 | >= 2.0.1 |
+| [os.run](#os-run) | 安静运行程序 | >= 2.0.1 |
+| [os.runv](#os-runv) | 安静运行程序,带参数列表 | >= 2.1.5 |
+| [os.exec](#os-exec) | 回显运行程序 | >= 2.0.1 |
+| [os.execv](#os-execv) | 回显运行程序,带参数列表 | >= 2.1.5 |
+| [os.iorun](#os-iorun) | 运行并获取程序输出内容 | >= 2.0.1 |
+| [os.iorunv](#os-iorunv) | 运行并获取程序输出内容,带参数列表 | >= 2.1.5 |
+| [os.getenv](#os-getenv) | 获取环境变量 | >= 2.0.1 |
+| [os.setenv](#os-setenv) | 设置环境变量 | >= 2.0.1 |
+| [os.tmpdir](#os-tmpdir) | 获取临时目录路径 | >= 2.0.1 |
+| [os.tmpfile](#os-tmpfile) | 获取临时文件路径 | >= 2.0.1 |
+| [os.curdir](#os-curdir) | 获取当前目录路径 | >= 2.0.1 |
+| [os.scriptdir](#os-scriptdir) | 获取脚本目录路径 | >= 2.0.1 |
+| [os.programdir](#os-programdir) | 获取xmake安装主程序脚本目录 | >= 2.1.5 |
+| [os.projectdir](#os-projectdir) | 获取工程主目录 | >= 2.1.5 |
+| [os.arch](#os-arch) | 获取当前系统架构 | >= 2.0.1 |
+| [os.host](#os-host) | 获取当前主机系统 | >= 2.0.1 |
+
+###### os.cp
+
+- 复制文件或目录
+
+行为和shell中的`cp`命令类似,支持路径通配符匹配(使用的是lua模式匹配),支持多文件复制,以及内置变量支持。
+
+例如:
+
+```lua
+os.cp("$(scriptdir)/*.h", "$(projectdir)/src/test/**.h", "$(buildir)/inc")
+```
+
+上面的代码将:当前`xmake.lua`目录下的所有头文件、工程源码test目录下的头文件全部复制到`$(buildir)`输出目录中。
+
+其中`$(scriptdir)`, `$(projectdir)` 这些变量是xmake的内置变量,具体详情见:[内置变量](#内置变量)的相关文档。
+
+而`*.h`和`**.h`中的匹配模式,跟[add_files](#targetadd_files)中的类似,前者是单级目录匹配,后者是递归多级目录匹配。
+
+此接口同时支持目录的`递归复制`,例如:
+
+```lua
+-- 递归复制当前目录到临时目录
+os.cp("$(curdir)/test/", "$(tmpdir)/test")
+```
+
+<p class="tip">
+尽量使用`os.cp`接口,而不是`os.run("cp ..")`,这样更能保证平台一致性,实现跨平台构建描述。
+</p>
+
+###### os.mv
+
+- 移动重命名文件或目录
+
+跟[os.cp](#os-cp)的使用类似,同样支持多文件移动操作和模式匹配,例如:
+
+```lua
+-- 移动多个文件到临时目录
+os.mv("$(buildir)/test1", "$(buildir)/test2", "$(tmpdir)")
+
+-- 文件移动不支持批量操作,也就是文件重命名
+os.mv("$(buildir)/libtest.a", "$(buildir)/libdemo.a")
+```
+
+###### os.rm
+
+- 删除文件或目录树
+
+支持递归删除目录,批量删除操作,以及模式匹配和内置变量,例如:
+
+```lua
+os.rm("$(buildir)/inc/**.h", "$(buildir)/lib/")
+```
+
+###### os.cd
+
+- 进入指定目录
+
+这个操作用于目录切换,同样也支持内置变量,但是不支持模式匹配和多目录处理,例如:
+
+```lua
+-- 进入临时目录
+os.cd("$(tmpdir)")
+```
+
+如果要离开进入之前的目录,有多种方式:
+
+```lua
+-- 进入上级目录
+os.cd("..")
+
+-- 进入先前的目录,相当于:cd -
+os.cd("-")
+
+-- 进入目录前保存之前的目录,用于之后跨级直接切回
+local oldir = os.cd("./src")
+...
+os.cd(oldir)
+```
+
+###### os.rmdir
+
+- 仅删除目录
+
+如果不是目录就无法删除。
+
+###### os.mkdir
+
+- 创建目录
+
+支持批量创建和内置变量,例如:
+
+```lua
+os.mkdir("$(tmpdir)/test", "$(buildir)/inc")
+```
+
+###### os.isdir
+
+- 判断是否为目录
+
+如果目录不存在,则返回false
+
+```lua
+if os.isdir("src") then
+ -- ...
+end
+```
+
+###### os.isfile
+
+- 判断是否为文件
+
+如果文件不存在,则返回false
+
+```lua
+if os.isfile("$(buildir)/libxxx.a") then
+ -- ...
+end
+```
+
+###### os.exists
+
+- 判断文件或目录是否存在
+
+如果文件或目录不存在,则返回false
+
+```lua
+-- 判断目录存在
+if os.exists("$(buildir)") then
+ -- ...
+end
+
+-- 判断文件存在
+if os.exists("$(buildir)/libxxx.a") then
+ -- ...
+end
+```
+
+###### os.dirs
+
+- 遍历获取指定目录下的所有目录
+
+支持[add_files](#targetadd_files)中的模式匹配,支持递归和非递归模式遍历,返回的结果是一个table数组,如果获取不到,返回空数组,例如:
+
+```lua
+-- 递归遍历获取所有子目录
+for _, dir in ipairs(os.dirs("$(buildir)/inc/**")) do
+ print(dir)
+end
+```
+
+###### os.files
+
+- 遍历获取指定目录下的所有文件
+
+支持[add_files](#targetadd_files)中的模式匹配,支持递归和非递归模式遍历,返回的结果是一个table数组,如果获取不到,返回空数组,例如:
+
+```lua
+-- 非递归遍历获取所有子文件
+for _, filepath in ipairs(os.files("$(buildir)/inc/*.h")) do
+ print(filepath)
+end
+```
+
+###### os.filedirs
+
+- 遍历获取指定目录下的所有文件和目录
+
+支持[add_files](#targetadd_files)中的模式匹配,支持递归和非递归模式遍历,返回的结果是一个table数组,如果获取不到,返回空数组,例如:
+
+```lua
+-- 递归遍历获取所有子文件和目录
+for _, filedir in ipairs(os.filedirs("$(buildir)/**")) do
+ print(filedir)
+end
+```
+
+###### os.run
+
+- 安静运行原生shell命令
+
+用于执行第三方的shell命令,但不会回显输出,仅仅在出错后,高亮输出错误信息。
+
+此接口支持参数格式化、内置变量,例如:
+
+```lua
+-- 格式化参数传入
+os.run("echo hello %s!", "xmake")
+
+-- 列举构建目录文件
+os.run("ls -l $(buildir)")
+```
+
+<p class="warning">
+使用此接口执行shell命令,容易使构建跨平台性降低,对于`os.run("cp ..")`这种尽量使用`os.cp`代替。<br>
+如果必须使用此接口运行shell程序,请自行使用[config.plat](#config-plat)接口判断平台支持。
+</p>
+
+更加高级的进程运行和控制,见[process](#process)模块接口。
+
+###### os.runv
+
+- 安静运行原生shell命令,带参数列表
+
+跟[os.run](#os-run)类似,只是传递参数的方式是通过参数列表传递,而不是字符串命令,例如:
+
+```lua
+os.runv("echo", {"hello", "xmake!"})
+```
+
+###### os.exec
+
+- 回显运行原生shell命令
+
+与[os.run](#os-run)接口类似,唯一的不同是,此接口执行shell程序时,是带回显输出的,一般调试的时候用的比较多
+
+###### os.execv
+
+- 回显运行原生shell命令,带参数列表
+
+跟[os.execv](#os-execv)类似,只是传递参数的方式是通过参数列表传递,而不是字符串命令,例如:
+
+```lua
+os.execv("echo", {"hello", "xmake!"})
+```
+
+###### os.iorun
+
+- 安静运行原生shell命令并获取输出内容
+
+与[os.run](#os-run)接口类似,唯一的不同是,此接口执行shell程序后,会获取shell程序的执行结果,相当于重定向输出。
+
+可同时获取`stdout`, `stderr`中的内容,例如:
+
+```lua
+local outdata, errdata = os.iorun("echo hello xmake!")
+```
+
+###### os.iorunv
+
+- 安静运行原生shell命令并获取输出内容,带参数列表
+
+跟[os.iorunv](#os-iorunv)类似,只是传递参数的方式是通过参数列表传递,而不是字符串命令,例如:
+
+```lua
+local result, errors = os.iorunv("echo", {"hello", "xmake!"})
+```
+
+###### os.getenv
+
+- 获取系统环境变量
+
+```lua
+print(os.getenv("PATH"))
+```
+
+###### os.setenv
+
+- 设置系统环境变量
+
+```lua
+os.setenv("HOME", "/tmp/")
+```
+
+###### os.tmpdir
+
+- 获取临时目录
+
+跟[$(tmpdir)](#var-tmpdir)结果一致,只不过是直接获取返回一个变量,可以用后续字符串维护。
+
+```lua
+print(path.join(os.tmpdir(), "file.txt"))
+```
+
+等价于:
+
+```lua
+print("$(tmpdir)/file.txt"))
+```
+
+###### os.tmpfile
+
+- 获取临时文件路径
+
+用于获取生成一个临时文件路径,仅仅是个路径,文件需要自己创建。
+
+###### os.curdir
+
+- 获取当前目录路径
+
+跟[$(curdir)](#var-curdir)结果一致,只不过是直接获取返回一个变量,可以用后续字符串维护。
+
+用法参考:[os.tmpdir](#os-tmpdir)。
+
+###### os.scriptdir
+
+- 获取当前描述脚本的路径
+
+跟[$(scriptdir)](#var-scriptdir)结果一致,只不过是直接获取返回一个变量,可以用后续字符串维护。
+
+用法参考:[os.tmpdir](#os-tmpdir)。
+
+###### os.programdir
+
+- 获取xmake安装主程序脚本目录
+
+跟[$(programdir)](#var-programdir)结果一致,只不过是直接获取返回一个变量,可以用后续字符串维护。
+
+###### os.projectdir
+
+- 获取工程主目录
+
+跟[$(projectdir)](#var-projectdir)结果一致,只不过是直接获取返回一个变量,可以用后续字符串维护。
+
+###### os.arch
+
+- 获取当前系统架构
+
+也就是当前主机系统的默认架构,例如我在`linux x86_64`上执行xmake进行构建,那么返回值是:`x86_64`
+
+###### os.host
+
+- 获取当前主机的操作系统
+
+跟[$(host)](#var-host)结果一致,例如我在`linux x86_64`上执行xmake进行构建,那么返回值是:`linux`
+
+##### io
+
+io操作模块,扩展了lua内置的io模块,提供更多易用的接口。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [io.open](#io-open) | 打开文件用于读写 | >= 2.0.1 |
+| [io.load](#io-load) | 从指定路径文件反序列化加载所有table内容 | >= 2.0.1 |
+| [io.save](#io-save) | 序列化保存所有table内容到指定路径文件 | >= 2.0.1 |
+| [io.readfile](#io.readfile) | 从指定路径文件读取所有内容 | >= 2.1.3 |
+| [io.writefile](#io.writefile) | 写入所有内容到指定路径文件 | >= 2.1.3 |
+| [io.gsub](#io-gsub) | 全文替换指定路径文件的内容 | >= 2.0.1 |
+| [io.tail](#io-tail) | 读取和显示文件的尾部内容 | >= 2.0.1 |
+| [io.cat](#io-cat) | 读取和显示文件的所有内容 | >= 2.0.1 |
+| [io.print](#io-print) | 带换行格式化输出内容到文件 | >= 2.0.1 |
+| [io.printf](#io-printf) | 无换行格式化输出内容到文件 | >= 2.0.1 |
+
+###### io.open
+
+- 打开文件用于读写
+
+这个是属于lua的原生接口,详细使用可以参看lua的官方文档:[The Complete I/O Model](https://www.lua.org/pil/21.2.html)
+
+如果要读取文件所有内容,可以这么写:
+
+```lua
+local file = io.open("$(tmpdir)/file.txt", "r")
+if file then
+ local data = file:read("*all")
+ file:close()
+end
+```
+
+或者可以使用[io.readfile](#io.readfile)更加快速地读取。
+
+如果要写文件,可以这么操作:
+
+```lua
+-- 打开文件:w 为写模式, a 为追加写模式
+local file = io.open("xxx.txt", "w")
+if file then
+
+ -- 用原生的lua接口写入数据到文件,不支持格式化,无换行,不支持内置变量
+ file:write("hello xmake\n")
+
+ -- 用xmake扩展的接口写入数据到文件,支持格式化,无换行,不支持内置变量
+ file:writef("hello %s\n", "xmake")
+
+ -- 使用xmake扩展的格式化传参写入一行,带换行符,并且支持内置变量
+ file:print("hello %s and $(buildir)", "xmake")
+
+ -- 使用xmake扩展的格式化传参写入一行,无换行符,并且支持内置变量
+ file:printf("hello %s and $(buildir) \n", "xmake")
+
+ -- 关闭文件
+ file:close()
+end
+```
+
+###### io.load
+
+- 从指定路径文件反序列化加载所有table内容
+
+可以从文件中加载序列化好的table内容,一般与[io.save](#io-save)配合使用,例如:
+
+```lua
+-- 加载序列化文件的内容到table
+local data = io.load("xxx.txt")
+if data then
+
+ -- 在终端中dump打印整个table中内容,格式化输出
+ table.dump(data)
+end
+```
+
+###### io.save
+
+- 序列化保存所有table内容到指定路径文件
+
+可以序列化存储table内容到指定文件,一般与[io.load](#io-load)配合使用,例如:
+
+```lua
+io.save("xxx.txt", {a = "a", b = "b", c = "c"})
+```
+
+存储结果为:
+
+```
+{
+ ["b"] = "b"
+, ["a"] = "a"
+, ["c"] = "c"
+}
+```
+
+###### io.readfile
+
+- 从指定路径文件读取所有内容
+
+可在不打开文件的情况下,直接读取整个文件的内容,更加的方便,例如:
+
+```lua
+local data = io.readfile("xxx.txt")
+```
+
+###### io.writefile
+
+- 写入所有内容到指定路径文件
+
+可在不打开文件的情况下,直接写入整个文件的内容,更加的方便,例如:
+
+```lua
+io.writefile("xxx.txt", "all data")
+```
+
+###### io.gsub
+
+- 全文替换指定路径文件的内容
+
+类似[string.gsub](#string-gsub)接口,全文模式匹配替换内容,不过这里是直接操作文件,例如:
+
+```lua
+-- 移除文件所有的空白字符
+io.gsub("xxx.txt", "%s+", "")
+```
+
+###### io.tail
+
+- 读取和显示文件的尾部内容
+
+读取文件尾部指定行数的数据,并显示,类似`cat xxx.txt | tail -n 10`命令,例如:
+
+```lua
+-- 显示文件最后10行内容
+io.tail("xxx.txt", 10)
+```
+
+###### io.cat
+
+- 读取和显示文件的所有内容
+
+读取文件的所有内容并显示,类似`cat xxx.txt`命令,例如:
+
+```lua
+io.cat("xxx.txt")
+```
+
+###### io.print
+
+- 带换行格式化输出内容到文件
+
+直接格式化传参输出一行字符串到文件,并且带换行,例如:
+
+```lua
+io.print("xxx.txt", "hello %s!", "xmake")
+```
+
+###### io.printf
+
+- 无换行格式化输出内容到文件
+
+直接格式化传参输出一行字符串到文件,不带换行,例如:
+
+```lua
+io.printf("xxx.txt", "hello %s!\n", "xmake")
+```
+
+##### path
+
+路径操作模块,实现跨平台的路径操作,这是xmake的一个自定义的模块。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [path.join](#path-join) | 拼接路径 | >= 2.0.1 |
+| [path.translate](#path-translate) | 转换路径到当前平台的路径风格 | >= 2.0.1 |
+| [path.basename](#path-basename) | 获取路径最后不带后缀的文件名 | >= 2.0.1 |
+| [path.filename](#path-filename) | 获取路径最后带后缀的文件名 | >= 2.0.1 |
+| [path.extension](#path-extension) | 获取路径的后缀名 | >= 2.0.1 |
+| [path.directory](#path-directory) | 获取路径最后的目录名 | >= 2.0.1 |
+| [path.relative](#path-relative) | 转换成相对路径 | >= 2.0.1 |
+| [path.absolute](#path-absolute) | 转换成绝对路径 | >= 2.0.1 |
+| [path.is_absolute](#path-is_absolute) | 判断是否为绝对路径 | >= 2.0.1 |
+
+###### path.join
+
+- 拼接路径
+
+将多个路径项进行追加拼接,由于`windows/unix`风格的路径差异,使用api来追加路径更加跨平台,例如:
+
+```lua
+print(path.join("$(tmpdir)", "dir1", "dir2", "file.txt"))
+```
+
+上述拼接在unix上相当于:`$(tmpdir)/dir1/dir2/file.txt`,而在windows上相当于:`$(tmpdir)\\dir1\\dir2\\file.txt`
+
+如果觉得这样很繁琐,不够清晰简洁,可以使用:[path.translate](path-translate)方式,格式化转换路径字符串到当前平台支持的格式。
+
+###### path.translate
+
+- 转换路径到当前平台的路径风格
+
+格式化转化指定路径字符串到当前平台支持的路径风格,同时支持`windows/unix`格式的路径字符串参数传入,甚至混合传入,例如:
+
+```lua
+print(path.translate("$(tmpdir)/dir/file.txt"))
+print(path.translate("$(tmpdir)\\dir\\file.txt"))
+print(path.translate("$(tmpdir)\\dir/dir2//file.txt"))
+```
+
+上面这三种不同格式的路径字符串,经过`translate`规范化后,就会变成当前平台支持的格式,并且会去掉冗余的路径分隔符。
+
+###### path.basename
+
+- 获取路径最后不带后缀的文件名
+
+```lua
+print(path.basename("$(tmpdir)/dir/file.txt"))
+```
+
+显示结果为:`file`
+
+###### path.filename
+
+- 获取路径最后带后缀的文件名
+
+```lua
+print(path.filename("$(tmpdir)/dir/file.txt"))
+```
+
+显示结果为:`file.txt`
+
+###### path.extension
+
+- 获取路径的后缀名
+
+```lua
+print(path.extensione("$(tmpdir)/dir/file.txt"))
+```
+
+显示结果为:`.txt`
+
+###### path.directory
+
+- 获取路径最后的目录名
+
+```lua
+print(path.directory("$(tmpdir)/dir/file.txt"))
+```
+
+显示结果为:`dir`
+
+###### path.relative
+
+- 转换成相对路径
+
+```lua
+print(path.relative("$(tmpdir)/dir/file.txt", "$(tmpdir)"))
+```
+
+显示结果为:`dir/file.txt`
+
+第二个参数是指定相对的根目录,如果不指定,则默认相对当前目录:
+
+```lua
+os.cd("$(tmpdir)")
+print(path.relative("$(tmpdir)/dir/file.txt"))
+```
+
+这样结果是一样的。
+
+###### path.absolute
+
+- 转换成绝对路径
+
+```lua
+print(path.absolute("dir/file.txt", "$(tmpdir)"))
+```
+
+显示结果为:`$(tmpdir)/dir/file.txt`
+
+第二个参数是指定相对的根目录,如果不指定,则默认相对当前目录:
+
+```lua
+os.cd("$(tmpdir)")
+print(path.absolute("dir/file.txt"))
+```
+
+这样结果是一样的。
+
+###### path.is_absolute
+
+- 判断是否为绝对路径
+
+```lua
+if path.is_absolute("/tmp/file.txt") then
+ -- 如果是绝对路径
+end
+```
+
+##### table
+
+table属于lua原生提供的模块,对于原生接口使用可以参考:[lua官方文档](http://www.lua.org/manual/5.1/manual.html#5.5)
+
+xmake中对其进行了扩展,增加了一些扩展接口:
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [table.join](#table-join) | 合并多个table并返回 | >= 2.0.1 |
+| [table.join2](#table-join2) | 合并多个table到第一个table | >= 2.0.1 |
+| [table.dump](#table-dump) | 输出table的所有内容 | >= 2.0.1 |
+| [table.unique](#table-unique) | 对table中的内容进行去重 | >= 2.0.1 |
+| [table.slice](#table-slice) | 获取table的切片 | >= 2.0.1 |
+
+###### table.join
+
+- 合并多个table并返回
+
+可以将多个table里面的元素进行合并后,返回到一个新的table中,例如:
+
+```lua
+local newtable = table.join({1, 2, 3}, {4, 5, 6}, {7, 8, 9})
+```
+
+结果为:`{1, 2, 3, 4, 5, 6, 7, 8, 9}`
+
+并且它也支持字典的合并:
+
+```lua
+local newtable = table.join({a = "a", b = "b"}, {c = "c"}, {d = "d"})
+```
+
+结果为:`{a = "a", b = "b", c = "c", d = "d"}`
+
+###### table.join2
+
+- 合并多个table到第一个table
+
+类似[table.join](#table.join),唯一的区别是,合并的结果放置在第一个参数中,例如:
+
+```lua
+local t = {0, 9}
+table.join2(t, {1, 2, 3})
+```
+
+结果为:`t = {0, 9, 1, 2, 3}`
+
+###### table.dump
+
+- 输出table的所有内容
+
+递归格式化打印table中的所有内容,一般用于调试, 例如:
+
+```lua
+table.dump({1, 2, 3})
+```
+
+结果为:`{1, 2, 3}`
+
+###### table.unique
+
+- 对table中的内容进行去重
+
+去重table的元素,一般用于数组table,例如:
+
+```lua
+local newtable = table.unique({1, 1, 2, 3, 4, 4, 5})
+```
+
+结果为:`{1, 2, 3, 4, 5}`
+
+###### table.slice
+
+- 获取table的切片
+
+用于提取数组table的部分元素,例如:
+
+```lua
+-- 提取第4个元素后面的所有元素,结果:{4, 5, 6, 7, 8, 9}
+table.slice({1, 2, 3, 4, 5, 6, 7, 8, 9}, 4)
+
+-- 提取第4-8个元素,结果:{4, 5, 6, 7, 8}
+table.slice({1, 2, 3, 4, 5, 6, 7, 8, 9}, 4, 8)
+
+-- 提取第4-8个元素,间隔步长为2,结果:{4, 6, 8}
+table.slice({1, 2, 3, 4, 5, 6, 7, 8, 9}, 4, 8, 2)
+```
+
+##### string
+
+字符串模块为lua原生自带的模块,具体使用见:[lua官方手册](http://www.lua.org/manual/5.1/manual.html#5.4)
+
+xmake中对其进行了扩展,增加了一些扩展接口:
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [string.startswith](#string-startswith) | 判断字符串开头是否匹配 | >= 1.0.1 |
+| [string.endswith](#string-endswith) | 判断字符串结尾是否匹配 | >= 1.0.1 |
+| [string.split](#string-split) | 分割字符串 | >= 1.0.1 |
+| [string.trim](#string-trim) | 去掉字符串左右空白字符 | >= 1.0.1 |
+| [string.ltrim](#string-ltrim) | 去掉字符串左边空白字符 | >= 1.0.1 |
+| [string.rtrim](#string-rtrim) | 去掉字符串右边空白字符 | >= 1.0.1 |
+
+###### string.startswith
+
+- 判断字符串开头是否匹配
+
+```lua
+local s = "hello xmake"
+if s:startswith("hello") then
+ print("match")
+end
+```
+
+###### string.endswith
+
+- 判断字符串结尾是否匹配
+
+```lua
+local s = "hello xmake"
+if s:endswith("xmake") then
+ print("match")
+end
+```
+
+###### string.split
+
+- 分割字符串
+
+通过指定的分隔符进行字符串分割,分隔符可以是:字符,字符串、模式匹配字符串,例如:
+
+```lua
+local s = "hello xmake!"
+s:split("%s+")
+```
+
+根据连续空白字符进行分割,结果为:`hello`, `xmake!`
+
+```lua
+local s = "hello,xmake:123"
+s:split("[,:]")
+```
+
+上面的代码根据`,`或者`:`字符进行分割,结果为:`hello`, `xmake`, `123`
+
+###### string.trim
+
+- 去掉字符串左右空白字符
+
+```lua
+string.trim(" hello xmake! ")
+```
+
+结果为:"hello xmake!"
+
+###### string.ltrim
+
+- 去掉字符串左边空白字符
+
+```lua
+string.ltrim(" hello xmake! ")
+```
+
+结果为:"hello xmake! "
+
+###### string.rtrim
+
+- 去掉字符串右边空白字符
+
+```lua
+string.rtrim(" hello xmake! ")
+```
+
+结果为:" hello xmake!"
+
+##### process
+
+这个是xmake扩展的进程控制模块,用于更加灵活的控制进程,比起:[os.run](#os-run)系列灵活性更高,也更底层。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [process.open](#process-open) | 打开进程 | >= 2.0.1 |
+| [process.wait](#process-wait) | 等待进程结束 | >= 2.0.1 |
+| [process.close](#process-close) | 关闭进程对象 | >= 2.0.1 |
+| [process.waitlist](#process-waitlist) | 同时等待多个进程 | >= 2.0.1 |
+
+###### process.open
+
+- 打开进程
+
+通过路径创建运行一个指定程序,并且返回对应的进程对象:
+
+```lua
+-- 打开进程,后面两个参数指定需要捕获的stdout, stderr文件路径
+local proc = process.open("echo hello xmake!", outfile, errfile)
+if proc then
+
+ -- 等待进程执行完成
+ --
+ -- 参数二为等待超时,-1为永久等待,0为尝试获取进程状态
+ -- 返回值waitok为等待状态:1为等待进程正常结束,0为进程还在运行中,-1位等待失败
+ -- 返回值status为,等待进程结束后,进程返回的状态码
+ local waitok, status = process.wait(proc, -1)
+
+ -- 释放进程对象
+ process.close(proc)
+end
+```
+
+###### process.wait
+
+- 等待进程结束
+
+具体使用见:[process.open](#process-open)
+
+###### process.close
+
+- 关闭进程对象
+
+具体使用见:[process.open](#process-open)
+
+###### process.waitlist
+
+- 同时等待多个进程
+
+```lua
+-- 第二个参数是等待超时,返回进程状态列表
+for _, procinfo in ipairs(process.waitlist(procs, -1)) do
+
+ -- 每个进程的:进程对象、进程pid、进程结束状态码
+ local proc = procinfo[1]
+ local procid = procinfo[2]
+ local status = procinfo[3]
+
+end
+```
+
+##### coroutine
+
+协程模块是lua原生自带的模块,具使用见:[lua官方手册](http://www.lua.org/manual/5.1/manual.html#5.2)
+
+#### 扩展模块
+
+所有扩展模块的使用,都需要通过[import](#import)接口,进行导入后才能使用。
+
+##### core.base.option
+
+一般用于获取xmake命令参数选项的值,常用于插件开发。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [option.get](#option-get) | 获取参数选项值 | >= 2.0.1 |
+
+###### option.get
+
+- 获取参数选项值
+
+在插件开发中用于获取参数选项值,例如:
+
+```lua
+-- 导入选项模块
+import("core.base.option")
+
+-- 插件入口函数
+function main(...)
+ print(option.get("info"))
+end
+```
+
+上面的代码获取hello插件,执行:`xmake hello --info=xxxx` 命令时候传入的`--info=`选项的值,并显示:`xxxx`
+
+对于非main入口的task任务或插件,可以这么使用:
+
+```lua
+task("hello")
+ on_run(function ())
+ import("core.base.option")
+ print(option.get("info"))
+ end)
+```
+
+##### core.base.global
+
+用于获取xmake全局的配置信息,也就是`xmake g|global --xxx=val` 传入的参数选项值。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [global.get](#global-get) | 获取指定配置值 | >= 2.0.1 |
+| [global.load](#global-load) | 加载配置 | >= 2.0.1 |
+| [global.directory](#global-directory) | 获取全局配置信息目录 | >= 2.0.1 |
+| [global.dump](#global-dump) | 打印输出所有全局配置信息 | >= 2.0.1 |
+
+<p class="tip">
+2.1.5版本之前为`core.project.global`。
+</p>
+
+###### global.get
+
+- 获取指定配置值
+
+类似[config.get](#config-get),唯一的区别就是这个是从全局配置中获取。
+
+###### global.load
+
+- 加载配置
+
+类似[global.get](#global-get),唯一的区别就是这个是从全局配置中加载。
+
+###### global.directory
+
+- 获取全局配置信息目录
+
+默认为`~/.config`目录。
+
+###### global.dump
+
+- 打印输出所有全局配置信息
+
+输出结果如下:
+
+```lua
+{
+ clean = true
+, ccache = "ccache"
+, xcode_dir = "/Applications/Xcode.app"
+}
+```
+
+##### core.base.task
+
+用于任务操作,一般用于在自定义脚本中、插件任务中,调用运行其他task任务。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [task.run](#task-run) | 运行指定任务 | >= 2.0.1 |
+
+<p class="tip">
+2.1.5版本之前为`core.project.task`。
+</p>
+
+###### task.run
+
+- 运行指定任务
+
+用于在自定义脚本、插件任务中运行[task](#task)定义的任务或插件,例如:
+
+```lua
+task("hello")
+ on_run(function ()
+ print("hello xmake!")
+ end)
+
+target("demo")
+ on_clean(function(target)
+
+ -- 导入task模块
+ import("core.base.task")
+
+ -- 运行这个hello task
+ task.run("hello")
+ end)
+```
+
+我们还可以在运行任务时,增加参数传递,例如:
+
+```lua
+task("hello")
+ on_run(function (arg1, arg2)
+ print("hello xmake: %s %s!", arg1, arg2)
+ end)
+
+target("demo")
+ on_clean(function(target)
+
+ -- 导入task
+ import("core.base.task")
+
+ -- {} 这个是给第一种选项传参使用,这里置空,这里在最后面传入了两个参数:arg1, arg2
+ task.run("hello", {}, "arg1", "arg2")
+ end)
+```
+
+对于`task.run`的第二个参数,用于传递命令行菜单中的选项,而不是直接传入`function (arg, ...)`函数入口中,例如:
+
+```lua
+-- 导入task
+import("core.base.task")
+
+-- 插件入口
+function main(...)
+
+ -- 运行内置的xmake配置任务,相当于:xmake f|config --plat=iphoneos --arch=armv7
+ task.run("config", {plat="iphoneos", arch="armv7"})
+emd
+```
+
+##### core.tool.linker
+
+链接器相关操作,常用于插件开发。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [linker.link](#linker-link) | 执行链接 | >= 2.0.1 |
+| [linker.linkcmd](#linker-linkcmd) | 获取链接命令行 | >= 2.0.1 |
+| [linker.linkargv](#linker-linkargv) | 获取链接命令行列表 | >= 2.1.5 |
+| [linker.linkflags](#linker-linkflags) | 获取链接选项 | >= 2.0.1 |
+| [linker.has_flags](#linker-has_flags) | 判断指定链接选项是否支持 | >= 2.1.5 |
+
+###### linker.link
+
+- 执行链接
+
+针对target,链接指定对象文件列表,生成对应的目标文件,例如:
+
+```lua
+linker.link({"a.o", "b.o", "c.o"}, target:targetfile(), {target = target})
+```
+
+其中[target](#target),为工程目标,这里传入,主要用于获取target特定的链接选项,具体如果获取工程目标对象,见:[core.project.project](#core-project-project)
+
+当然也可以不指定target,例如:
+
+```lua
+linker.link("binary", "cc", {"a.o", "b.o", "c.o"}, "/tmp/targetfile")
+```
+
+###### linker.linkcmd
+
+- 获取链接命令行字符串
+
+直接获取[linker.link](#linker-link)中执行的命令行字符串,相当于:
+
+```lua
+local cmdstr = linker.linkcmd("static", "cxx", {"a.o", "b.o", "c.o"}, target:targetfile(), {target = target})
+```
+
+注:后面`{target = target}`扩展参数部分是可选的,如果传递了target对象,那么生成的链接命令,会加上这个target配置对应的链接选项。
+
+并且还可以自己传递各种配置,例如:
+
+```lua
+local cmdstr = linker.linkcmd("static", "cxx", {"a.o", "b.o", "c.o"}, target:targetfile(), {config = {linkdirs = "/usr/lib"}})
+```
+
+###### linker.linkargv
+
+- 获取链接命令行参数列表
+
+跟[linker.linkcmd](#linker-linkcmd)稍微有点区别的是,此接口返回的是参数列表,table表示,更加方便操作:
+
+```lua
+local program, argv = linker.linkargv("static", "cxx", {"a.o", "b.o", "c.o"}, target:targetfile(), {target = target})
+```
+
+其中返回的第一个值是主程序名,后面是参数列表,而`os.args(table.join(program, argv))`等价于`linker.linkcmd`。
+
+我们也可以通过传入返回值给[os.runv](#os-runv)来直接运行它:`os.runv(linker.linkargv(..))`
+
+###### linker.linkflags
+
+- 获取链接选项
+
+获取[linker.linkcmd](#linker-linkcmd)中的链接选项字符串部分,不带shellname和对象文件列表,并且是按数组返回,例如:
+
+```lua
+local flags = linker.linkflags("shared", "cc", {target = target})
+for _, flag in ipairs(flags) do
+ print(flag)
+end
+```
+
+返回的是flags的列表数组。
+
+###### linker.has_flags
+
+- 判断指定链接选项是否支持
+
+虽然通过[lib.detect.has_flags](detect-has_flags)也能判断,但是那个接口更加底层,需要指定链接器名称
+而此接口只需要指定target的目标类型,源文件类型,它会自动切换选择当前支持的链接器。
+
+```lua
+if linker.has_flags(target:targetkind(), target:sourcekinds(), "-L/usr/lib -lpthread") then
+ -- ok
+end
+```
+
+##### core.tool.compiler
+
+编译器相关操作,常用于插件开发。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [compiler.compile](#compiler-compile) | 执行编译 | >= 2.0.1 |
+| [compiler.compcmd](#compiler-compcmd) | 获取编译命令行 | >= 2.0.1 |
+| [compiler.compargv](#compiler-compargv) | 获取编译命令行列表 | >= 2.1.5 |
+| [compiler.compflags](#compiler-compflags) | 获取编译选项 | >= 2.0.1 |
+| [compiler.has_flags](#compiler-has_flags) | 判断指定编译选项是否支持 | >= 2.1.5 |
+| [compiler.features](#compiler-features) | 获取所有编译器特性 | >= 2.1.5 |
+| [compiler.has_features](#compiler-has_features) | 判断指定编译特性是否支持 | >= 2.1.5 |
+
+###### compiler.compile
+
+- 执行编译
+
+针对target,链接指定对象文件列表,生成对应的目标文件,例如:
+
+```lua
+compiler.compile("xxx.c", "xxx.o", "xxx.h.d", {target = target})
+```
+
+其中[target](#target),为工程目标,这里传入主要用于获取taeget的特定编译选项,具体如果获取工程目标对象,见:[core.project.project](#core-project-project)
+
+而`xxx.h.d`文件用于存储为此源文件的头文件依赖文件列表,最后这两个参数都是可选的,编译的时候可以不传他们:
+
+```lua
+compiler.compile("xxx.c", "xxx.o")
+```
+
+来单纯编译一个源文件。
+
+###### compiler.compcmd
+
+- 获取编译命令行
+
+直接获取[compiler.compile](#compiler-compile)中执行的命令行字符串,相当于:
+
+```lua
+local cmdstr = compiler.compcmd("xxx.c", "xxx.o", {target = target})
+```
+
+注:后面`{target = target}`扩展参数部分是可选的,如果传递了target对象,那么生成的编译命令,会加上这个target配置对应的链接选项。
+
+并且还可以自己传递各种配置,例如:
+
+```lua
+local cmdstr = compiler.compcmd("xxx.c", "xxx.o", {config = {includedirs = "/usr/include", defines = "DEBUG"}})
+```
+
+通过target,我们可以导出指定目标的所有源文件编译命令:
+
+```lua
+import("core.project.project")
+
+for _, target in pairs(project.targets()) do
+ for sourcekind, sourcebatch in pairs(target:sourcebatches()) do
+ for index, objectfile in ipairs(sourcebatch.objectfiles) do
+ local cmdstr = compiler.compcmd(sourcebatch.sourcefiles[index], objectfile, {target = target})
+ end
+ end
+end
+```
+
+###### compiler.compargv
+
+- 获取编译命令行列表
+
+跟[compiler.compargv](#compiler-compargv)稍微有点区别的是,此接口返回的是参数列表,table表示,更加方便操作:
+
+```lua
+local program, argv = compiler.compargv("xxx.c", "xxx.o")
+```
+
+###### compiler.compflags
+
+- 获取编译选项
+
+获取[compiler.compcmd](#compiler-compcmd)中的编译选项字符串部分,不带shellname和文件列表,例如:
+
+```lua
+local flags = compiler.compflags(sourcefile, {target = target})
+for _, flag in ipairs(flags) do
+ print(flag)
+end
+```
+
+返回的是flags的列表数组。
+
+###### compiler.has_flags
+
+- 判断指定编译选项是否支持
+
+虽然通过[lib.detect.has_flags](detect-has_flags)也能判断,但是那个接口更加底层,需要指定编译器名称。
+而此接口只需要指定语言类型,它会自动切换选择当前支持的编译器。
+
+```lua
+-- 判断c语言编译器是否支持选项: -g
+if compiler.has_flags("c", "-g") then
+ -- ok
+end
+
+-- 判断c++语言编译器是否支持选项: -g
+if compiler.has_flags("cxx", "-g") then
+ -- ok
+end
+```
+
+###### compiler.features
+
+- 获取所有编译器特性
+
+虽然通过[lib.detect.features](detect-features)也能获取,但是那个接口更加底层,需要指定编译器名称。
+而此接口只需要指定语言类型,它会自动切换选择当前支持的编译器,然后获取当前的编译器特性列表。
+
+```lua
+-- 获取当前c语言编译器的所有特性
+local features = compiler.features("c")
+
+-- 获取当前c++语言编译器的所有特性,启用c++11标准,否则获取不到新标准的特性
+local features = compiler.features("cxx", {config = {cxxflags = "-std=c++11"}})
+
+-- 获取当前c++语言编译器的所有特性,传递工程target的所有配置信息
+local features = compiler.features("cxx", {target = target, config = {defines = "..", includedirs = ".."}})
+```
+
+所有c编译器特性列表:
+
+| 特性名 |
+| --------------------- |
+| c_static_assert |
+| c_restrict |
+| c_variadic_macros |
+| c_function_prototypes |
+
+所有c++编译器特性列表:
+
+| 特性名 |
+| ------------------------------------ |
+| cxx_variable_templates |
+| cxx_relaxed_constexpr |
+| cxx_aggregate_default_initializers |
+| cxx_contextual_conversions |
+| cxx_attribute_deprecated |
+| cxx_decltype_auto |
+| cxx_digit_separators |
+| cxx_generic_lambdas |
+| cxx_lambda_init_captures |
+| cxx_binary_literals |
+| cxx_return_type_deduction |
+| cxx_decltype_incomplete_return_types |
+| cxx_reference_qualified_functions |
+| cxx_alignof |
+| cxx_attributes |
+| cxx_inheriting_constructors |
+| cxx_thread_local |
+| cxx_alias_templates |
+| cxx_delegating_constructors |
+| cxx_extended_friend_declarations |
+| cxx_final |
+| cxx_nonstatic_member_init |
+| cxx_override |
+| cxx_user_literals |
+| cxx_constexpr |
+| cxx_defaulted_move_initializers |
+| cxx_enum_forward_declarations |
+| cxx_noexcept |
+| cxx_nullptr |
+| cxx_range_for |
+| cxx_unrestricted_unions |
+| cxx_explicit_conversions |
+| cxx_lambdas |
+| cxx_local_type_template_args |
+| cxx_raw_string_literals |
+| cxx_auto_type |
+| cxx_defaulted_functions |
+| cxx_deleted_functions |
+| cxx_generalized_initializers |
+| cxx_inline_namespaces |
+| cxx_sizeof_member |
+| cxx_strong_enums |
+| cxx_trailing_return_types |
+| cxx_unicode_literals |
+| cxx_uniform_initialization |
+| cxx_variadic_templates |
+| cxx_decltype |
+| cxx_default_function_template_args |
+| cxx_long_long_type |
+| cxx_right_angle_brackets |
+| cxx_rvalue_references |
+| cxx_static_assert |
+| cxx_extern_templates |
+| cxx_func_identifier |
+| cxx_variadic_macros |
+| cxx_template_template_parameters |
+
+###### compiler.has_features
+
+- 判断指定的编译器特性是否支持
+
+虽然通过[lib.detect.has_features](detect-has-features)也能获取,但是那个接口更加底层,需要指定编译器名称。
+而此接口只需要指定需要检测的特姓名称列表,就能自动切换选择当前支持的编译器,然后判断指定特性在当前的编译器中是否支持。
+
+```lua
+if compiler.has_features("c_static_assert") then
+ -- ok
+end
+
+if compiler.has_features({"c_static_assert", "cxx_constexpr"}, {languages = "cxx11"}) then
+ -- ok
+end
+
+if compiler.has_features("cxx_constexpr", {target = target, defines = "..", includedirs = ".."}) then
+ -- ok
+end
+```
+
+具体特性名有哪些,可以参考:[compiler.features](#compiler-features)。
+
+##### core.project.config
+
+用于获取工程编译时候的配置信息,也就是`xmake f|config --xxx=val` 传入的参数选项值。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [config.get](#config-get) | 获取指定配置值 | >= 2.0.1 |
+| [config.load](#config-load) | 加载配置 | >= 2.0.1 |
+| [config.arch](#config-arch) | 获取当前工程的架构配置 | >= 2.0.1 |
+| [config.plat](#config-plat) | 获取当前工程的平台配置 | >= 2.0.1 |
+| [config.mode](#config-mode) | 获取当前工程的编译模式配置 | >= 2.0.1 |
+| [config.buildir](#config-buildir) | 获取当前工程的输出目录配置 | >= 2.0.1 |
+| [config.directory](#config-directory) | 获取当前工程的配置信息目录 | >= 2.0.1 |
+| [config.dump](#config-dump) | 打印输出当前工程的所有配置信息 | >= 2.0.1 |
+
+###### config.get
+
+- 获取指定配置值
+
+用于获取`xmake f|config --xxx=val`的配置值,例如:
+
+```lua
+target("test")
+ on_run(function (target)
+
+ -- 导入配置模块
+ import("core.project.config")
+
+ -- 获取配置值
+ print(config.get("xxx"))
+ end)
+```
+
+###### config.load
+
+- 加载配置
+
+一般用于插件开发中,插件任务中不像工程的自定义脚本,环境需要自己初始化加载,默认工程配置是没有被加载的,如果要用[config.get](#config-get)接口获取工程配置,那么需要先:
+
+```lua
+
+-- 导入配置模块
+import("core.project.config")
+
+function main(...)
+
+ -- 先加载工程配置
+ config.load()
+
+ -- 获取配置值
+ print(config.get("xxx"))
+end
+```
+
+###### config.arch
+
+- 获取当前工程的架构配置
+
+也就是获取`xmake f|config --arch=armv7`的平台配置,相当于`config.get("arch")`。
+
+###### config.plat
+
+- 获取当前工程的平台配置
+
+也就是获取`xmake f|config --plat=iphoneos`的平台配置,相当于`config.get("plat")`。
+
+###### config.mode
+
+- 获取当前工程的编译模式配置
+
+也就是获取`xmake f|config --mode=debug`的平台配置,相当于`config.get("mode")`。
+
+###### config.buildir
+
+- 获取当前工程的输出目录配置
+
+也就是获取`xmake f|config -o /tmp/output`的平台配置,相当于`config.get("buildir")`。
+
+###### config.directory
+
+- 获取当前工程的配置信息目录
+
+获取工程配置的存储目录,默认为:`projectdir/.config`
+
+###### config.dump
+
+- 打印输出当前工程的所有配置信息
+
+输出结果例如:
+
+```lua
+{
+ sh = "xcrun -sdk macosx clang++"
+, xcode_dir = "/Applications/Xcode.app"
+, ar = "xcrun -sdk macosx ar"
+, small = true
+, object = false
+, arch = "x86_64"
+, xcode_sdkver = "10.12"
+, ex = "xcrun -sdk macosx ar"
+, cc = "xcrun -sdk macosx clang"
+, rc = "rustc"
+, plat = "macosx"
+, micro = false
+, host = "macosx"
+, as = "xcrun -sdk macosx clang"
+, dc = "dmd"
+, gc = "go"
+, openssl = false
+, ccache = "ccache"
+, cxx = "xcrun -sdk macosx clang"
+, sc = "xcrun -sdk macosx swiftc"
+, mm = "xcrun -sdk macosx clang"
+, buildir = "build"
+, mxx = "xcrun -sdk macosx clang++"
+, ld = "xcrun -sdk macosx clang++"
+, mode = "release"
+, kind = "static"
+}
+```
+
+##### core.project.global
+
+<p class="tip">
+此模块自2.1.5版本后迁移至[core.base.global](#core-base-global)。
+</p>
+
+##### core.project.task
+
+<p class="tip">
+此模块自2.1.5版本后迁移至[core.base.task](#core-base-task)。
+</p>
+
+##### core.project.project
+
+用于获取当前工程的一些描述信息,也就是在`xmake.lua`工程描述文件中定义的配置信息,例如:[target](#target)、[option](#option)等。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------------------- |
+| [project.load](#project-load) | 加载工程配置 | >= 2.0.1 (2.1.5废弃) |
+| [project.directory](#project-directory) | 获取工程目录 | >= 2.0.1 |
+| [project.target](#project-target) | 获取指定工程目标对象 | >= 2.0.1 |
+| [project.targets](#project-targets) | 获取工程目标对象列表 | >= 2.0.1 |
+| [project.option](#project-option) | 获取指定的选项对象 | >= 2.1.5 |
+| [project.options](#project-options) | 获取工程所有的选项对象 | >= 2.1.5 |
+| [project.name](#project-name) | 获取当前工程名 | >= 2.0.1 |
+| [project.version](#project-version) | 获取当前工程版本号 | >= 2.0.1 |
+
+###### project.load
+
+- 加载工程描述配置
+
+仅在插件中使用,因为这个时候还没有加载工程配置信息,在工程目标的自定义脚本中,不需要执行此操作,就可以直接访问工程配置。
+
+```lua
+-- 导入工程模块
+import("core.project.project")
+
+-- 插件入口
+function main(...)
+
+ -- 加载工程描述配置
+ project.load()
+
+ -- 访问工程描述,例如获取指定工程目标
+ local target = project.target("test")
+end
+```
+
+<p class="tip">
+2.1.5版本后,不在需要,工程加载会自动在合适时机延迟加载。
+</p>
+
+###### project.directory
+
+- 获取工程目录
+
+获取当前工程目录,也就是`xmake -P xxx`中指定的目录,否则为默认当前`xmake`命令执行目录。
+
+<p class="tip">
+2.1.5版本后,建议使用[os.projectdir](#os-projectdir)来获取。
+</p>
+
+###### project.target
+
+- 获取指定工程目标对象
+
+获取和访问指定工程目标配置,例如:
+
+```lua
+local target = project.target("test")
+if target then
+
+ -- 获取目标文件名
+ print(target:targetfile())
+
+ -- 获取目标类型,也就是:binary, static, shared
+ print(target:targetkind())
+
+ -- 获取目标名
+ print(target:name())
+
+ -- 获取目标源文件
+ local sourcefiles = target:sourcefiles()
+
+ -- 获取目标安装头文件列表
+ local srcheaders, dstheaders = target:headerfiles()
+
+ -- 获取目标依赖
+ print(target:get("deps"))
+end
+```
+
+###### project.targets
+
+- 获取工程目标对象列表
+
+返回当前工程的所有编译目标,例如:
+
+```lua
+for targetname, target in pairs(project.targets())
+ print(target:targetfile())
+end
+```
+
+###### project.option
+
+- 获取指定选项对象
+
+获取和访问工程中指定的选项对象,例如:
+
+```lua
+local option = project.option("test")
+if option:enabled() then
+ option:enable(false)
+end
+```
+
+###### project.options
+
+- 获取工程所有选项对象
+
+返回当前工程的所有编译目标,例如:
+
+```lua
+for optionname, option in pairs(project.options())
+ print(option:enabled())
+end
+```
+
+###### project.name
+
+- 获取当前工程名
+
+也就是获取[set_project](#set_project)的工程名配置。
+
+```lua
+print(project.name())
+```
+
+###### project.version
+
+- 获取当前工程版本号
+
+也就是获取[set_version](#set_version)的工程版本配置。
+
+```lua
+print(project.version())
+```
+
+##### core.language.language
+
+用于获取编译语言相关信息,一般用于代码文件的操作。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [language.extensions](#language-extensions) | 获取所有语言的代码后缀名列表 | >= 2.1.1 |
+| [language.targetkinds](#language-targetkinds) | 获取所有语言的目标类型列表 | >= 2.1.1 |
+| [language.sourcekinds](#language-sourcekinds) | 获取所有语言的源文件类型列表 | >= 2.1.1 |
+| [language.sourceflags](#language-sourceflags) | 加载所有语言的源文件编译选项名列表 | >= 2.1.1 |
+| [language.load](#language-load) | 加载指定语言 | >= 2.1.1 |
+| [language.load_sk](#language-load_sk) | 从源文件类型加载指定语言 | >= 2.1.1 |
+| [language.load_ex](#language-load_ex) | 从源文件后缀名加载指定语言 | >= 2.1.1 |
+| [language.sourcekind_of](#language-sourcekind_of) | 获取指定源文件的源文件类型 | >= 2.1.1 |
+
+###### language.extensions
+
+- 获取所有语言的代码后缀名列表
+
+获取结果如下:
+
+```lua
+{
+ [".c"] = cc
+, [".cc"] = cxx
+, [".cpp"] = cxx
+, [".m"] = mm
+, [".mm"] = mxx
+, [".swift"] = sc
+, [".go"] = gc
+}
+```
+
+###### language.targetkinds
+
+- 获取所有语言的目标类型列表
+
+获取结果如下:
+
+```lua
+{
+ binary = {"ld", "gc-ld", "dc-ld"}
+, static = {"ar", "gc-ar", "dc-ar"}
+, shared = {"sh", "dc-sh"}
+}
+```
+
+###### language.sourcekinds
+
+- 获取所有语言的源文件类型列表
+
+获取结果如下:
+
+```lua
+{
+ cc = ".c"
+, cxx = {".cc", ".cpp", ".cxx"}
+, mm = ".m"
+, mxx = ".mm"
+, sc = ".swift"
+, gc = ".go"
+, rc = ".rs"
+, dc = ".d"
+, as = {".s", ".S", ".asm"}
+}
+```
+
+###### language.sourceflags
+
+- 加载所有语言的源文件编译选项名列表
+
+获取结果如下:
+
+```lua
+{
+ cc = {"cflags", "cxflags"}
+, cxx = {"cxxflags", "cxflags"}
+, ...
+}
+```
+
+###### language.load
+
+- 加载指定语言
+
+从语言名称加载具体语言对象,例如:
+
+```lua
+local lang = language.load("c++")
+if lang then
+ print(lang:name())
+end
+```
+
+###### language.load_sk
+
+- 从源文件类型加载指定语言
+
+从源文件类型:`cc, cxx, mm, mxx, sc, gc, as ..`加载具体语言对象,例如:
+
+```lua
+local lang = language.load_sk("cxx")
+if lang then
+ print(lang:name())
+end
+```
+
+###### language.load_ex
+
+- 从源文件后缀名加载指定语言
+
+从源文件后缀名:`.cc, .c, .cpp, .mm, .swift, .go ..`加载具体语言对象,例如:
+
+```lua
+local lang = language.load_sk(".cpp")
+if lang then
+ print(lang:name())
+end
+```
+
+###### language.sourcekind_of
+
+- 获取指定源文件的源文件类型
+
+也就是从给定的一个源文件路径,获取它是属于那种源文件类型,例如:
+
+```lua
+print(language.sourcekind_of("/xxxx/test.cpp"))
+```
+
+显示结果为:`cxx`,也就是`c++`类型,具体对应列表见:[language.sourcekinds](#language-sourcekinds)
+
+##### core.platform.platform
+
+平台信息相关操作
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [platform.get](#platform-get) | 获取指定平台相关配置信息 | >= 2.0.1 |
+
+###### platform.get
+
+- 获取指定平台相关配置信息
+
+获取平台配置`xmake.lua`中设置的信息,一般只有在写插件的时候会用到,例如:
+
+```lua
+-- 获取当前平台的所有支持架构
+print(platform.get("archs"))
+
+-- 获取指定iphoneos平台的目标文件格式信息
+local formats = platform.get("formats", "iphoneos")
+table.dump(formats)
+```
+
+具体有哪些可读的平台配置信息,可参考:[platform](#platform)
+
+##### core.platform.environment
+
+环境相关操作,用于进入和离开指定环境变量对应的终端环境,一般用于`path`环境的进入和离开,尤其是一些需要特定环境的构建工具,例如:msvc的工具链。
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| [environment.enter](#environment-enter) | 进入指定环境 | >= 2.0.1 |
+| [environment.leave](#environment-leave) | 离开指定环境 | >= 2.0.1 |
+
+目前支持的环境有:
+
+| 接口 | 描述 | 支持版本 |
+| ----------------------------------------------- | -------------------------------------------- | -------- |
+| toolchains | 工具链执行环境 | >= 2.0.1 |
+
+###### environment.enter
+
+- 进入指定环境
+
+进入指定环境,例如msvc有自己的环境变量环境用于运行构建工具,例如:`cl.exe`, `link.exe`这些,这个时候想要在xmake里面运行他们,需要:
+
+```lua
+-- 进入工具链环境
+environment.enter("toolchains")
+
+-- 这个时候运行cl.exe才能正常运行,这个时候的path等环境变量都会进入msvc的环境模式
+os.run("cl.exe ..")
+
+-- 离开工具链环境
+environment.leave("toolchains")
+```
+
+因此为了通用性,默认xmake编译事都会设置这个环境,在linux下基本上内部环境不需要特殊切换,目前仅对windows下msvc进行了处理。
+
+###### environment.leave
+
+- 离开指定环境
+
+具体使用见:[environment.enter](#environment-enter)
+
+##### lib.detect
+
+此模块提供了非常强大的探测功能,用于探测程序、编译器、语言特性、依赖包等。
+
+<p class="tip">
+此模块的接口分散在多个模块目录中,尽量通过导入单个接口来使用,这样效率更高,例如:`import("lib.detect.find_package")`,而不是通过`import("lib.detect")`导入所有来调用。
+</p>
+
+| 接口 | 描述 | 支持版本 |
+| --------------------------------------------------- | -------------------------------------------- | -------------------- |
+| [detect.find_file](#detect-find_file) | 查找文件 | >= 2.1.5 |
+| [detect.find_path](#detect-find_path) | 查找文件路径 | >= 2.1.5 |
+| [detect.find_library](#detect-find_library) | 查找库文件 | >= 2.1.5 |
+| [detect.find_program](#detect-find_program) | 查找可执行程序 | >= 2.1.5 |
+| [detect.find_programver](#detect-find_programver) | 查找可执行程序版本号 | >= 2.1.5 |
+| [detect.find_package](#detect-find_package) | 查找包文件,包含库文件和搜索路径 | >= 2.1.5 |
+| [detect.find_tool](#detect-find_tool) | 查找工具 | >= 2.1.5 |
+| [detect.find_toolname](#detect-find_toolname) | 查找工具名 | >= 2.1.5 |
+| [detect.features](#detect-features) | 获取指定工具的所有特性 | >= 2.1.5 |
+| [detect.has_features](#detect-has_features) | 判断指定特性是否支持 | >= 2.1.5 |
+| [detect.has_flags](#detect-has_flags) | 判断指定参数选项是否支持 | >= 2.1.5 |
+| [detect.has_cfuncs](#detect-has_cfuncs) | 判断指定c函数是否存在 | >= 2.1.5 |
+| [detect.has_cxxfuncs](#detect-has_cxxfuncs) | 判断指定c++函数是否存在 | >= 2.1.5 |
+| [detect.has_cincludes](#detect-has_cincludes) | 判断指定c头文件是否存在 | >= 2.1.5 |
+| [detect.has_cxxincludess](#detect-has_cxxincludes) | 判断指定c++头文件是否存在 | >= 2.1.5 |
+| [detect.has_ctypes](#detect-has_ctypes) | 判断指定c类型是否存在 | >= 2.1.5 |
+| [detect.has_cxxtypes](#detect-has_cxxtypes) | 判断指定c++类型是否存在 | >= 2.1.5 |
+| [detect.check_cxsnippets](#detect-check_cxsnippets) | 检测c/c++代码片段是否能够编译通过 | >= 2.1.5 |
+
+###### detect.find_file
+
+- 查找文件
+
+这个接口提供了比[os.files](#os-files)更加强大的工程, 可以同时指定多个搜索目录,并且还能对每个目录指定附加的子目录,来模式匹配查找,相当于是[os.files](#os-files)的增强版。
+
+例如:
+
+```lua
+import("lib.detect.find_file")
+
+local file = find_file("ccache", { "/usr/bin", "/usr/local/bin"})
+```
+
+如果找到,返回的结果是:`/usr/bin/ccache`
+
+它同时也支持模式匹配路径,进行递归查找,类似`os.files`:
+
+```lua
+local file = find_file("test.h", { "/usr/include", "/usr/local/include/**"})
+```
+
+不仅如此,里面的路径也支持内建变量,来从环境变量和注册表中获取路径进行查找:
+
+```lua
+local file = find_file("xxx.h", { "$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name)"})
+```
+
+如果路径规则比较复杂多变,还可以通过自定义脚本来动态生成路径传入:
+
+```lua
+local file = find_file("xxx.h", { "$(env PATH)", function () return val("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name"):match("\"(.-)\"") end})
+```
+
+大部分场合下,上面的使用已经满足各种需求了,如果还需要一些扩展功能,可以通过传入第三个参数,自定义一些可选配置,例如:
+
+```lua
+local file = find_file("test.h", { "/usr", "/usr/local"}, {suffixes = {"/include", "/lib"}})
+```
+
+通过指定suffixes子目录列表,可以扩展路径列表(第二个参数),使得实际的搜索目录扩展为:
+
+```
+/usr/include
+/usr/lib
+/usr/local/include
+/usr/local/lib
+```
+
+并且不用改变路径列表,就能动态切换子目录来搜索文件。
+
+<p class="tip">
+我们也可以通过`xmake lua`插件来快速调用和测试此接口:`xmake lua lib.detect.find_file test.h /usr/local`
+</p>
+
+###### detect.find_path
+
+- 查找路径
+
+这个接口的用法跟[lib.detect.find_file](#detect-find_file)类似,唯一的区别是返回的结果不同。
+此接口查找到传入的文件路径后,返回的是对应的搜索路径,而不是文件路径本身,一般用于查找文件对应的父目录位置。
+
+```lua
+import("lib.detect.find_path")
+
+local p = find_path("include/test.h", { "/usr", "/usr/local"})
+```
+
+上述代码如果查找成功,则返回:`/usr/local`,如果`test.h`在`/usr/local/include/test.h`的话。
+
+还有一个区别就是,这个接口传入不只是文件路径,还可以传入目录路径来查找:
+
+```lua
+local p = find_path("lib/xxx", { "$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name)"})
+```
+
+同样,此接口也支持模式匹配和后缀子目录:
+
+```lua
+local p = find_path("include/*.h", { "/usr", "/usr/local/**"}, {suffixes = "/subdir"})
+```
+
+###### detect.find_library
+
+- 查找库文件
+
+此接口用于指定的搜索目录中查找库文件(静态库,动态库),例如:
+
+```lua
+import("lib.detect.find_library")
+
+local library = find_library("crypto", {"/usr/lib", "/usr/local/lib"})
+```
+
+在macosx上运行,返回的结果如下:
+
+```lua
+{
+ filename = libcrypto.dylib
+, linkdir = /usr/lib
+, link = crypto
+, kind = shared
+}
+```
+
+如果不指定是否需要静态库还是动态库,那么此接口会自动选择一个存在的库(有可能是静态库、也有可能是动态库)进行返回。
+
+如果需要强制指定需要查找的库类型,可以指定kind参数为(`static/shared`):
+
+```lua
+local library = find_library("crypto", {"/usr/lib", "/usr/local/lib"}, {kind = "static"})
+```
+
+此接口也支持suffixes后缀子目录搜索和模式匹配操作:
+
+```lua
+local library = find_library("cryp*", {"/usr", "/usr/local"}, {suffixes = "/lib"})
+```
+
+###### detect.find_program
+
+- 查找可执行程序
+
+这个接口比[lib.detect.find_tool](#detect-find_tool)较为原始底层,通过指定的参数目录来查找可执行程序。
+
+```lua
+import("lib.detect.find_program")
+
+local program = find_program("ccache")
+```
+
+上述代码犹如没有传递搜索目录,所以它会尝试直接执行指定程序,如果运行ok,那么直接返回:`ccache`,表示查找成功。
+
+指定搜索目录,修改尝试运行的检测命令参数(默认是:`ccache --version`):
+
+```lua
+local program = find_program("ccache", {"/usr/bin", "/usr/local/bin"}, "--help")
+```
+
+上述代码会尝试运行:`/usr/bin/ccache --help`,如果运行成功,则返回:`/usr/bin/ccache`。
+
+如果`--help`也没法满足需求,有些程序没有`--version/--help`参数,那么可以自定义运行脚本,来运行检测:
+
+```lua
+local program = find_program("ccache", {"/usr/bin", "/usr/local/bin"}, function (program) os.run("%s -h", program) end)
+```
+
+同样,搜索路径列表支持内建变量和自定义脚本:
+
+```lua
+local program = find_program("ccache", {"$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug;Debugger)"})
+local program = find_program("ccache", {"$(env PATH)", function () return "/usr/local/bin" end})
+```
+
+<p class="tip">
+为了加速频发查找的效率,此接口是默认自带cache的,所以就算频繁查找相同的程序,也不会花太多时间。
+如果要禁用cache,可以在工程目录执行`xmake f -c`清除本地cache。
+</p>
+
+我们也可以通过`xmake lua lib.detect.find_program ccache` 来快速测试。
+
+###### detect.find_programver
+
+- 查找可执行程序版本号
+
+
+```lua
+import("lib.detect.find_programver")
+
+local programver = find_programver("ccache")
+```
+
+返回结果为:3.2.2
+
+默认它会通过`ccache --version`尝试获取版本,如果不存在此参数,可以自己指定其他参数:
+
+```lua
+local version = find_programver("ccache", "-v")
+```
+
+甚至自定义版本获取脚本:
+
+```lua
+local version = find_programver("ccache", function () return os.iorun("ccache --version") end)
+```
+
+对于版本号的提取规则,如果内置的匹配模式不满足要求,也可以自定义:
+
+```lua
+local version = find_programver("ccache", "--version", "(%d+%.?%d*%.?%d*.-)%s")
+local version = find_programver("ccache", "--version", function (output) return output:match("(%d+%.?%d*%.?%d*.-)%s") end)
+```
+
+<p class="tip">
+为了加速频发查找的效率,此接口是默认自带cache的,如果要禁用cache,可以在工程目录执行`xmake f -c`清除本地cache。
+</p>
+
+我们也可以通过`xmake lua lib.detect.find_programver ccache` 来快速测试。
+
+###### detect.find_package
+
+- 查找包文件
+
+此接口也是用于查找库文件,但是比[lib.detect.find_library](#detect-find_library)更加上层,也更为强大和简单易用,因为它是以包为力度进行查找。
+
+那怎样算是一个完整的包,它包含:
+
+1. 多个静态库或者动态库文件
+2. 库的搜索目录
+3. 头文件的搜索目录
+4. 可选的编译链接选项,例如:`defines`等
+5. 可选的版本号
+
+例如我们查找一个openssl包:
+
+```lua
+import("lib.detect.find_package")
+
+local package = find_package("openssl")
+```
+
+返回的结果如下:
+
+```lua
+{links = {"ssl", "crypto", "z"}, linkdirs = {"/usr/local/lib"}, includedirs = {"/usr/local/include"}}
+```
+
+如果查找成功,则返回一个包含所有包信息的table,如果失败返回nil
+
+这里的返回结果可以直接作为`target:add`, `option:add`的参数传入,用于动态增加`target/option`的配置:
+
+```lua
+option("zlib")
+ set_showmenu(true)
+ before_check(function (option)
+ import("lib.detect.find_package")
+ option:add(find_package("zlib"))
+ end)
+```
+
+```lua
+target("test")
+ on_load(function (target)
+ import("lib.detect.find_package")
+ target:add(find_package("zlib"))
+ end)
+```
+
+如果系统上装有`homebrew`, `pkg-config`等第三方工具,那么此接口会尝试使用它们去改进查找结果。
+
+我们也可以通过指定版本号,来选择查找指定版本的包(如果这个包获取不到版本信息或者没有匹配版本的包,则返回nil):
+
+```lua
+local package = find_package("openssl", {version = "1.0.1"})
+```
+
+默认情况下查找的包是根据如下规则匹配平台,架构和模式的:
+
+1. 如果参数传入指定了`{plat = "iphoneos", arch = "arm64", mode = "release"}`,则优先匹配,例如:`find_package("openssl", {plat = "iphoneos"})`。
+2. 如果是在当前工程环境,存在配置文件,则优先尝试从`config.get("plat")`, `config.get("arch")`和`config.get("mode")`获取平台架构进行匹配。
+3. 最后从`os.host()`和`os.arch()`中进行匹配,也就是当前主机的平台架构环境。
+
+如果系统的库目录以及`pkg-config`都不能满足需求,找不到包,那么可以自己手动设置搜索路径:
+
+```lua
+local package = find_package("openssl", {linkdirs = {"/usr/lib", "/usr/local/lib"}, includedirs = "/usr/local/include"})
+```
+
+也可以同时指定需要搜索的链接名,头文件名:
+
+```lua
+local package = find_package("openssl", {links = {"ssl", "crypto"}, includes = "ssl.h"}})
+```
+
+甚至可以指定xmake的`packagedir/*.pkg`包目录,用于查找对应的`openssl.pkg`包,一般用于查找内置在工程目录中的本地包。
+
+例如,tbox工程内置了`pkg/openssl.pkg`本地包载项目中,我们可以通过下面的脚本,传入`{packagedirs = ""}`参数优先查找本地包,如果找不到再去找系统包。
+
+```lua
+target("test")
+ on_load(function (target)
+ import("lib.detect.find_package")
+ target:add(find_package("openssl", {packagedirs = path.join(os.projectdir(), "pkg")}))
+ end)
+```
+
+总结下,现在的查找顺序:
+
+1. 如果指定`{packagedirs = ""}`参数,优先从这个参数指定的路径中查找本地包`*.pkg`
+2. 如果在`xmake/modules`下面存在`detect.packages.find_xxx`脚本,那么尝试调用此脚本来改进查找结果
+3. 如果系统存在`pkg-config`,并且查找的是系统环境的库,则尝试使用`pkg-config`提供的路径和链接信息进行查找
+4. 如果系统存在`homebrew`,并且查找的是系统环境的库,则尝试使用`brew --prefix xxx`提供的信息进行查找
+5. 从参数中指定的pathes路径和一些已知的系统路径`/usr/lib`, `/usr/include`中进行查找
+
+这里需要着重说下第二点,通过在`detect.packages.find_xxx`脚本来改进查找结果,很多时候自动的包探测是没法完全探测到包路径的,
+尤其是针对windows平台,没有默认的库目录,也没有包管理app,很多库装的时候,都是自己所处放置在系统目录,或者添加注册表项。
+
+因此查找起来没有同意的规则,这个时候,就可以自定义一个查找脚本,去改进`find_package`的查找机制,对指定包进行更精准的查找。
+
+在xmake自带的`xmake/modules/detect/packages`目录下,已经有许多的内置包脚本,来对常用的包进行更好的查找支持。
+当然这不可能满足所有用户的需求,如果用户需要的包还是找不到,那么可以自己定义一个查找脚本,例如:
+
+查找一个名为`openssl`的包,可以编写一个`find_openssl.lua`的脚本放置在工程目录:
+
+```
+projectdir
+ - xmake
+ - modules
+ - detect/package/find_openssl.lua
+```
+
+然后在工程的`xmake.lua`文件的开头指定下这个modules的目录:
+
+```lua
+add_moduledirs("$(projectdir)/xmake/modules")
+```
+
+这样xmake就能找到自定义的扩展模块了。
+
+接下来我们看下`find_openssl.lua`的实现:
+
+```lua
+-- imports
+import("lib.detect.find_path")
+import("lib.detect.find_library")
+
+-- find openssl
+--
+-- @param opt the package options. e.g. see the options of find_package()
+--
+-- @return see the return value of find_package()
+--
+function main(opt)
+
+ -- for windows platform
+ --
+ -- http://www.slproweb.com/products/Win32OpenSSL.html
+ --
+ if opt.plat == "windows" then
+
+ -- init bits
+ local bits = ifelse(opt.arch == "x64", "64", "32")
+
+ -- init search pathes
+ local pathes = {"$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL %(" .. bits .. "-bit%)_is1;Inno Setup: App Path)",
+ "$(env PROGRAMFILES)/OpenSSL",
+ "$(env PROGRAMFILES)/OpenSSL-Win" .. bits,
+ "C:/OpenSSL",
+ "C:/OpenSSL-Win" .. bits}
+
+ -- find library
+ local result = {links = {}, linkdirs = {}, includedirs = {}}
+ for _, name in ipairs({"libssl", "libcrypto"}) do
+ local linkinfo = find_library(name, pathes, {suffixes = "lib"})
+ if linkinfo then
+ table.insert(result.links, linkinfo.link)
+ table.insert(result.linkdirs, linkinfo.linkdir)
+ end
+ end
+
+ -- not found?
+ if #result.links ~= 2 then
+ return
+ end
+
+ -- find include
+ table.insert(result.includedirs, find_path("openssl/ssl.h", pathes, {suffixes = "include"}))
+
+ -- ok
+ return result
+ end
+end
+```
+
+里面对windows平台进行注册表读取,去查找指定的库文件,其底层其实也是调用的[find_library](#detect-find_library)等接口。
+
+<p class="tip">
+为了加速频发查找的效率,此接口是默认自带cache的,如果要禁用cache,可以在工程目录执行`xmake f -c`清除本地cache。
+也可以通过指定force参数,来禁用cache,强制重新查找:`find_package("openssl", {force = true})`
+</p>
+
+我们也可以通过`xmake lua lib.detect.find_package openssl` 来快速测试。
+
+###### detect.find_tool
+
+- 查找工具
+
+此接口也是用于查找可执行程序,不过比[lib.detect.find_program](#detect-find_program)更加的高级,功能也更加强大,它对可执行程序进行了封装,提供了工具这个概念:
+
+* toolname: 工具名,可执行程序的简称,用于标示某个工具,例如:`gcc`, `clang`等
+* program: 可执行程序命令,例如:`xcrun -sdk macosx clang`
+
+其对应关系如下:
+
+| toolname | program |
+| --------- | ----------------------------------- |
+| clang | `xcrun -sdk macosx clang` |
+| gcc | `/usr/toolchains/bin/arm-linux-gcc` |
+| link | `link.exe -lib` |
+
+[lib.detect.find_program](#detect-find_program)只能通过传入的原始program命令或路径,去判断该程序是否存在。
+而`find_tool`则可以通过更加一致的toolname去查找工具,并且返回对应的program完整命令路径,例如:
+
+```lua
+import("lib.detect.find_tool")
+
+local tool = find_tool("clang")
+```
+
+返回的结果为:`{name = "clang", program = "clang"}`,这个时候还看不出区别,我们可以手动指定可执行的命令:
+
+```lua
+local tool = find_tool("clang", {program = "xcrun -sdk macosx clang"})
+```
+
+返回的结果为:`{name = "clang", program = "xcrun -sdk macosx clang"}`
+
+而在macosx下,gcc就是clang,如果我们执行`gcc --version`可以看到就是clang的一个马甲,我们可以通过`find_tool`接口进行智能识别:
+
+```lua
+local tool = find_tool("gcc")
+```
+
+返回的结果为:`{name = "clang", program = "gcc"}`
+
+通过这个结果就可以看的区别来了,工具名实际会被标示为clang,但是可执行的命令用的是gcc。
+
+我们也可以指定`{version = true}`参数去获取工具的版本,并且指定一个自定义的搜索路径,也支持内建变量和自定义脚本哦:
+
+```lua
+local tool = find_tool("clang", {version = true, {pathes = {"/usr/bin", "/usr/local/bin", "$(env PATH)", function () return "/usr/xxx/bin" end}})
+```
+
+返回的结果为:`{name = "clang", program = "/usr/bin/clang", version = "4.0"}`
+
+这个接口是对`find_program`的上层封装,因此也支持自定义脚本检测:
+
+```lua
+local tool = find_tool("clang", {check = "--help"})
+local tool = find_tool("clang", {check = function (tool) os.run("%s -h", tool) end})
+```
+
+最后总结下,`find_tool`的查找流程:
+
+1. 优先通过`{program = "xxx"}`的参数来尝试运行和检测。
+2. 如果在`xmake/modules/detect/tools`下存在`detect.tools.find_xxx`脚本,则调用此脚本进行更加精准的检测。
+3. 尝试从`/usr/bin`,`/usr/local/bin`等系统目录进行检测。
+
+我们也可以在工程`xmake.lua`中`add_moduledirs`指定的模块目录中,添加自定义查找脚本,来改进检测机制:
+
+```
+projectdir
+ - xmake/modules
+ - detect/tools/find_xxx.lua
+```
+
+例如我们自定义一个`find_7z.lua`的查找脚本:
+
+```lua
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+
+ -- find program
+ local program = find_program(opt.program or "7z", opt.pathes, opt.check or "--help")
+
+ -- find program version
+ local version = nil
+ if program and opt and opt.version then
+ version = find_programver(program, "--help", "(%d+%.?%d*)%s")
+ end
+
+ -- ok?
+ return program, version
+end
+```
+
+将它放置到工程的模块目录下后,执行:`xmake l lib.detect.find_tool 7z`就可以查找到了。
+
+<p class="tip">
+为了加速频发查找的效率,此接口是默认自带cache的,如果要禁用cache,可以在工程目录执行`xmake f -c`清除本地cache。
+</p>
+
+我们也可以通过`xmake lua lib.detect.find_tool clang` 来快速测试。
+
+###### detect.find_toolname
+
+- 查找工具名
+
+通过program命令匹配对应的工具名,例如:
+
+| program | toolname |
+| ------------------------- | ---------- |
+| `xcrun -sdk macosx clang` | clang |
+| `/usr/bin/arm-linux-gcc` | gcc |
+| `link.exe -lib` | link |
+| `gcc-5` | gcc |
+| `arm-android-clang++` | clangxx |
+| `pkg-config` | pkg_config |
+
+toolname相比program,更能唯一标示某个工具,也方便查找和加载对应的脚本`find_xxx.lua`。
+
+###### detect.features
+
+- 获取指定工具的所有特性
+
+此接口跟[compiler.features](#compiler-features)类似,区别就是此接口更加的原始,传入的参数是实际的工具名toolname。
+
+并且此接口不仅能够获取编译器的特性,任何工具的特性都可以获取,因此更加通用。
+
+```lua
+import("lib.detect.features")
+
+local features = features("clang")
+local features = features("clang", {flags = "-O0", program = "xcrun -sdk macosx clang"})
+local features = features("clang", {flags = {"-g", "-O0", "-std=c++11"}})
+```
+
+通过传入flags,可以改变特性的获取结果,例如一些c++11的特性,默认情况下获取不到,通过启用`-std=c++11`后,就可以获取到了。
+
+所有编译器的特性列表,可以见:[compiler.features](#compiler-features)。
+
+###### detect.has_features
+
+- 判断指定特性是否支持
+
+此接口跟[compiler.has_features](#compiler-has_features)类似,但是更加原始,传入的参数是实际的工具名toolname。
+
+并且此接口不仅能够判断编译器的特性,任何工具的特性都可以判断,因此更加通用。
+
+```lua
+import("lib.detect.has_features")
+
+local features = has_features("clang", "cxx_constexpr")
+local features = has_features("clang", {"cxx_constexpr", "c_static_assert"}, {flags = {"-g", "-O0"}, program = "xcrun -sdk macosx clang"})
+local features = has_features("clang", {"cxx_constexpr", "c_static_assert"}, {flags = "-g"})
+```
+
+如果指定的特性列表存在,则返回实际支持的特性子列表,如果都不支持,则返回nil,我们也可以通过指定flags去改变特性的获取规则。
+
+所有编译器的特性列表,可以见:[compiler.features](#compiler-features)。
+
+###### detect.has_flags
+
+- 判断指定参数选项是否支持
+
+此接口跟[compiler.has_flags](#compiler-has_flags)类似,但是更加原始,传入的参数是实际的工具名toolname。
+
+```lua
+import("lib.detect.has_flags")
+
+local ok = has_flags("clang", "-g")
+local ok = has_flags("clang", {"-g", "-O0"}, {program = "xcrun -sdk macosx clang"})
+local ok = has_flags("clang", "-g -O0", {toolkind = "cxx"})
+```
+
+如果检测通过,则返回true。
+
+此接口的检测做了一些优化,除了cache机制外,大部分场合下,会去拉取工具的选项列表(`--help`)直接判断,如果选项列表里获取不到的话,才会通过尝试运行的方式来检测。
+
+###### detect.has_cfuncs
+
+- 判断指定c函数是否存在
+
+此接口是[lib.detect.check_cxsnippets](#detect-check_cxsnippets)的简化版本,仅用于检测函数。
+
+```lua
+import("lib.detect.has_cfuncs")
+
+local ok = has_cfuncs("setjmp")
+local ok = has_cfuncs({"sigsetjmp((void*)0, 0)", "setjmp"}, {includes = "setjmp.h"})
+```
+
+对于函数的描述规则如下:
+
+| 函数描述 | 说明 |
+| ----------------------------------------------- | ------------- |
+| `sigsetjmp` | 纯函数名 |
+| `sigsetjmp((void*)0, 0)` | 函数调用 |
+| `sigsetjmp{int a = 0; sigsetjmp((void*)a, a);}` | 函数名 + {}块 |
+
+在最后的可选参数中,除了可以指定`includes`外,还可以指定其他的一些参数用于控制编译检测的选项条件:
+
+```lua
+{ verbose = false, target = [target|option], includes = .., config = {linkdirs = .., links = .., defines = ..}}
+```
+
+其中verbose用于回显检测信息,target用于在检测前追加target中的配置信息, 而config用于自定义配置跟target相关的编译选项。
+
+###### detect.has_cxxfuncs
+
+- 判断指定c++函数是否存在
+
+此接口跟[lib.detect.has_cfuncs](#detect-has_cfuncs)类似,请直接参考它的使用说明,唯一区别是这个接口用于检测c++函数。
+
+###### detect.has_cincludes
+
+- 判断指定c头文件是否存在
+
+此接口是[lib.detect.check_cxsnippets](#detect-check_cxsnippets)的简化版本,仅用于检测头文件。
+
+```lua
+import("lib.detect.has_cincludes")
+
+local ok = has_cincludes("stdio.h")
+local ok = has_cincludes({"stdio.h", "stdlib.h"}, {target = target})
+local ok = has_cincludes({"stdio.h", "stdlib.h"}, {config = {defines = "_GNU_SOURCE=1", languages = "cxx11"}})
+```
+
+###### detect.has_cxxincludes
+
+- 判断指定c++头文件是否存在
+
+此接口跟[lib.detect.has_cincludess](#detect-has_cincludes)类似,请直接参考它的使用说明,唯一区别是这个接口用于检测c++头文件。
+
+###### detect.has_ctypes
+
+- 判断指定c类型是否存在
+
+此接口是[lib.detect.check_cxsnippets](#detect-check_cxsnippets)的简化版本,仅用于检测函数。
+
+```lua
+import("lib.detect.has_ctypes")
+
+local ok = has_ctypes("wchar_t")
+local ok = has_ctypes({"char", "wchar_t"}, {includes = "stdio.h"})
+local ok = has_ctypes("wchar_t", {includes = {"stdio.h", "stdlib.h"}, config = {"defines = "_GNU_SOURCE=1", languages = "cxx11"}})
+```
+
+###### detect.has_cxxtypes
+
+- 判断指定c++类型是否存在
+
+此接口跟[lib.detect.has_ctypess](#detect-has_ctypes)类似,请直接参考它的使用说明,唯一区别是这个接口用于检测c++类型。
+
+###### detect.check_cxsnippets
+
+- 检测c/c++代码片段是否能够编译通过
+
+通用的c/c++代码片段检测接口,通过传入多个代码片段列表,它会自动生成一个编译文件,然后常识对它进行编译,如果编译通过返回true。
+
+对于一些复杂的编译器特性,连[compiler.has_features](#compiler-has_features)都无法检测到的时候,可以通过此接口通过尝试编译来检测它。
+
+```lua
+import("lib.detect.check_cxsnippets")
+
+local ok = check_cxsnippets("void test() {}")
+local ok = check_cxsnippets({"void test(){}", "#define TEST 1"}, {types = "wchar_t", includes = "stdio.h"})
+```
+
+此接口是[detect.has_cfuncs](#detect-has_cfuncs), [detect.has_cincludes](#detect-has_cincludes)和[detect.has_ctypes](detect-has_ctypes)等接口的通用版本,也更加底层。
+
+因此我们可以用它来检测:types, functions, includes 还有 links,或者是组合起来一起检测。
+
+第一个参数为代码片段列表,一般用于一些自定义特性的检测,如果为空,则可以仅仅检测可选参数中条件,例如:
+
+```lua
+local ok = check_cxsnippets({}, {types = {"wchar_t", "char*"}, includes = "stdio.h", funcs = {"sigsetjmp", "sigsetjmp((void*)0, 0)"}})
+```
+
+上面那个调用,会去同时检测types, includes和funcs是否都满足,如果通过返回true。
+
+还有其他一些可选参数:
+
+```lua
+{ verbose = false, target = [target|option], sourcekind = "[cc|cxx]"}
+```
+
+其中verbose用于回显检测信息,target用于在检测前追加target中的配置信息, sourcekind 用于指定编译器等工具类型,例如传入`cxx`强制作为c++代码来检测。
+
+##### net.http
+
+此模块提供http的各种操作支持,目前提供的接口如下:
+
+| 接口 | 描述 | 支持版本 |
+| --------------------------------------------------- | -------------------------------------------- | -------------------- |
+| [http.download](#http-download) | 下载http文件 | >= 2.1.5 |
+
+###### http.download
+
+- 下载http文件
+
+这个接口比较简单,就是单纯的下载文件。
+
+```lua
+import("net.http")
+
+http.download("http://xmake.io", "/tmp/index.html")
+```
+
+##### privilege.sudo
+
+此接口用于通过`sudo`来运行命令,并且提供了平台一致性处理,对于一些需要root权限运行的脚本,可以使用此接口。
+
+<p class="warning">
+为了保证安全性,除非必须使用的场合,其他情况下尽量不要使用此接口。
+</p>
+
+| 接口 | 描述 | 支持版本 |
+| --------------------------------------------------- | -------------------------------------------- | -------------------- |
+| [sudo.has](#sudo-has) | 判断sudo是否支持 | >= 2.1.5 |
+| [sudo.run](#sudo-run) | 安静运行程序 | >= 2.1.5 |
+| [sudo.runv](#sudo-runv) | 安静运行程序,带参数列表 | >= 2.1.5 |
+| [sudo.exec](#sudo-exec) | 回显运行程序 | >= 2.1.5 |
+| [sudo.execv](#sudo-execv) | 回显运行程序,带参数列表 | >= 2.1.5 |
+| [sudo.iorun](#sudo-iorun) | 运行并获取程序输出内容 | >= 2.1.5 |
+| [sudo.iorunv](#sudo-iorunv) | 运行并获取程序输出内容,带参数列表 | >= 2.1.5 |
+
+###### sudo.has
+
+- 判断sudo是否支持
+
+目前仅在`macosx/linux`下支持sudo,windows上的管理员权限运行暂时还不支持,因此建议使用前可以通过此接口判断支持情况后,针对性处理。
+
+```lua
+import("privilege.sudo")
+
+if sudo.has() then
+ sudo.run("rm /system/file")
+end
+```
+
+###### sudo.run
+
+- 安静运行原生shell命令
+
+具体用法可参考:[os.run](#os-run)。
+
+```lua
+import("privilege.sudo")
+
+sudo.run("rm /system/file")
+```
+
+###### sudo.runv
+
+- 安静运行原生shell命令,带参数列表
+
+具体用法可参考:[os.runv](#os-runv)。
+
+###### sudo.exec
+
+- 回显运行原生shell命令
+
+具体用法可参考:[os.exec](#os-exec)。
+
+###### sudo.execv
+
+- 回显运行原生shell命令,带参数列表
+
+具体用法可参考:[os.execv](#os-execv)。
+
+###### sudo.iorun
+
+- 安静运行原生shell命令并获取输出内容
+
+具体用法可参考:[os.iorun](#os-iorun)。
+
+###### sudo.iorunv
+
+- 安静运行原生shell命令并获取输出内容,带参数列表
+
+具体用法可参考:[os.iorunv](#os-iorunv)。
+
+##### devel.git
+
+此接口提供了git各种命令的访问接口,相对于直接调用git命令,此模块提供了更加上层易用的封装接口,并且提供对git的自动检测和跨平台处理。
+
+<p class="tip">
+目前windows上,需要手动安装git包后,才能检测到,后续版本会提供自动集成git功能,用户将不用关心如何安装git,就可以直接使用。
+</p>
+
+| 接口 | 描述 | 支持版本 |
+| --------------------------------------------------- | -------------------------------------------- | -------------------- |
+| [git.clone](#git-clone) | clone代码库 | >= 2.1.5 |
+| [git.pull](#git-pull) | 拉取代码库最新提交 | >= 2.1.5 |
+| [git.clean](#git-clean) | 清理代码库文件 | >= 2.1.5 |
+| [git.checkout](#git-checkout) | 签出指定分支版本 | >= 2.1.5 |
+| [git.refs](#git-refs) | 获取所有引用列表 | >= 2.1.5 |
+| [git.tags](#git-tags) | 获取所有标记列表 | >= 2.1.5 |
+| [git.branches](#git-branches) | 获取所有分支列表 | >= 2.1.5 |
+
+###### git.clone
+
+- clone代码库
+
+此接口对应`git clone`命令
+
+```lua
+import("devel.git")
+
+git.clone("git@github.com:tboox/xmake.git")
+git.clone("git@github.com:tboox/xmake.git", {depth = 1, branch = "master", outputdir = "/tmp/xmake"})
+```
+
+###### git.pull
+
+- 拉取代码库最新提交
+
+此接口对应`git pull`命令
+
+```lua
+import("devel.git")
+
+git.pull()
+git.pull({remote = "origin", tags = true, branch = "master", repodir = "/tmp/xmake"})
+```
+
+###### git.clean
+
+- 清理代码库文件
+
+此接口对应`git clean`命令
+
+```lua
+import("devel.git")
+
+git.clean()
+git.clean({repodir = "/tmp/xmake", force = true})
+```
+
+###### git.checkout
+
+- 签出指定分支版本
+
+此接口对应`git checkout`命令
+
+```lua
+import("devel.git")
+
+git.checkout("master", {repodir = "/tmp/xmake"})
+git.checkout("v1.0.1", {repodir = "/tmp/xmake"})
+```
+
+###### git.refs
+
+- 获取所有引用列表
+
+此接口对应`git ls-remote --refs`命令
+
+```lua
+import("devel.git")
+
+local refs = git.refs(url)
+```
+
+###### git.tags
+
+- 获取所有标记列表
+
+此接口对应`git ls-remote --tags`命令
+
+```lua
+import("devel.git")
+
+local tags = git.tags(url)
+```
+
+###### git.branches
+
+- 获取所有分支列表
+
+此接口对应`git ls-remote --heads`命令
+
+```lua
+import("devel.git")
+
+local branches = git.branches(url)
+```
+
+##### utils.archive
+
+此模块用于压缩和解压缩文件。
+
+| 接口 | 描述 | 支持版本 |
+| --------------------------------------------------- | -------------------------------------------- | -------------------- |
+| [archive.extract](#archive-extract) | 解压文件 | >= 2.1.5 |
+
+###### archive.extract
+
+- 解压文件
+
+支持大部分常用压缩文件的解压,它会自动检测系统提供了哪些解压工具,然后适配到最合适的解压器对指定压缩文件进行解压操作。
+
+```lua
+import("utils.archive")
+
+archive.extract("/tmp/a.zip", "/tmp/outputdir")
+archive.extract("/tmp/a.7z", "/tmp/outputdir")
+archive.extract("/tmp/a.gzip", "/tmp/outputdir")
+archive.extract("/tmp/a.tar.bz2", "/tmp/outputdir")
+```
diff --git a/zh/plugins.md b/zh/plugins.md
new file mode 100644
index 00000000..36b1a948
--- /dev/null
+++ b/zh/plugins.md
@@ -0,0 +1,525 @@
+---
+nav: zh
+search: zh
+---
+
+## 插件开发
+
+#### 简介
+
+XMake完全支持插件模式,我们可以很方便的扩展实现自己的插件,并且xmake也提供了一些内建的使用插件。
+
+我们可以执行下 `xmake -h` 看下当前支持的插件:
+
+```
+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: 运行lua脚本的插件
+* macro: 这个很实用,宏脚本插件,可以手动录制多条xmake命令并且回放,也可以通过脚本实现一些复杂的宏脚本,这个我们后续会更加详细的介绍
+* doxygen:一键生成doxygen文档的插件
+* hello: 插件demo,仅仅显示一句话:'hello xmake!'
+* project: 生成工程文件的插件,目前仅支持(makefile),后续还会支持(vs,xcode等工程)的生成
+
+#### 快速开始
+
+接下来我们介绍下本文的重点,一个简单的hello xmake插件的开发,代码如下:
+
+```lua
+-- 定义一个名叫hello的插件任务
+task("hello")
+
+ -- 设置类型为插件
+ set_category("plugin")
+
+ -- 插件运行的入口
+ on_run(function ()
+
+ -- 显示hello xmake!
+ print("hello xmake!")
+
+ end)
+
+ -- 设置插件的命令行选项,这里没有任何参数选项,仅仅显示插件描述
+ set_menu {
+ -- usage
+ usage = "xmake hello [options]"
+
+ -- description
+ , description = "Hello xmake!"
+
+ -- options
+ , options = {}
+ }
+```
+
+这个插件的文件结构如下:
+
+```
+hello
+ - xmake.lua
+
+```
+
+现在一个最简单的插件写完了,那怎么让它被xmake检测到呢,有三种方式:
+
+1. 把 hello 这个文件夹放置在 xmake的插件安装目录 `xmake/plugins`,这个里面都是些内建的插件
+2. 把 hello 文件夹放置在 `~/.xmake/plugins` 用户全局目录,这样对当前xmake 全局生效
+3. 把 hello 文件夹放置在任意地方,通过在工程描述文件xmake.lua中调用`add_plugindirs("./hello")` 添加当前的工程的插件搜索目录,这样只对当前工程生效
+
+#### 运行插件
+
+接下来,我们尝试运行下这个插件:
+
+```console
+xmake hello
+```
+
+显示结果:
+
+```
+hello xmake!
+```
+
+最后我们还可以在target自定义的脚本中运行这个插件:
+
+```lua
+target("demo")
+
+ -- 构建之后运行插件
+ after_build(function (target)
+
+ -- 导入task模块
+ import("core.project.task")
+
+ -- 运行插件任务
+ task.run("hello")
+ end)
+```
+
+## 内置插件
+
+#### 宏记录和回放
+
+##### 简介
+
+我们可以通过这个插件,快速记录和回放我们平常频繁使用到的一些xmake操作,来简化我们日常的开发工作。
+
+它提供了一些功能:
+
+* 手动记录和回放多条执行过的xmake命令
+* 支持快速的匿名宏创建和回放
+* 支持命名宏的长久记录和重用
+* 支持宏脚本的批量导入和导出
+* 支持宏脚本的删除、显示等管理功能
+* 支持自定义高级宏脚本,以及参数配置
+
+##### 记录操作
+
+```console
+# 开始记录宏
+$ xmake macro --begin
+
+# 执行一些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
+
+# 结束宏记录,这里不设置宏名字,所以记录的是一个匿名宏
+xmake macro --end
+```
+
+##### 回放
+
+```console
+# 回放一个匿名宏
+$ xmake macro .
+```
+
+##### 命名宏
+
+匿名宏的好处就是快速记录,快速回放,如果需要长久保存,就需要给宏取个名字。
+
+```console
+$ xmake macro --begin
+$ ...
+$ xmake macro --end macroname
+$ xmake macro macroname
+```
+
+##### 导入导出宏
+
+导入指定的宏脚本或者宏目录:
+
+```console
+$ xmake macro --import=/xxx/macro.lua macroname
+$ xmake macro --import=/xxx/macrodir
+```
+
+导出指定的宏到脚本或者目录:
+
+```console
+$ xmake macro --export=/xxx/macro.lua macroname
+$ xmake macro --export=/xxx/macrodir
+```
+
+##### 列举显示宏
+
+列举所有`xmake`内置的宏脚本:
+
+```console
+$ xmake macro --list
+```
+
+显示指定的宏脚本内容:
+
+```console
+$ xmake macro --show macroname
+```
+
+##### 自定义宏脚本
+
+我们也可以自己编写个宏脚本 `macro.lua` 然后导入到xmake中去。
+
+```lua
+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
+```
+
+导入到xmake,并且定义宏名字:
+
+```console
+$ xmake macro --import=/xxx/macro.lua [macroname]
+```
+
+回放这个宏脚本:
+
+```console
+$ xmake macro [.|macroname]
+```
+
+##### 内置的宏脚本
+
+XMake 提供了一些内置的宏脚本,来简化我们的日常开发工作。
+
+例如,我们可以使用 `package` 宏来对`iphoneos`平台的所有架构,一次性批量构建和打包:
+
+```console
+$ xmake macro package -p iphoneos
+```
+
+##### 高级的宏脚本编写
+
+以上面提到的`package`宏为例,我们看下其具体代码,里面通过`import`导入一些扩展模块,实现了复杂的脚本操作。
+
+
+```lua
+-- 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">
+ 如果你想要获取更多宏参数选项信息,请运行: `xmake macro --help`
+</p>
+
+#### 运行自定义lua脚本
+
+这个跟宏脚本类似,只是省去了导入导出操作,直接指定lua脚本来加载运行,这对于想要快速测试一些接口模块,验证自己的某些思路,都是一个不错的方式。
+
+##### 运行指定的脚本文件
+
+我们先写个简单的lua脚本:
+
+```lua
+function main()
+ print("hello xmake!")
+end
+```
+
+然后直接运行它就行了:
+
+```console
+$ xmake lua /tmp/test.lua
+```
+
+<p class="tip">
+ 当然,你也可以像宏脚本那样,使用`import`接口导入扩展模块,实现复杂的功能。
+</p>
+
+##### 运行内置的脚本命令
+
+你可以运行 `xmake lua -l` 来列举所有内置的脚本名,例如:
+
+```console
+$ xmake lua -l
+scripts:
+ cat
+ cp
+ echo
+ versioninfo
+ ...
+```
+
+并且运行它们:
+
+```console
+$ xmake lua cat ~/file.txt
+$ xmake lua echo "hello xmake"
+$ xmake lua cp /tmp/file /tmp/file2
+$ xmake lua versioninfo
+```
+
+##### 运行交互命令 (REPL)
+
+有时候在交互模式下,运行命令更加的方便测试和验证一些模块和api,也更加的灵活,不需要再去额外写一个脚本文件来加载。
+
+我们先看下,如何进入交互模式:
+
+```console
+# 不带任何参数执行,就可以进入
+$ xmake lua
+>
+
+# 进行表达式计算
+> 1 + 2
+3
+
+# 赋值和打印变量值
+> a = 1
+> a
+1
+
+# 多行输入和执行
+> for _, v in pairs({1, 2, 3}) do
+>> print(v)
+>> end
+1
+2
+3
+```
+
+我们也能够通过 `import` 来导入扩展模块:
+
+```console
+> task = import("core.project.task")
+> task.run("hello")
+hello xmake!
+```
+
+如果要中途取消多行输入,只需要输入字符:`q` 就行了
+
+```console
+> for _, v in ipairs({1, 2}) do
+>> print(v)
+>> q <-- 取消多行输入,清空先前的输入数据
+> 1 + 2
+3
+```
+
+#### 生成IDE工程文件
+
+##### 简介
+
+XMake跟`cmake`, `premake`等其他一些构建工具的区别在于:
+
+<p class="warning">
+`xmake`默认是直接构建运行的,生成第三方的IDE的工程文件仅仅作为`插件`来提供。
+</p>
+
+这样做的一个好处是:插件更加容易扩展,维护也更加独立和方便。
+
+##### 生成Makefile
+
+```console
+$ xmake project -k makefile
+```
+
+##### 生成compiler_commands
+
+导出每个源文件的编译信息,生成基于clang的编译数据库文件,json格式,可用于跟ide,编辑器,静态分析工具进行交互。
+
+```console
+$ xmake project -k compile_commands
+```
+
+输出的内容格式如下:
+
+```
+[
+ { "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" },
+ ...
+]
+
+```
+
+对于`compile_commands`的详细说明见:[JSONCompilationDatabase](#https://clang.llvm.org/docs/JSONCompilationDatabase.html)
+
+##### 生成VisualStudio工程
+
+```console
+$ xmake project -k [vs2008|vs2013|vs2015|..]
+```
+
+v2.1.2以上版本,增强了vs201x版本工程的生成,支持多模式+多架构生成,生成的时候只需要指定:
+
+```console
+$ xmake project -k vs2017 -m "debug,release"
+```
+
+生成后的工程文件,同时支持`debug|x86`, `debug|x64`, `release|x86`, `release|x64`四种配置模式。
+
+如果不想每次生成的时候,指定模式,可以把模式配置加到`xmake.lua`的中,例如:
+
+```lua
+-- 配置当前的工程,支持哪些编译模式
+set_modes("debug", "release")
+```
+
+具体`set_modes`的使用,可以参考对应的接口手册文档。
+
+#### 生成doxygen文档
+
+请先确保本机已安装`doxygen`工具,然后在工程目录下运行:
+
+```console
+$ xmake doxygen
+```
+
+## 更多插件
+
+请到插件仓库进行下载安装: [xmake-plugins](https://github.com/tboox/xmake-plugins).
+
+#### 从app生成ipa包
+
+这仅仅是一个小插件,ios开发的同学,可能会用的到。
+
+```console
+$ xmake app2ipa --icon=/xxx.png /xxx/ios.app -o /xxx.ios.ipa
+```