Skip to content

Commit 546288f

Browse files
committed
update docs
1 parent 8c826f3 commit 546288f

File tree

2 files changed

+147
-17
lines changed

2 files changed

+147
-17
lines changed

docs/examples/cpp/autogen.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# Automatic Code Generation {#autogen}
2+
3+
In many cases, we need to preprocess and automatically generate code before compilation, and then include the generated code in the subsequent build process.
4+
5+
As Xmake continues to evolve, its support for code generation features is also being updated and improved. Currently, the following approaches are supported:
6+
7+
## The Simplest Approach
8+
9+
This is the most straightforward method: simply generate the code before building and forcibly add it using `add_files`.
10+
11+
By default, `add_files` will not add files that do not exist, so you need to set `always_added = true` to force the addition, even if the file does not exist yet.
12+
13+
```lua
14+
add_rules("mode.debug", "mode.release")
15+
16+
target("test")
17+
set_kind("binary")
18+
add_files("$(builddir)/autogen.cpp", {always_added = true})
19+
before_build(function (target)
20+
io.writefile("$(builddir)/autogen.cpp", [[
21+
#include <iostream>
22+
using namespace std;
23+
int main(int argc, char** argv) {
24+
cout << "hello world!" << endl;
25+
return 0;
26+
}
27+
]])
28+
end)
29+
```
30+
31+
This approach has many limitations and is not commonly used in real-world scenarios, but it is simple and easy to understand.
32+
33+
## Generation via Dependent Target
34+
35+
Sometimes, code generation requires running a target program within the project. This can be achieved as follows:
36+
37+
```lua
38+
add_rules("mode.debug", "mode.release")
39+
40+
rule("autogen")
41+
set_extensions(".in")
42+
before_buildcmd_file(function (target, batchcmds, sourcefile, opt)
43+
local sourcefile_cx = path.join(target:autogendir(), "rules", "autogen", path.basename(sourcefile) .. ".cpp")
44+
local objectfile = target:objectfile(sourcefile_cx)
45+
table.insert(target:objectfiles(), objectfile)
46+
47+
batchcmds:show_progress(opt.progress, "${color.build.object}compiling.autogen %s", sourcefile)
48+
batchcmds:mkdir(path.directory(sourcefile_cx))
49+
batchcmds:vrunv(target:dep("autogen"):targetfile(), {sourcefile, sourcefile_cx})
50+
batchcmds:compile(sourcefile_cx, objectfile)
51+
52+
batchcmds:add_depfiles(sourcefile, target:dep("autogen"):targetfile())
53+
batchcmds:set_depmtime(os.mtime(objectfile))
54+
batchcmds:set_depcache(target:dependfile(objectfile))
55+
end)
56+
57+
target("autogen")
58+
set_default(false)
59+
set_kind("binary")
60+
set_plat(os.host()) -- Build for the host platform
61+
set_arch(os.arch())
62+
add_files("src/autogen.cpp")
63+
set_languages("c++11")
64+
set_policy("build.fence", true) -- Disable parallel compilation between source files
65+
66+
target("test")
67+
set_kind("binary")
68+
add_deps("autogen")
69+
add_rules("autogen")
70+
add_files("src/main.cpp")
71+
add_files("src/*.in")
72+
```
73+
74+
First, configure an `autogen` target program that must be runnable on the current build platform, so use `set_plat(os.host())` to force building for the host platform.
75+
76+
Also, set the `build.fence` policy to disable parallel compilation between source files, ensuring the `autogen` target is built first and its executable is available in advance.
77+
78+
Then, define a custom rule to invoke the `autogen` target program before building, generate the source code, and compile the generated code into object files for linking.
79+
80+
See the full example: [autogen_codedep](https://github.com/xmake-io/xmake/blob/dev/tests/projects/other/autogen/autogen_codedep/xmake.lua)
81+
82+
## Generation via Native Module
83+
84+
Xmake introduces native module development, allowing code generation via native modules without defining an extra `autogen` target program.
85+
86+
For details on native module development, see: [Native Module Development](/api/scripts/native-modules).
87+
88+
```lua
89+
add_rules("mode.debug", "mode.release")
90+
91+
add_moduledirs("modules")
92+
93+
rule("autogen")
94+
set_extensions(".in")
95+
before_build_file(function (target, sourcefile, opt)
96+
import("utils.progress")
97+
import("core.project.depend")
98+
import("core.tool.compiler")
99+
import("autogen.foo", {always_build = true})
100+
101+
local sourcefile_cx = path.join(target:autogendir(), "rules", "autogen", path.basename(sourcefile) .. ".cpp")
102+
local objectfile = target:objectfile(sourcefile_cx)
103+
table.insert(target:objectfiles(), objectfile)
104+
105+
depend.on_changed(function ()
106+
progress.show(opt.progress, "${color.build.object}compiling.autogen %s", sourcefile)
107+
os.mkdir(path.directory(sourcefile_cx))
108+
foo.generate(sourcefile, sourcefile_cx)
109+
compiler.compile(sourcefile_cx, objectfile, {target = target})
110+
end, {dependfile = target:dependfile(objectfile),
111+
files = sourcefile,
112+
changed = target:is_rebuilt()})
113+
end)
114+
115+
target("test")
116+
set_kind("binary")
117+
add_rules("autogen")
118+
add_files("src/main.cpp")
119+
add_files("src/*.in")
120+
```
121+
122+
See the full example: [Native Module Autogen](https://github.com/xmake-io/xmake/blob/dev/tests/projects/other/autogen/autogen_shared_module/xmake.lua).
123+
124+
## Generation in the Prepare Phase
125+
126+
Since Xmake 3.x, the `on_prepare` and `on_prepare_files` interfaces have been introduced to enable two-phase builds. The Prepare phase can be used specifically for source code generation and preprocessing.
127+
128+
The Prepare phase is executed before all `on_build` and `on_build_files` interfaces.
129+
130+
For details, see: [Prepare Interface Manual](/api/description/project-target.html#on-prepare).

docs/zh/examples/cpp/autogen.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# 自动代码生成 {#autogen}
22

3-
很多时候,我们需要在编译之前对代码做一些预处理和自动生成,然后将生成的代码参与到后续的编译中去
3+
在许多情况下,我们需要在编译之前对代码进行预处理和自动生成,然后将生成的代码参与到后续的编译流程中
44

5-
而随着 Xmake 的不断迭代,对代码生成特性的支持也在不断更新和改进。目前支持以下几种方式。
5+
随着 Xmake 的不断迭代,对代码生成特性的支持也在持续更新和改进。目前主要支持以下几种方式:
66

77
## 最简单的方式
88

9-
这种方式最为简单直接,只需要在构建之前生成代码后,强制通过 `add_files` 添加进来
9+
这种方式最为简单直接,只需在构建之前生成代码,并通过 `add_files` 强制添加进来
1010

11-
由于 add_files 默认不会添加不存在的文件,所以需要配置 `always_added = true` 去强制添加,即使文件当前还不存在
11+
由于 `add_files` 默认不会添加不存在的文件,所以需要配置 `always_added = true`,即使文件当前还不存在也能强制添加
1212

1313
```lua
1414
add_rules("mode.debug", "mode.release")
@@ -28,11 +28,11 @@ int main(int argc, char** argv) {
2828
end)
2929
```
3030

31-
这种方式有很多的局限,很多场景下不太使用,但胜在比较简单
31+
这种方式有很多局限性,实际场景下不常用,但胜在简单易懂
3232

3333
## 依赖目标生成
3434

35-
有时候,我们生成代码,需要通过执行项目中某个目标程序来完成,这个时候我们需要通过下面的方式来实现。
35+
有时我们需要通过执行项目中的某个目标程序来生成代码,可以通过如下方式实现:
3636

3737
```lua
3838
add_rules("mode.debug", "mode.release")
@@ -57,11 +57,11 @@ rule("autogen")
5757
target("autogen")
5858
set_default(false)
5959
set_kind("binary")
60-
set_plat(os.host()) ----- 生成当前主机平台程序
60+
set_plat(os.host()) -- 生成当前主机平台程序
6161
set_arch(os.arch())
6262
add_files("src/autogen.cpp")
6363
set_languages("c++11")
64-
set_policy("build.fence", true) ----- 禁用源码间并行编译
64+
set_policy("build.fence", true) -- 禁用源码间并行编译
6565

6666
target("test")
6767
set_kind("binary")
@@ -71,19 +71,19 @@ target("test")
7171
add_files("src/*.in")
7272
```
7373

74-
我们需要先配置一个 autogen 的目标程序,它是一个可以在当前编译平台能够运行的程序,因此需要配置 `set_plat(os.host())` 强制作为主机平台来编译
74+
首先需要配置一个 autogen 目标程序,它必须能在当前编译平台运行,因此需通过 `set_plat(os.host())` 强制为主机平台编译
7575

76-
另外,我们需要配置 `build.fence` 策略,禁用源码间并行编译, autogen 目标的源码总是优先编译完成,提前完成 autogen 可执行程序的生成
76+
另外,需要配置 `build.fence` 策略,禁用源码间并行编译,确保 autogen 目标源码优先编译,提前生成 autogen 可执行程序
7777

78-
然后,我们配置一个自定义规则,在构建之前,去调用 autogen 目标程序去生成源码,并直接将生成的源码编译出对象文件,插入到后续的链接中去
78+
然后,配置自定义规则,在构建前调用 autogen 目标程序生成源码,并直接将生成的源码编译为对象文件,插入到后续链接流程中
7979

8080
完整例子见:[autogen_codedep](https://github.com/xmake-io/xmake/blob/dev/tests/projects/other/autogen/autogen_codedep/xmake.lua)
8181

82-
## 通过原生模块来生成
82+
## 通过原生模块生成
8383

84-
我们新增了原生模块开发的特性,通过这个特性,即使不通过定义额外的 autogen 目标程序,也可以通过原生模块来生成代码
84+
Xmake 新增了原生模块开发特性,即使不定义额外的 autogen 目标程序,也可以通过原生模块生成代码
8585

86-
关于原生模块的开发,可以参考文档[Native 模块开发](/zh/api/scripts/native-modules)
86+
关于原生模块开发,可参考文档[Native 模块开发](/zh/api/scripts/native-modules)
8787

8888
```lua
8989
add_rules("mode.debug", "mode.release")
@@ -123,8 +123,8 @@ target("test")
123123

124124
## Prepare 阶段生成
125125

126-
Xmake 3.x 之后,我们新增了 `on_prepare``on_prepare_files` 接口,实现两阶段编译在 Prepare 阶段,我们可以专门用于处理源码生成和预处理
126+
Xmake 3.x 之后,新增了 `on_prepare``on_prepare_files` 接口,实现两阶段编译在 Prepare 阶段,可专门处理源码生成和预处理
127127

128-
它会在所有的 `on_build``on_build_files` 接口之前被执行
128+
它会在所有 `on_build``on_build_files` 接口之前执行
129129

130-
关于 Prepare 的相关接口说明,见文档[Prepare 接口手册](/zh/api/description/project-target.html#on-prepare)
130+
相关接口说明见文档[Prepare 接口手册](/zh/api/description/project-target.html#on-prepare)

0 commit comments

Comments
 (0)