---
url: /api/description/builtin-rules.md
---
# Builtin Rules

sinceAfter the 2.2.1 release, xmake provides some built-in rules to simplify the daily xmake.lua description and support for some common build environments.

We can view the complete list of built-in rules by running the following command:

```sh
$ xmake show -l rules
```

Built-in rules are applied to targets via [add\_rules()](/api/description/project-target#add-rules). To create custom rules, see [Custom Rule API](/api/description/custom-rule). For related policy configurations, see [Built-in Policies](/api/description/builtin-policies).

## mode.debug

Add the configuration rules for the debug compilation mode for the current project xmake.lua, for example:

```lua
add_rules("mode.debug")
```

Equivalent to:

```lua
if is_mode("debug") then
    set_symbols("debug")
    set_optimize("none")
end
```

We can switch to this compilation mode by `xmake f -m debug`.

## mode.release

Add the configuration rules for the release compilation mode for the current project xmake.lua, for example:

```lua
add_rules("mode.release")
```

Equivalent to:

```lua
if is_mode("release") then
    set_symbols("hidden")
    set_optimize("fastest")
    set_strip("all")
end
```

We can switch to this compilation mode by `xmake f -m release`.

## mode.releasedbg

Add the configuration rules for the releasedbg compilation mode for the current project xmake.lua, for example:

```lua
add_rules("mode.releasedbg")
```

::: tip NOTE
The built-in releasedbg mode generates an executable program without any symbols, and the debugging symbols exist as separate files.
:::

They exhibit consistent behavior across different platforms:

* **A minimal release program without debug symbols + A separate debug symbol file.**
* **on windows**: release program + .pdb debug symbol file
* **on macOS**: release program + .dSYM debug symbol file
* **on linux**: release program + .sym debug symbol file

Although on Linux, the executable program has stripped its debug symbols, the generated .sym debug symbol file has already been associated with the executable program via objcopy. We can use gdb to load its debug symbols normally.

```sh
/usr/bin/objcopy --only-keep-debug build/linux/x86_64/releasedbg/test build/linux/x86_64/releasedbg/test.sym
/usr/bin/strip -s build/linux/x86_64/releasedbg/test
/usr/bin/objcopy --add-gnu-debuglink=build/linux/x86_64/releasedbg/test.sym build/linux/x86_64/releasedbg/test
```

gdb will automatically load the test.sym symbol file.

```sh
gdb build/linux/x86_64/releasedbg/test
Reading symbols from build/linux/x86_64/releasedbg/test...
Reading symbols from /tmp/test/build/linux/x86_64/releasedbg/test.sym...
(gdb) b main
Breakpoint 1 at 0x10e0: file src/main.cpp, line 3.
(gdb) r
Starting program: /tmp/test/build/linux/x86_64/releasedbg/test 
Breakpoint 1, main (argc=1, argv=0x7ffd8daf0618) at src/main.cpp:3
3	int main(int argc, char **argv) {
(gdb) bt
#0  main (argc=1, argv=0x7ffd8daf0618) at src/main.cpp:3
(gdb) 
```

Equivalent to:

```lua
if is_mode("releasedbg") then
    set_symbols("debug")
    set_optimize("fastest")
    set_strip("all")
end
```

We can switch to this compilation mode by `xmake f -m releasedbg`.

If you want to generate a single executable with debug symbols, you can easily override the releasedbg mode in your project configuration.

```lua
add_rules("mode.release", "mode.releasedbg")

if is_mode("releasedbg") then
    set_strip("none")
end
```

You can also fully customize the releasedbg mode rules without using the built-in mode.releasedbg.

## mode.minsizerel

Add the configuration rules for the minsizerel compilation mode for the current project xmake.lua, for example:

```lua
add_rules("mode.minsizerel")
```

::: tip NOTE
Compared with the release mode, this mode is more inclined to the minimum code compilation optimization, rather than speed priority.
:::

相当于：

```lua
if is_mode("minsizerel") then
    set_symbols("hidden")
    set_optimize("smallest")
    set_strip("all")
end
```

We can switch to this compilation mode by `xmake f -m minsizerel`.

## mode.check

Add the check compilation mode configuration rules for the current project xmake.lua, generally used for memory detection, for example:

```lua
add_rules("mode.check")
```

Equivalent to:

```lua
if is_mode("check") then
    set_symbols("debug")
    set_optimize("none")
    add_cxflags("-fsanitize=address", "-ftrapv")
    add_mxflags("-fsanitize=address", "-ftrapv")
    add_ldflags("-fsanitize=address")
end
```

We can switch to this compilation mode by `xmake f -m check`.

## mode.profile

Add configuration rules for the profile compilation mode for the current project xmake.lua, which is generally used for performance analysis, for example:

```lua
add_rules("mode.profile")
```

Equivalent to:

```lua
if is_mode("profile") then
    set_symbols("debug")
    add_cxflags("-pg")
    add_ldflags("-pg")
end
```

We can switch to this compilation mode by `xmake f -m profile`.

## mode.coverage

Add the configuration rules for the coverage compilation mode for the current project xmake.lua, which is generally used for coverage analysis, for example:

```lua
add_rules("mode.coverage")
```

Equivalent to:

```lua
if is_mode("coverage") then
    add_cxflags("--coverage")
    add_mxflags("--coverage")
    add_ldflags("--coverage")
end
```

We can switch to this compilation mode by `xmake f -m coverage`.

## mode.valgrind

This mode provides valgrind memory analysis and detection support.

```lua
add_rules("mode.valgrind")
```

We can switch to this compilation mode by: `xmake f -m valgrind`.

## mode.asan

This mode provides AddressSanitizer memory analysis and detection support.

```lua
add_rules("mode.asan")
```

We can switch to this compilation mode by: `xmake f -m asan`.

## mode.tsan

This mode provides ThreadSanitizer memory analysis and detection support.

```lua
add_rules("mode.tsan")
```

We can switch to this compilation mode by: `xmake f -m tsan`.

## mode.lsan

This mode provides LeakSanitizer memory analysis and detection support.

```lua
add_rules("mode.lsan")
```

We can switch to this compilation mode by: `xmake f -m lsan`.

## mode.ubsan

This mode provides UndefinedBehaviorSanitizer memory analysis and detection support.

```lua
add_rules("mode.ubsan")
```

We can switch to this compilation mode by: `xmake f -m ubsan`.

## qt.static

A static library program used to compile and generate Qt environments:

```lua
target("test")
    add_rules("qt.static")
    add_files("src/*.cpp")
    add_frameworks("QtNetwork", "QtGui")
```

## qt.shared

Dynamic library program for compiling and generating Qt environment:

```lua
target("test")
    add_rules("qt.shared")
    add_files("src/*.cpp")
    add_frameworks("QtNetwork", "QtGui")
```

## qt.console

A console program for compiling and generating a Qt environment:

```lua
target("test")
    add_rules("qt.console")
    add_files("src/*.cpp")
```

## qt.quickapp

Quick(qml) ui application for compiling and generating Qt environment.

```lua
target("test")
    add_rules("qt.quickapp")
    add_files("src/*.cpp")
    add_files("src/qml.qrc")
```

## qt.quickapp\_static

Quick(qml) ui application (statically linked version) for compiling and generating Qt environment.

::: tip NOTE
Need to switch to static library version Qt SDK
:::

```lua
target("test")
    add_rules("qt.quickapp_static")
    add_files("src/*.cpp")
    add_files("src/qml.qrc")
```

## qt.widgetapp

Used to compile Qt Widgets (ui/moc) applications

```lua
target("test")
    add_rules("qt.widgetapp")
    add_files("src/*.cpp")
    add_files("src/mainwindow.ui")
    add_files("src/mainwindow.h") -- add meta header files with Q_OBJECT
```

## qt.widgetapp\_static

Used to compile Qt Widgets (ui/moc) applications (static library version)

::: tip NOTE
Need to switch to static library version Qt SDK
:::

```lua
target("test")
    add_rules("qt.widgetapp_static")
    add_files("src/*.cpp")
    add_files("src/mainwindow.ui")
    add_files("src/mainwindow.h") -- add meta header files with Q_OBJECT
```

For more descriptions of Qt, see: [#160](https://github.com/xmake-io/xmake/issues/160)

## xcode.bundle

Used to compile and generate ios/macos bundle program

```lua
target("test")
     add_rules("xcode.bundle")
     add_files("src/*.m")
     add_files("src/Info.plist")
```

## xcode.framework

Used to compile and generate ios/macos framework program

```lua
target("test")
     add_rules("xcode.framework")
     add_files("src/*.m")
     add_files("src/Info.plist")
```

## xcode.application

Used to compile and generate ios/macos applications

```lua
target("test")
    add_rules("xcode.application")
    add_files("src/*.m", "src/**.storyboard", "src/*.xcassets")
    add_files("src/Info.plist")
```

## android.native\_app

Used to build Android Native applications.

```lua
add_rules("mode.debug", "mode.release")

add_requires("raylib 5.5.0")

target("raydemo_custom_glue")
    set_kind("binary")
    set_languages("c++17")
    add_files("src/main.cpp", "src/android_native_app_glue.c")
    add_syslinks("log")
    add_packages("raylib")
    add_rules("android.native_app", {
        android_sdk_version = "35",
        android_manifest = "android/AndroidManifest.xml",
        android_res = "android/res",
        keystore = "android/debug.jks",
        keystore_pass = "123456",
        package_name = "com.raylib.custom_glue",
        native_app_glue = false, -- Disable default glue
        logcat_filters = {"raydemo_custom_glue", "raylib"}
    })
```

### Parameter Description

* `android_sdk_version`: Set Android SDK version
* `android_manifest`: Set AndroidManifest.xml file path
* `android_res`: Set resource directory
* `keystore`: Set signing keystore file
* `keystore_pass`: Set signing keystore password
* `package_name`: Set package name
* `native_app_glue`: Whether to use the default `android_native_app_glue` library, default is true. If set to false, you need to handle the entry and event loop yourself.
* `logcat_filters`: Set logcat filter keywords

## wdk.env.kmdf

Application of the compilation environment setting of kmdf under WDK, need to cooperate with: `wdk.[driver|binary|static|shared]` and other rules to use.

## wdk.env.umdf

Application of the umdf compiler environment settings under WDK, you need to cooperate with: `wdk.[driver|binary|static|shared]` and other rules to use.

## wdk.env.wdm

Application wdm compiler environment settings under WDK, need to cooperate with: `wdk.[driver|binary|static|shared]` and other rules to use.

## wdk.driver

Compile and generate drivers based on the WDK environment under Windows. Currently, only the WDK10 environment is supported.

Note: need to cooperate: `wdk.env.[umdf|kmdf|wdm]`Environmental rules are used.

```lua
-- add target
target("echo")

    -- add rules
    add_rules("wdk.driver", "wdk.env.kmdf")

    -- add files
    add_files("driver/*.c")
    add_files("driver/*.inx")

    -- add includedirs
    add_includedirs("exe")
```

## wdk.binary

Compile and generate executable programs based on WDK environment under Windows. Currently, only WDK10 environment is supported.

Note: It is necessary to cooperate with: environment rules such as `wdk.env.[umdf|kmdf|wdm]`.

```lua
-- add target
target("app")

    -- add rules
    add_rules("wdk.binary", "wdk.env.umdf")

    -- add files
    add_files("exe/*.cpp")
```

## wdk.static

Compile and generate static library programs based on WDK environment under Windows. Currently, only WDK10 environment is supported.

Note: It is necessary to cooperate with: environment rules such as `wdk.env.[umdf|kmdf|wdm]`.

```lua
target("nonpnp")

    -- add rules
    add_rules("wdk.static", "wdk.env.kmdf")

    -- add flags for rule: wdk.tracewpp
    add_values("wdk.tracewpp.flags", "-func:TraceEvents(LEVEL,FLAGS,MSG,...)", "-func:Hexdump((LEVEL,FLAGS,MSG,...))")

    -- add files
    add_files("driver/*.c", {rules = "wdk.tracewpp"})
```

## wdk.shared

Compile and generate dynamic library programs based on WDK environment under Windows. Currently, only WDK10 environment is supported.

Note: It is necessary to cooperate with: environment rules such as `wdk.env.[umdf|kmdf|wdm]`.

```lua
target("nonpnp")

    -- add rules
    add_rules("wdk.shared", "wdk.env.wdm")

    -- add flags for rule: wdk.tracewpp
    add_values("wdk.tracewpp.flags", "-func:TraceEvents(LEVEL,FLAGS,MSG,...)", "-func:Hexdump((LEVEL,FLAGS,MSG,...))")

    -- add files
    add_files("driver/*.c", {rules = "wdk.tracewpp"})
```

## wdk.tracewpp

Used to enable tracewpp to preprocess source files:

```lua
target("nonpnp")

    -- add rules
    add_rules("wdk.driver", "wdk.env.kmdf")

    -- add flags for rule: wdk.tracewpp
    add_values("wdk.tracewpp.flags", "-func:TraceEvents(LEVEL,FLAGS,MSG,...)", "-func:Hexdump((LEVEL,FLAGS,MSG,...))")

    -- add files
    add_files("driver/*.c", {rules = "wdk.tracewpp"})
    add_files("driver/*.rc")
```

For more information on WDK rules, see: [#159](https://github.com/xmake-io/xmake/issues/159)

## win.sdk.application

Compile and generate the winsdk application.

```lua
-- add rules
add_rules("mode.debug", "mode.release")

-- define target
target("usbview")

    -- windows application
    add_rules("win.sdk.application")

    -- add files
    add_files("*.c", "*.rc")
    add_files("xmlhelper.cpp", {rules = "win.sdk.dotnet"})
```

## wdk.sdk.dotnet

Used to specify certain c++ source files to be compiled as c++.net.

```lua
add_files("xmlhelper.cpp", {rules = "win.sdk.dotnet"})
```

For more information on WDK rules, see: [#159](https://github.com/xmake-io/xmake/issues/159)

## plugin.vsxmake.autoupdate

Automatically update the VS project file (when each build is completed) in the VS project generated by `xmake project -k vsxmake`.

```lua
add_rules("plugin.vsxmake.autoupdate")
target("test")
     set_kind("binary")
     add_files("src/*.c")
```

## plugin.compile\_commands.autoupdate

Automatically update the `compile_commands.json` file, commonly used with language servers like clangd:

```lua
add_rules("plugin.compile_commands.autoupdate")

target("test")
    set_kind("binary")
    add_files("src/*.c")
```

And if needed, set a custom output directory:

```lua
add_rules("plugin.compile_commands.autoupdate", {outputdir = ".vscode"})

target("test")
    set_kind("binary")
    add_files("src/*.c")
```

## utils.symbols.export\_all

Provided in v2.5.2 and above, we can use it to automatically export all dynamic library symbols. Currently, only the symbol export of windows dll target programs is supported, even if there is no export interface through `__declspec(dllexport)` in the code.
xmake will also automatically export all c/c++ interface symbols.

```lua
add_rules("mode.release", "mode.debug")

target("foo")
     set_kind("shared")
     add_files("src/foo.c")
     add_rules("utils.symbols.export_all")

target("test")
     set_kind("binary")
     add_deps("foo")
     add_files("src/main.c")
```

c++

```lua
add_rules("utils.symbols.export_all", {export_classes = true})
```

Versions from 2.9.5 onwards also support custom filters to filter the symbol names and source file names that need to be exported:

```lua
target("bar")
    set_kind("shared")
    add_files("src/bar.cpp")
    add_rules("utils.symbols.export_all", {export_filter = function (symbol, opt)
        local filepath = opt.sourcefile or opt.objectfile
        if filepath and filepath:find("bar.cpp", 1, true) and symbol:find("add", 1, true) then
            print("export: %s at %s", symbol, filepath)
            return true
        end
    end})
```

Related issue [#1123](https://github.com/xmake-io/xmake/issues/1123)

## utils.symbols.export\_list

We can define the list of exported symbols directly in xmake.lua, for example:

```lua
target("foo")
     set_kind("shared")
     add_files("src/foo.c")
     add_rules("utils.symbols.export_list", {symbols = {
         "add",
         "sub"}})
```

Alternatively, add a list of exported symbols in the `*.export.txt` file.

```lua
target("foo2")
     set_kind("shared")
     add_files("src/foo.c")
     add_files("src/foo.export.txt")
     add_rules("utils.symbols.export_list")
```

For a complete project example, see: [Export Symbol Example](https://github.com/xmake-io/xmake/tree/dev/tests/projects/c/shared_library_export_list)

## utils.install.cmake\_importfiles

We can use this rule to export the .cmake file when installing the target library file for the library import and search of other cmake projects.

## utils.install.pkgconfig\_importfiles

We can use this rule to export the pkgconfig/.pc file when installing the target target library file for library import and search for other projects.

## utils.bin2c

This rule can be used in versions above v2.5.7 to introduce some binary files into the project, and see them as c/c++ header files for developers to use to obtain the data of these files.

For example, we can embed some png/jpg resource files into the code in the project.

```lua
target("console")
    set_kind("binary")
    add_rules("utils.bin2c", {extensions = {".png", ".jpg"}})
    add_files("src/*.c")
    add_files("res/*.png", "res/*.jpg")
```

::: tip NOTE
The setting of extensions is optional, the default extension is .bin
:::

Then, we can import and use it through `#include "filename.png.h"`, xmake will automatically generate the corresponding header file for you, and add the corresponding search directory.

```c
static unsigned char g_png_data[] = {
    #include "image.png.h"
};

int main(int argc, char** argv) {
    printf("image.png: %s, size: %d\n", g_png_data, sizeof(g_png_data));
    return 0;
}
```

The content of the generated header file is similar:

```sh
cat build/.gens/test/macosx/x86_64/release/rules/c++/bin2c/image.png.h
  0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x78, 0x6D, 0x61, 0x6B, 0x65, 0x21, 0x0A, 0x00
```

:::tip TIP
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&#x20;

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.

Compared to `utils.bin2c`, it generates object files directly, skipping the generation of C header files, so it is faster when dealing with large files.

For example, embedding a 120MB file:

* `utils.bin2c`: 354s
* `utils.bin2obj`: 1.8s

### Usage

```lua
target("myapp")
    set_kind("binary")
    add_rules("utils.bin2obj", {extensions = {".bin", ".ico"}})
    add_files("src/*.c")
    -- Embed data.bin and ensure it is zero-terminated
    add_files("assets/data.bin", {zeroend = true})
```

### 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.

```c
#include <stdio.h>
#include <stdint.h>

extern const uint8_t _binary_data_bin_start[];
extern const uint8_t _binary_data_bin_end[];

int main() {
    // Calculate size
    const uint32_t size = (uint32_t)(_binary_data_bin_end - _binary_data_bin_start);
    
    // Access data
    printf("Data size: %u bytes\n", size);
    for (uint32_t i = 0; i < size; i++) {
        printf("%02x ", _binary_data_bin_start[i]);
    }
    return 0;
}
```

### Transform&#x20;

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

The per-file config takes precedence over the per-rule one, so a rule-scoped transform can still be overridden for a specific file.

::: 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
* The transform receives an extra `opt` table as its last argument, `opt.target` is the target instance being built
* The transformed file is written under the target's auto-generated directory and tracked by the dependency system, so it is only re-run when the source file actually changes
* Under the hood this is implemented with [batchcmds:call](custom-rule.md#batchcmds-call), which is also available in your own rules
  :::

## utils.replace&#x20;

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.

The rule uses dependency tracking, so the substitution is only re-run when the source file or the replace list actually changes.

### Lua-pattern replacement (default)

```lua
target("foo")
    set_kind("binary")
    add_files("src/foo.c", {rules = "utils.replace", replaces = {
        {"old_pattern", "new_text"},
    }})
```

### Plain-text replacement

When `replace_plain = true` is passed, the patterns are treated as literal text instead of Lua patterns.

```lua
target("foo")
    set_kind("binary")
    add_files("src/foo.c", {rules = "utils.replace",
        replaces = {{"old text", "new text"}},
        replace_plain = true})
```

### Function-based transform

`replaces` also accepts an arbitrary function that takes the file content and returns the rewritten content.

```lua
target("foo")
    set_kind("binary")
    add_files("src/foo.c", {rules = "utils.replace", replaces = function (content)
        content = content:gsub("old", "new")
        return content
    end})
```

This rule is what xmake itself uses internally to patch the bundled Lua 5.5 `lparser.c`, so that writing to the for-in control variable is still allowed under the new runtime.

## utils.glsl2spv

This rule can be used in v2.6.1 and above. Import glsl shader files such as `*.vert/*.frag` into the project, and then realize automatic compilation to generate `*.spv` files.

In addition, we also support binary embedding spv file data in the form of C/C++ header file, which is convenient for program use.

### Compile and generate spv file

xmake will automatically call glslangValidator or glslc to compile shaders to generate .spv files, and then output them to the specified `{outputdir = "build"}` directory.

```lua
add_rules("mode.debug", "mode.release")

add_requires("glslang", {configs = {binaryonly = true}})

target("test")
    set_kind("binary")
    add_rules("utils.glsl2spv", {outputdir = "build"})
    add_files("src/*.c")
    add_files("src/*.vert", "src/*.frag")
    add_packages("glslang")
```

Note that the `add_packages("glslang")` here is mainly used to import and bind the glslangValidator in the glslang package to ensure that xmake can always use it.

Of course, if you have already installed it on your own system, you don’t need to bind this package additionally, but I still recommend adding it.

### Compile and generate c/c++ header files

We can also use the bin2c module internally to generate the corresponding binary header file from the compiled spv file, which is convenient for direct import in user code. We only need to enable `{bin2c = true}`. :w

```lua
add_rules("mode.debug", "mode.release")

add_requires("glslang", {configs = {binaryonly = true}})

target("test")
    set_kind("binary")
    add_rules("utils.glsl2spv", {bin2c = true})
    add_files("src/*.c")
    add_files("src/*.vert", "src/*.frag")
    add_packages("glslang")
```

Then we can introduce in the code like this:

```c
static unsigned char g_test_vert_spv_data[] = {
    #include "test.vert.spv.h"
};

static unsigned char g_test_frag_spv_data[] = {
    #include "test.frag.spv.h"
};
```

Similar to the usage of bin2c rules, see the complete example: [glsl2spv example](https://github.com/xmake-io/xmake/tree/master/tests/projects/other/glsl2spv)

## utils.hlsl2spv

In addition to the `utils.glsl2spv` rule, we now support the `utils.hlsl2spv` rule.

```lua
add_rules("mode.debug", "mode.release")

add_requires("directxshadercompiler")

target("test")
    set_kind("binary")
    add_rules("utils.hlsl2spv", {bin2c = true})
    add_files("src/*.c")
    add_files("src/*.hlsl")
    add_packages("directxshadercompiler")
```

## python.library

We can use this rule to generate python library modules with pybind11, which will adjust the module name of the python library.

```lua
add_rules("mode.release", "mode.debug")
add_requires("pybind11")

target("example")
     add_rules("python.library")
     add_files("src/*.cpp")
     add_packages("pybind11")
     set_languages("c++11")
```

with soabi:

```lua
add_rules("mode.release", "mode.debug")
add_requires("pybind11")

target("example")
     add_rules("python.library", {soabi = true})
     add_files("src/*.cpp")
     add_packages("pybind11")
     set_languages("c++11")
```

## nodejs.module

Build nodejs module.

```lua
add_requires("node-addon-api")

target("foo")
    set_languages("cxx17")
    add_rules("nodejs.module")
    add_packages("node-addon-api")
    add_files("*.cc")
end
```

## utils.ipsc

The ipsc compiler rules are supported and are used as follows.

```lua
target("test")
    set_kind("binary")
    add_rules("utils.ispc", {header_extension = "_ispc.h"})
    set_values("ispc.flags", "--target=host")
    add_files("src/*.ispc")
    add_files("src/*.cpp")
```
