IDLize 工具使用者指南
本指南面向把 IDLize 用作 ArkUI 代码生成工具的开发者。读完后,应能够:
- 运行标准生成流程。
- 判断输入声明、IDL 中间产物和生成代码分别位于哪里。
- 添加手写 IDL 或扩展现有接口。
- 修改接口参数后验证 ArkTS 和 C++ 侧生成结果。
完整 IDL 语言语法请参见 IDL_SPEC.md。命令参数请参见 CLI_REFERENCE.md。
1. 使用前提
从仓库根目录准备环境:
npm i --no-save /path/to/ace_ets2bundle/libarkts.tgz
cd runner
npm run compile
cd ..
npm run download:sdk
libarkts 压缩包应使用 ace_ets2bundle 的产物;公共 npm 依赖继续使用仓库已配置的
registry。
以上命令完成后即可运行标准生成流程。更完整的开发环境和发布说明请参见 开发者指南。
2. 运行标准生成流程
在仓库根目录执行:
bash generate.sh
generate.sh 调用 runner m3,使用 sdk-patched-arkts/ 作为已准备的 SDK,
并把 interfaces/interfaces/arkui-extra/ 作为额外 IDL 输入。标准生成会安装
全部目标:
out/
sig/ # ArkTS / TypeScript peer 和组件类
libace/ # C++ modifier、serializer 和 native module 胶水代码
中间产物位于 runner/out/:
| 路径 | 用途 |
|---|---|
runner/out/idl/ |
etsgen 从 .d.ts / .d.ets 转换出的 .idl。 |
runner/out/peers/sig/ |
arkgen 生成的 ArkTS / TypeScript peer 中间输出。 |
runner/out/peers/libace/ |
arkgen 生成的 C++ 中间输出。 |
runner/out/patched-sdk-arkts/ |
已准备的 ArkTS SDK 声明。 |
runner/out/patched-sdk-ts/ |
已准备的 TypeScript SDK 声明。 |
runner/out/scraper/ |
scraper 阶段处理后的 IDL 输入。 |
这些目录是生成产物,不要手工修改。需要修正输入时,应修改手写 IDL、SDK patch
或生成配置,然后重新运行 bash generate.sh。
3. 判断生成结果是否正确
当生成代码缺少组件、方法或属性,或参数类型、可选标记、返回类型不符合预期时, 按产物链路反向检查:
- 查看
out/sig/或out/libace/,确认安装后的文件是否缺失或内容不对。 - 查看
runner/out/peers/sig/或runner/out/peers/libace/,确认 printer 实际输出。 - 查看
runner/out/idl/,确认 parser 实际接收到的 IDL。 - 如果 IDL 已经错误,继续检查
runner/out/patched-sdk-arkts/、runner/out/patched-sdk-ts/和输入 patch。 - 如果 IDL 正确但 peer 输出错误,检查
arkgen/generation-config/config.json和相关生成器。
常用检查命令:
rg -n "MyButton" out runner/out/peers runner/out/idl
rg -n "borderWidth" out/sig runner/out/peers/sig
rg -n "setData" out/libace runner/out/peers/libace
4. 添加手写 IDL 组件
4.1 编写 IDL 文件
下面示例定义一个 MyButton 组件:
package arkui.component.mybutton;
import arkui.component.units;
import arkui.component.common;
callback MyButtonClickCallback = void (i32 clickCount);
[Component]
interface MyButton {
constructor();
attribute String label;
attribute ResourceColor backgroundColor;
attribute Length width;
attribute Length height;
attribute boolean enabled;
MyButton onClick(MyButtonClickCallback callback);
MyButton fontSize(Length size);
MyButton borderRadius(Length radius);
};
[ComponentInterface]
interface MyButtonAttribute {
MyButtonAttribute label(String value);
MyButtonAttribute backgroundColor(ResourceColor color);
MyButtonAttribute onClick(MyButtonClickCallback callback);
MyButtonAttribute fontSize(Length size);
MyButtonAttribute borderRadius(Length radius);
MyButtonAttribute enabled(boolean value);
};
要点:
package决定接口的命名空间。import引入外部 IDL 包中的类型。[Component]标记 ArkUI 组件接口。[ComponentInterface]标记属性 setter 接口。- setter 通常返回组件或属性接口类型,以支持链式调用。
4.2 放置 IDL 文件
推荐把手写 IDL 放在标准额外输入目录:
interfaces/interfaces/arkui-extra/mybutton.idl
如果使用自定义目录,可以直接调用 runner m3,通过 <idl-files...> 位置参数传入。
4.3 配置生成
组件是否完整生成主要由 arkgen/generation-config/config.json 控制。新组件通常会被
materialized;如果需要强制完整生成,可将完全限定名加入 forceMaterialized:
{
"forceMaterialized": [
"arkui.component.mybutton.MyButton",
"arkui.component.mybutton.MyButtonAttribute"
]
}
完全限定名格式为 <package>.<InterfaceName>。如果组件在 ignoreMaterialized 中,
只会生成最小 stub。
4.4 重新生成并验证
bash generate.sh
find out/sig -name "*MyButton*"
find out/libace -name "*MyButton*"
常见命名约定:
| 生成产物 | 命名模式 |
|---|---|
| Peer 类 | Ark<Component>Peer,例如 ArkMyButtonPeer。 |
| Component 类 | Ark<Component>Component,例如 ArkMyButtonComponent。 |
| C++ Modifier | <Component>Modifier,例如 MyButtonModifier。 |
| Materialized 接口实现 | <Name>Internal,例如 MyButtonInternal。 |
| Native module 调用 | ArkUIGeneratedNativeModule._<method>。 |
5. 扩展现有组件接口
5.1 先确定输入来源
不要修改 runner/out/idl/ 或 out/。这些目录会在每次生成时被覆盖。
| 来源 | 应修改的位置 |
|---|---|
| 手写或补充 IDL | interfaces/interfaces/arkui-extra/ 或传给 runner m3 的自定义 IDL 路径。 |
| 上游 ArkTS SDK 声明 | sdk-patched-arkts/。 |
| 上游 TypeScript SDK 声明 | sdk-patched/。 |
| 生成配置 | arkgen/generation-config/config.json。 |
可以用以下命令定位手写 IDL:
rg -n "ExistingComponent" interfaces/interfaces
5.2 添加属性或方法
在组件接口和属性接口中补充对应声明:
package arkui.component.existing;
import arkui.component.common;
import arkui.component.units;
[Component]
interface ExistingComponent {
attribute String tooltip;
ExistingComponent shadow(number radius, number offsetX, number offsetY, ResourceColor color);
ExistingComponent animation(optional Duration duration);
};
[ComponentInterface]
interface ExistingComponentAttribute {
ExistingComponentAttribute tooltip(String value);
ExistingComponentAttribute shadow(number radius, number offsetX, number offsetY, ResourceColor color);
};
重新生成:
bash generate.sh
生成方法名通常与 IDL 方法名一致,首字母不会自动转换大小写。
6. 修改现有接口参数
常见变更示例:
interface ExistingComponent {
ExistingComponent borderWidth(Length width, optional ResourceColor color);
void setData(sequence<String> data);
ExistingComponent padding(Length value);
ExistingComponent padding(record<String, Length> edges);
};
兼容性判断:
- 添加可选参数通常向后兼容。
- 新增重载通常向后兼容。
- 修改参数类型是破坏性变更。
- 删除参数或方法是破坏性变更;应先使用
[Deprecated]标记旧 API。
interface ExistingComponent {
[Deprecated]
ExistingComponent oldMethod(String param);
ExistingComponent newMethod(String param, optional i32 flags);
};
验证时同时检查 ArkTS 和 C++ 侧:
bash generate.sh
rg -n "borderWidth" out/sig runner/out/peers/sig
rg -n "setData" out/libace runner/out/peers/libace
确认以下内容:
- ArkTS peer 方法签名已更新。
- C++ modifier 接受新的参数类型。
- Serializer 对新参数类型的编码符合预期。
7. 直接调用 runner m3
标准脚本等价于以下调用:
node runner m3 sdk-patched-arkts ./interfaces/interfaces/arkui-extra/ \
--sdk-stage prepared \
--arkgen-options-file ./arkgen/generation-config/config.json \
--etsgen-options-file ./etsgen/generator-config.json \
--arkgen-interop-types ./runner/interop-types/src/cpp/interop-types.h \
--scraper-options-file ./runner/configs/scraper-config.json \
--arkgen "node arkgen" \
--etsgen "node etsgen" \
--target all \
--no-arkgen-dummy-impl \
--output "./out"
关键参数:
| 参数 | 用途 |
|---|---|
--sdk-stage prepared |
从已准备的 SDK 开始。只使用 IDL 输入时可改为 idl。 |
--arkgen-options-file |
ArkUI 生成配置。 |
--etsgen-options-file |
.d.ts / .d.ets 到 IDL 的转换配置;idl 阶段不需要。 |
--arkgen-interop-types |
ArkTS/C++ 共享 interop 类型头文件。 |
--scraper-options-file |
scraper 处理范围配置。 |
--target |
sig、libace 或 all。 |
--output |
安装后的输出目录。 |
8. IDL 快速参考
包和导入
package arkui.component.mycomponent;
import arkui.component.common;
import arkui.component.units.Length as Length;
接口、属性和方法
interface MyService {
constructor(String name, optional i32 timeout);
attribute String name;
readonly attribute i32 id;
[Optional] attribute String description;
void start();
boolean isRunning();
String getStatus(optional boolean verbose);
static MyService createDefault();
};
如果带 [Entity=Class] 的接口需要作为 peer 或包含方法,应避免普通属性,或使用
[Accessor=Getter] / [Accessor=Setter] 组合:
[Entity=Class]
interface MyService {
[Accessor=Getter]
attribute String name;
[Accessor=Setter]
attribute String name;
void start();
};
回调
callback OnChangeCallback = void (String newValue, i32 changeId);
interface MyComponent {
attribute OnChangeCallback onChange;
void setOnChange(OnChangeCallback callback);
};
联合、序列和记录
void setSize((number or String or Length) value);
void setColor(optional (ResourceColor or undefined) color);
void setItems(sequence<String> items);
void setMetadata(record<String, boolean> meta);
常用扩展属性
| 扩展属性 | 用法 | 说明 |
|---|---|---|
[Component] |
接口 | 标记 ArkUI 组件。 |
[ComponentInterface] |
接口 | 标记组件属性 setter 接口。 |
[Entity=Class] |
接口 | 生成带指针支持的类形态。 |
[Entity=Interface] |
接口 | 生成接口形态。 |
[Optional] |
属性 | 属性可以省略。 |
[Deprecated] |
任意声明 | 标记 API 已弃用。 |
[Throws] |
方法 | 方法可能抛出异常。 |
[Accessor=Getter] / [Accessor=Setter] |
属性 | 属性为访问器。 |
[Documentation="..."] |
任意声明 | 内联文档。 |
[DtsName="original"] |
任意声明 | 保留原始声明名称。 |
9. 位置速查
| 内容 | 位置 |
|---|---|
| 手写 IDL | interfaces/interfaces/arkui-extra/。 |
| SDK ArkTS patch | sdk-patched-arkts/。 |
| SDK TypeScript patch | sdk-patched/。 |
| 生成配置 | arkgen/generation-config/config.json。 |
| Scraper 配置 | runner/configs/scraper-config.json。 |
| Etsgen 配置 | etsgen/generator-config.json。 |
| 输出目录常量 | runner/src/shared.ts。 |