# API

[链接](https://www.bookstack.cn/read/xmake/manual-project_target.md)

`api("param1","param2",...,dict_prop)`

`on_script("dir.file") || on_script(function(...) end)  `

## [命名规范](https://www.bookstack.cn/read/xmake/manual-specification.md)

接口的命名，是有按照预定义的一些规范来命名的，这样更加方便理解和易于使用，目前命名按照如下一些规则：

| 接口规则                | 描述                                                         |
| ----------------------- | ------------------------------------------------------------ |
| `is_`, `has_`前缀的接口 | 表示为条件判断                                               |
| `set_`前缀的接口        | 表示为覆盖设置                                               |
| `add_`前缀的接口        | 表示为追加设置                                               |
| `s`后缀的接口           | 表示支持多值传入，例如：`add_files("*.c", "test.cpp")`       |
| `on_`前缀的接口         | 表示为覆盖内置脚本                                           |
| `before_`前缀的接口     | 表示为在内置脚本运行前，执行此脚本                           |
| `after_`前缀的接口      | 表示为在内置脚本运行后，执行此脚本                           |
| `scope("name")`的接口   | 表示为定义一个描述域，例如：`target("xxx")`, `option("xxx")` |
| 描述域/描述设置         | 建议缩进表示                                                 |

## [条件判断](https://www.bookstack.cn/read/xmake/manual-conditions.md)

条件判断的api，一般用于必须要处理特定平台的编译逻辑的场合。。通常跟lua的if语句配合使用。

| 接口                                                         | 描述                         | 支持版本                |
| ------------------------------------------------------------ | ---------------------------- | ----------------------- |
| [is_os](https://www.bookstack.cn/read/xmake/manual-conditions.md#is_os) | 判断当前构建目标的操作系统   | >= 2.0.1                |
| [is_arch](https://www.bookstack.cn/read/xmake/manual-conditions.md#is_arch) | 判断当前编译架构             | >= 2.0.1                |
| [is_plat](https://www.bookstack.cn/read/xmake/manual-conditions.md#is_plat) | 判断当前编译平台             | >= 2.0.1                |
| [is_host](https://www.bookstack.cn/read/xmake/manual-conditions.md#is_host) | 判断当前主机环境操作系统     | >= 2.1.4                |
| [is_mode](https://www.bookstack.cn/read/xmake/manual-conditions.md#is_mode) | 判断当前编译模式             | >= 2.0.1                |
| [is_kind](https://www.bookstack.cn/read/xmake/manual-conditions.md#is_kind) | 判断当前编译类型             | >= 2.0.1                |
| [is_option](https://www.bookstack.cn/read/xmake/manual-conditions.md#is_option) | 判断选项是否启用             | >= 2.0.1 < 2.2.2 已废弃 |
| [is_config](https://www.bookstack.cn/read/xmake/manual-conditions.md#is_config) | 判断指定配置是否为给定的值   | >= 2.2.2                |
| [has_config](https://www.bookstack.cn/read/xmake/manual-conditions.md#has_config) | 判断配置是否启用或者存在     | >= 2.2.2                |
| [has_package](https://www.bookstack.cn/read/xmake/manual-conditions.md#has_package) | 判断依赖包是否被启用或者存在 | >= 2.2.3                |

## 特殊字符

### 正则表达式

```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")

-- 批量导入配置文件
includes("test/**/xmake.lua")
```



### [内置变量](https://www.bookstack.cn/read/xmake/manual-builtin_variables.md)

```lua
target("test")

    -- 添加工程源码目录下的源文件
    add_files("$(projectdir)/src/*.c")

    -- 添加构建目录下的头文件搜索路径
    add_includedirs("$(buildir)/inc")
```



| 接口                                                         | 描述                        | 支持版本 |
| ------------------------------------------------------------ | --------------------------- | -------- |
| [$(os)](https://xmake.io/mirror/zh-cn/manual/builtin_variables.html#varos) | 获取当前编译平台的操作系统  | >= 2.0.1 |
| [$(host)](https://xmake.io/mirror/zh-cn/manual/builtin_variables.html#varhost) | 获取本机操作系统            | >= 2.0.1 |
| [$(tmpdir)](https://xmake.io/mirror/zh-cn/manual/builtin_variables.html#vartmpdir) | 获取临时目录                | >= 2.0.1 |
| [$(curdir)](https://xmake.io/mirror/zh-cn/manual/builtin_variables.html#varcurdir) | 获取当前目录                | >= 2.0.1 |
| [$(buildir)](https://xmake.io/mirror/zh-cn/manual/builtin_variables.html#varbuildir) | 获取构建输出目录            | >= 2.0.1 |
| [$(scriptdir)](https://xmake.io/mirror/zh-cn/manual/builtin_variables.html#varscriptdir) | 获取工程描述脚本目录        | >= 2.1.1 |
| [$(globaldir)](https://xmake.io/mirror/zh-cn/manual/builtin_variables.html#varglobaldir) | 获取全局配置目录            | >= 2.0.1 |
| [$(configdir)](https://xmake.io/mirror/zh-cn/manual/builtin_variables.html#varconfigdir) | 获取本地工程配置目录        | >= 2.0.1 |
| [$(programdir)](https://xmake.io/mirror/zh-cn/manual/builtin_variables.html#varprogramdir) | xmake安装脚本目录           | >= 2.1.5 |
| [$(projectdir)](https://xmake.io/mirror/zh-cn/manual/builtin_variables.html#varprojectdir) | 获取工程根目录              | >= 2.0.1 |
| [$(shell)](https://xmake.io/mirror/zh-cn/manual/builtin_variables.html#varshell) | 执行外部shell命令           | >= 2.0.1 |
| [$(env)](https://xmake.io/mirror/zh-cn/manual/builtin_variables.html#varenv) | 获取外部环境变量            | >= 2.1.5 |
| [$(reg)](https://xmake.io/mirror/zh-cn/manual/builtin_variables.html#varreg) | 获取windows注册表配置项的值 | >= 2.1.5 |

## 模块接口

### [内置模块](https://www.bookstack.cn/read/xmake/manual-builtin_modules.md)

### [扩展模块](https://www.bookstack.cn/read/xmake/manual-extension_modules.md)

### 常用接口

- import
- includes

## 测试

```lua
  
on_test(function (package)
    assert(package:has_cxxfuncs("func1", {includes = "xxx.h", configs = {defines = "c++14", cxflags = "-Dxxx"}}))
end)

on_test(function (package)
    assert(package:check_cxxsnippets({test = [[
            #include <boost/algorithm/string.hpp>
            #include <string>
            #include <vector>
            #include <assert.h>
            using namespace boost::algorithm;
            using namespace std;
            static void test() {
                string str("a,b");
                vector<string> strVec;
                split(strVec, str, is_any_of(","));
                assert(strVec.size()==2);
                assert(strVec[0]=="a");
                assert(strVec[1]=="b");
            }
        ]]}, {configs = {languages = "c++14"}}))
    end)
```



# 项目配置

## [config.lua](https://www.bookstack.cn/read/xmake/guide-configuration.md)

相当于命令行配置，优先级最高

### 类型

本地配置会覆盖全局配置

- 全局配置
  - 所有项目生效
- 本地配置
  - 本地项目生效

### 作用

- 设置编译选项
- 设置环境变量
- 设置项目配置

## xmake.lua

```lua
-- 全局根作用域，影响所有target，包括includes() 中的子工程target设置
add_defines("DEBUG")

option("test")
	set_default(false)
-- 显示结束作用域
option_end()

-- 隐式结束上一个作用域
target("demo")
	set_kind("binary")
	add_files("src/*.c")
target_end()
```

### 配置域

 `set_xxx`/`add_xxx`的配置集，用于静态的生成lua对象的属性集

配置域通过includes 导入子配置

配置文件在不同阶段会被多次解析 **会被执行多遍！**

- 配置里可以加入简单的逻辑判断
- 沙盒环境，被禁止执行复杂操作（屏蔽接口）

### 描述域

命令行中的属性优先级最高，会影响到所有设置

进入另一个target/option域设置，会自动离开上个target/option域，但是有时候为了比较一些作用域污染情况，我们可以显示离开某个域

- 命令行
- 配置域
- 全局域
- 范围域

### 脚本域

导入后就可以直接使用里面的所有公有接口，私有接口用`_`前缀标示，表明不会被导出，不会被外部调用到。

其中 main 为入口函数，可选，如果设置，模块 foo 可以直接被调用

- 在指定时机中执行复杂操作,只执行一遍
- 脚本域中开放所有接口，可执行任何操作

#### on_link

```lua
--定制化处理target的链接过程
target("test")
    on_link(function (target) 
        print("link it")
    end)
```

#### on_build

```lua
--[[
覆盖target目标默认的构建行为，实现自定义的编译过程，
一般情况下，并不需要这么做，除非确实需要做一些xmake默认没有提供的编译操作
如果第一个参数为字符串，那么就是指定这个脚本需要在哪个平台|架构下，才会被执行
]]
target("test")
    on_build("iphoneos|arm*", function (target)
        print("build for iphoneos and arm")
    end)
```

#### on_build_file

```lua
--通过此接口，可以用来hook指定target内置的构建过程，自己重新实现每个源文件编译过程
target("test")
    set_kind("binary")
    add_files("src/*.c")
    on_build_file(function (target, sourcefile, opt)
    end)
```

#### on_build_files

```lua
--通过此接口，可以用来hook指定target内置的构建过程，替换一批同类型源文件编译过程：
target("test")
    set_kind("binary")
    add_files("src/*.c")
    on_build_files(function (target, sourcebatch, opt)
    end)
```

其中sourcebatch描述了这批同类型源文件：

- `sourcebatch.sourcekind`: 获取这批源文件的类型，比如：cc, as, ..
- `sourcebatch.sourcefiles()`: 获取源文件列表
- `sourcebatch.objectfiles()`: 获取对象文件列表
- `sourcebatch.dependfiles()`: 获取对应依赖文件列表，存有源文件中编译依赖信息，例如：xxx.d

#### on_clean

```lua
--覆盖target目标的xmake [c|clean}的清理操作，实现自定义清理过程。
target("test")

    -- 设置自定义清理脚本
    on_clean(function (target) 

        -- 仅删掉目标文件
        os.rm(target:targetfile())
    end)
```

#### on_package

```lua
--覆盖target目标的xmake [p|package}的打包操作，实现自定义打包过程，如果你想对指定target打包成自己想要的格式，可以通过这个接口自定义它
target("demo")
    set_kind("shared")
    add_files("jni/*.c")
    on_package(function (target) 
        os.exec("./gradlew app:assembleDebug") 
    end)
```

#### on_install

```lua
--覆盖target目标的xmake [i|install}的安装操作，实现自定义安装过程
target("test")

    -- 设置自定义安装脚本，自动安装apk文件
    on_install(function (target) 

        -- 使用adb安装打包生成的apk文件
        os.run("adb install -r ./bin/Demo-debug.apk")
    end)
```

#### on_uninstall

```lua
--覆盖target目标的xmake [u|uninstall}的卸载操作，实现自定义卸载过程
target("test")
    on_uninstall(function (target) 
        ...
    end)
```

#### on_run

```lua
--覆盖target目标的xmake [r|run}的运行操作，实现自定义运行过程。
target("test")

    -- 设置自定义运行脚本，自动运行安装好的app程序，并且自动获取设备输出信息
    on_run(function (target) 
        os.run("adb shell am start -n com.demo/com.demo.DemoTest")
        os.run("adb logcat")
    end)
```

#### on_link

```lua
--定制化处理target的链接过程
target("test")
    on_link(function (target) 
        print("link it")
    end)
```

#### 扩展事件

- before_xxx
- after_xxx

target:on_xxx的所有接口都覆盖内部默认实现，通常我们并不需要完全复写，只是额外挂接自己的一些逻辑，那么可以使用`target:before_xxx`和`target:after_xxx`系列脚本就行了。

所有的on_xxx都有对应的before_和after_xx版本，参数也完全一致

## 文件拆分

文件间存在树形继承关系，当前文件目录为工作空间

### 配置域

配置域通过includes 导入子配置

- 拆分属性配置到多个文件
- 支持批量导入

### 脚本域

不仅可以使用大部分lua的api，还可以使用很多xmake提供的扩展模块

所有扩展模块，通过import来导入

# [Target](https://www.bookstack.cn/read/xmake/manual-project_target.md)

- 项目属性配置
- 项目间存在继承关系

## 项目配置

```lua
-- 批量导入配置文件
includes("test/**/xmake.lua")

target("test")
    --  静态库 | 动态库 | 可执行程序
    -- static | shared | binary
    set_kind("binary")

	-- 源文件
	add_files("src/*.cpp")
    -- 删除指定文件
    del_files("src/test.c")
    -- 头文件
    add_headerfiles("src/*.h")
    
	-- 头文件目录
    add_includedirs("/usr/local/include")
    -- 库目录
    add_linkdirs("/usr/local/lib")

	-- 链接 非系统库
    add_links("pthread")
    -- 链接 系统库
    add_syslinks("pthread")

	-- 项目依赖，会自动添加目录与库
    add_deps("lua")
    -- 就继承了 lua 的所有导出设置：linkdirs, links, includedirs以及defines
    -- {inherit = false} 可禁止配置继承
	
	-- 添加第三方库依赖
	add_requires("lua")
	-- 链接第三方库
	add_packages("lua")
```

## 第三方库

```lua
-- 远程第三方仓库集
add_repositories("my-repo git@github.com:myrepo/xmake-repo.git")
-- 本地第三方仓库集
add_repositories("my-repo myrepo")

-- 定义第三方库
package("libjpeg")
    set_urls("http://www.ijg.org/files/jpegsrc.$(version).tar.gz")
    add_versions("v9c", "650250979303a649e21f87b5ccd02672af1ea6954b911342ea491f351ceb7122")
    on_install("windows", function (package)
        os.mv("jconfig.vc", "jconfig.h")
        os.vrun("nmake -f makefile.vc")
        os.cp("*.h", package:installdir("include"))
        os.cp("libjpeg.lib", package:installdir("lib"))
    end)
    on_install("macosx", "linux", function (package)
        import("package.tools.autoconf").install(package)
    end)
package_end()

--语义版本支持，例如：”>= 1.1.0 < 1.2”, “~1.6”, “1.2.x”, “1.*”
add_requires("lua 5.4.*", "libpng ~1.16", "brew::zlib", {alias = "zlib"})
add_requires("vcpkg::zlib", "vcpkg::pcre2")
```



## 编译配置

```lua
-- 启用调试符号
set_symbols("debug")
-- 隐藏符号
set_symbols("hidden")
-- 添加扩展指令集
add_vectorexts("sse2", "sse3", "ssse3", "mmx")

-- 仅添加C代码相关编译flags
add_cflags("-g", "-O2", "-DDEBUG")
-- 添加C/C++代码相关编译flags
add_cxflags("-g", "-O2", "-DDEBUG")
-- 仅添加C++代码相关编译flags
add_cxxflags("-g", "-O2", "-DDEBUG", {force = true})

-- force 强制检测 flag 是否添加成功

-- 设置语言标准
set_languages("c99", "c++11")

-- 编译优化选项
set_optimize("fastest")

set_toolchain("cxx", "clang")
set_toolchain("ld", "clang++")

-- 设置 xmake f 参数默认值,优先级最高
set_config("cflags", "-DTEST")
set_config("sdk", "/home/xxx/tooksdk")
set_config("cc", "gcc")
set_config("ld", "g++")
```



## Lua对象接口

| Target 接口                      |                    |
| -------------------------------- | ------------------ |
| target:name()                    | 获取目标名         |
| target:targetfile()              | 获取目标文件路径   |
| target:targetkind()              | 获取目标构建类型   |
| target:get("defines")            | 获取目标宏定义     |
| target:get("xxx")                | 获取set_/add_ 信息 |
| target:add("link","pthread")     | 添加目标设置       |
| target:set("link","pthread","z") | 覆写目标设置       |
| target:deps()                    | 获取目标所有依赖   |
| target:dep("depname")            | 获取指定依赖       |
| target:opts(")                   | 获取所有关联选项   |
| target:opt("optname")            | 获取指定关联选项   |
| target:pkgs()                    | 获取所有关联依赖包 |
| target:pkg("pkgname")            | 获取指定关联依赖包 |
| target:sourcebatches()           | 获取所有源文件列表 |



# Rule

- 属性与事件组成特定实体
- 方便继承到其他域中
- 项目间存在组合关系


# Package

第三方库配置

- 语义版本支持，例如：”>= 1.1.0 < 1.2”, “~1.6”, “1.2.x”, “1.*”

第三方库的配置和项目配置不一样

kind 决定 package 如何用于 项目

- 程序依赖
- 库依赖
- 源码依赖

## 接口

- #### 类型

  - #### set_kind

- #### 版本

  - #### set_urls

  - #### add_urls

  - #### add_versions

  - #### add_patches

- #### 参数

  - #### add_configs

```lua
-- 源码地址
set_urls("https://ffmpeg.org/releases/ffmpeg-$(version).tar.bz2", {alias = "home"})
add_urls("https://github.com/FFmpeg/FFmpeg/archive/n$(version).zip", {alias = "github"})
add_urls("https://gitlab.gnome.org/GNOME/libxml2.git")

-- 源码包 与 哈希码
add_versions("home:4.0.2", "346c51735f42c37e0712e0b3d2f6476c86ac15863e4445d9e823fe396420d056")
add_versions("github:4.0.2", "4df1ef0bf73b7148caea1270539ef7bd06607e0ea8aa2fbf1bb34062a097f026")

-- 版本补丁
add_patches("1.15", "https://raw.githubusercontent.com/Homebrew/patches/9be2793af/libiconv/patch-utf8mac.diff",
    "e8128732f22f63b5c656659786d2cf76f1450008f36bcf541285268c66cabeab")

-- 配置自定义参数 与 参数描述
add_configs("bitwidth", {description = "Set the code unit width.", default = "8", values = {"8", "16", "32"}})

package("luasocket")
	-- 设置类型 binary 不可省略
    set_kind("library")
    set_homepage("https://cmake.org")
    set_description("A cross-platform family of tool designed to build, test and package software")
```



# Option

xmake 命令后加入可选配置



# Task

```shell
#task project
#option : k m
#kind vsxmake2022 
#mode "debug;release"
xmake project -k vsxmake2022 -m "debug;release"
xmake project --help
```



xmake可以实现自定义任务或者插件，其两者的核心就是`task`任务，其两者实际上是一样的，xmake的插件都是用`task`实现的。

本质上都是任务，只是[set_category](https://www.bookstack.cn/read/xmake/manual-plugin_task.md#taskset_category)分类不同而已。

| 接口                                                         | 描述               | 支持版本 |
| ------------------------------------------------------------ | ------------------ | -------- |
| [task](https://www.bookstack.cn/read/xmake/manual-plugin_task.md#task) | 定义插件或者任务   | >= 2.0.1 |
| [task_end](https://www.bookstack.cn/read/xmake/manual-plugin_task.md#task_end) | 结束定义插件或任务 | >= 2.1.1 |
| [set_menu](https://www.bookstack.cn/read/xmake/manual-plugin_task.md#taskset_menu) | 设置任务菜单       | >= 2.0.1 |
| [set_category](https://www.bookstack.cn/read/xmake/manual-plugin_task.md#taskset_category) | 设置任务类别       | >= 2.0.1 |
| [on_run](https://www.bookstack.cn/read/xmake/manual-plugin_task.md#taskon_run) | 设置任务运行脚本   | >= 2.0.1 |
