Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 67 additions & 1 deletion docs/api/description/builtin-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,10 @@ cat build/.gens/test/macosx/x86_64/release/rules/c++/bin2c/image.png.h
If you are using a compiler that supports the C23 `#embed` feature (such as clang or gcc), you can also use the `#embed` directive directly to embed binary files. You need to set the C23 language standard first via `set_languages("c23")`, and then use [add_embeddirs](project-target.md#add_embeddirs) to set the search path. This approach is more aligned with the C23 standard and does not require generating additional header files.
:::

### Transform <Badge type="tip" text="v3.1.0" />

Since v3.1.0, binary files can be transformed before being generated as a header. Transform functions are assigned in the same way as [utils.bin2obj](#transform-1).

## utils.bin2obj

New rule added in v3.0.6 to convert binary files to object files and link them into the target program.
Expand All @@ -721,7 +725,7 @@ target("myapp")
add_files("assets/data.bin", {zeroend = true})
```

### Access Data
### Accessing Data

In C/C++ code, we can access the embedded data via symbols. The symbol name generation rule is: `_binary_<filename>_start` and `_binary_<filename>_end`.
Non-alphanumeric characters in the filename are replaced with underscores.
Expand All @@ -746,6 +750,68 @@ int main() {
}
```

### Transform <Badge type="tip" text="v3.1.0" />

Since v3.1.0, binary files can be transformed before converting into object files by using the newly added `transform` parameter. For example, an asset file can be compressed using LZ4 ([core.compress.lz4](../scripts/extension-modules/core/compress/lz4.md)) before embedding into the application. See below for detailed usage.

#### Inline Function

Inline function can be used to transform the binary file. Suitable for short and simple conversions.

```lua
target("test")
set_kind("binary")
add_rules("utils.bin2obj")
add_files("src/*.c")
add_files("src/asset.bin", {transform = function (inputfile, outputfile, opt)
import("core.base.bytes")
local data = io.readfile(inputfile, {encoding = "binary"})
io.writefile(outputfile, data:reverse(), {encoding = "binary"})
end})
```

::: tip WARNING
Inline transform functions are not compatible with [generated projects](../../guide/extensions/builtin-plugins.md#generate-ide-project-files). Write the function in a lua file instead.
:::

#### Function In Lua File

For more complex transforms, writing the function in a separate lua file keeps the code clear.

`xmake.lua`:
```lua
target("test")
set_kind("binary")
add_rules("utils.bin2obj")
add_files("src/*.c")
add_files("src/asset.bin", {transform = path.join(os.projectdir(), "transform.lua")})
```

`transform.lua`:
```lua
function main(inputfile, outputfile)
import("core.base.bytes")
local data = io.readfile(inputfile, {encoding = "binary"})
io.writefile(outputfile, data:reverse(), {encoding = "binary"})
end
```

#### Per-rule Transform Function

Besides writing a function for each file or file group, a transform function can also be applied across the entire rule scope.

```lua
add_rules("utils.bin2obj", {
transform = path.join(os.projectdir(), "transform.lua")
})
```

::: tip NOTE
- Remember to pass argument `{encoding = "binary"}` to `io.readfile` or `io.writefile` when reading or writing binary data
- It's preferred to pass an absolute path (formed by joining `os.projectdir()` with the relative path) to the transform lua file
- See [core.base.bytes](../scripts/extension-modules/core/base/bytes.md) for handling binary data
:::

## utils.replace <Badge type="tip" text="v3.0.9" />

This rule applies in-memory text substitutions on a source file before it is fed to the compiler. The rewritten file is written under the target's auto-generated directory, and the original file's directory is automatically added to `includedirs` so relative `#include` directives in the rewritten file still resolve.
Expand Down
66 changes: 66 additions & 0 deletions docs/zh/api/description/builtin-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,10 @@ cat build/.gens/test/macosx/x86_64/release/rules/c++/bin2c/image.png.h
如果你使用支持 C23 `#embed` 特性的编译器(如 clang 或 gcc),也可以直接使用 `#embed` 指令来嵌入二进制文件。需要先通过 `set_languages("c23")` 设置 C23 语言标准,然后使用 [add_embeddirs](project-target.md#add_embeddirs) 来设置搜索路径。这种方式更符合 C23 标准,无需生成额外的头文件。
:::

### 转换函数 <Badge type="tip" text="v3.1.0" />

在v3.1.0中,xmake添加了转换函数接口。利用该接口,可以自定义被生成为头文件的二进制数据。用法请参考 [utils.bin2obj](#转换函数-1)

## utils.bin2obj

v3.0.6 以上版本可以使用此规则,相比 `utils.bin2c` 具有极快的构建速度。因为它跳过了 C 代码生成和编译步骤,直接生成对象文件(COFF, ELF, Mach-O)参与链接。
Expand Down Expand Up @@ -736,6 +740,68 @@ int main() {

此外,`glsl2spv` 和 `hlsl2spv` 规则也新增了对 `bin2obj` 的支持,可以直接将编译后的 SPIR-V 文件作为对象文件嵌入。

### 转换函数 <Badge type="tip" text="v3.1.0" />

在v3.1.0中,xmake添加了转换函数接口。利用该接口,可以自定义被生成为对象文件的二进制数据,如使用LZ4([core.compress.lz4](../scripts/extension-modules/core/compress/lz4.md))压缩文件后再生成为对象文件,嵌入程序中。

#### 内联转换函数

转换函数可内联在描述域中,适合简单的转换:

```lua
target("test")
set_kind("binary")
add_rules("utils.bin2obj")
add_files("src/*.c")
add_files("src/asset.bin", {transform = function (inputfile, outputfile, opt)
import("core.base.bytes")
local data = io.readfile(inputfile, {encoding = "binary"})
io.writefile(outputfile, data:reverse(), {encoding = "binary"})
end})
```

::: tip 警告
内联转换函数无法用于生成的第三方工程文件(见[生成IDE工程文件](../../guide/extensions/builtin-plugins.md#generate-ide-project-files))。如有需要,请使用Lua文件形式
:::

#### Lua文件形式

对于更加复杂的转化,可以将转换函数单独写在Lua文件中:

`xmake.lua`:
```lua
target("test")
set_kind("binary")
add_rules("utils.bin2obj")
add_files("src/*.c")
add_files("src/asset.bin", {transform = path.join(os.projectdir(), "transform.lua")})
```

`transform.lua`:
```lua
function main(inputfile, outputfile)
import("core.base.bytes")
local data = io.readfile(inputfile, {encoding = "binary"})
io.writefile(outputfile, data:reverse(), {encoding = "binary"})
end
```

#### 规则级转换函数

转换函数不仅可作用于文件或者文件组,还可以写成以下的形式,以作用于整个规则:

```lua
add_rules("utils.bin2obj", {
transform = path.join(os.projectdir(), "transform.lua")
})
```

::: tip 提示
- 在使用`io.readfile`或`io.writefile`处理二进制时,记得加入`{encoding = "binary"}`参数
- 使用Lua形式转换函数时,最好传入由`path.join(os.projectdir(), <路径>)`得到的绝对路径
- 可参考xmake提供的二进制处理API:[core.base.bytes](../scripts/extension-modules/core/base/bytes.md)
:::

## utils.replace <Badge type="tip" text="v3.0.9" />

此规则会在源码送入编译器之前对其做文本替换。替换后的文件会写到目标的自动生成目录下,同时原始文件所在目录会被自动加入 `includedirs`,所以替换后文件里的相对 `#include` 依然能正确解析。
Expand Down
Loading