import argparse
import os
import sys
import shutil
import subprocess
STATIC_SUBDIRS = ["api", "kits", "arkts"]
def copy_subdirs(source_base, subdirs, output_path):
"""从源目录拷贝指定子目录到输出路径
Args:
source_base (str): 源目录根路径
subdirs (list[str]): 需要拷贝的子目录名列表
output_path (str): 输出目录根路径
Returns:
None
"""
for subdir in subdirs:
src = os.path.join(source_base, subdir)
dst = os.path.join(output_path, subdir)
if not os.path.exists(src):
print(f"[copy_runtimeapi] WARNING: source subdir does not exist: {src}, skipping")
continue
if os.path.exists(dst):
shutil.rmtree(dst)
shutil.copytree(src, dst)
def run_unpublished_tool(nodejs, unpublished_tool, input_dir, output_dir, mode, sdk_path):
"""调用 delete_unpublished_plugin.js 执行 @unpublished 标签处理
Args:
nodejs (str): Node.js 可执行文件路径
unpublished_tool (str): delete_unpublished_plugin.js 文件路径
input_dir (str): 输入目录路径
output_dir (str): 输出目录路径
mode (str): 处理模式,"tag-only" 或 "tag-and-api"
sdk_path (str): SDK build-tools 路径,用于 libarkts 库解析
Returns:
None
"""
tool = os.path.abspath(unpublished_tool)
nodejs = os.path.abspath(nodejs)
input_dir = os.path.abspath(input_dir)
output_dir = os.path.abspath(output_dir)
sdk_path = os.path.abspath(sdk_path)
if not os.path.exists(input_dir):
print(f"[copy_runtimeapi] WARNING: dir does not exist: {input_dir}, skipping unpublished processing")
return
env = os.environ.copy()
ets2panda_lib = os.path.join(sdk_path, "build-tools", "ets2panda", "lib")
if os.path.isdir(ets2panda_lib):
env["LD_LIBRARY_PATH"] = ets2panda_lib + os.pathsep + env.get("LD_LIBRARY_PATH", "")
print(f"[copy_runtimeapi] LD_LIBRARY_PATH set to: {ets2panda_lib}")
else:
print(f"[copy_runtimeapi] WARNING: ets2panda lib dir not found: {ets2panda_lib}")
print(f"[copy_runtimeapi] running delete_unpublished_plugin.js --mode {mode} on {input_dir}")
p = subprocess.Popen([nodejs, tool, "--input", input_dir, "--output", output_dir, "--mode", mode, "--sdk-path", sdk_path, "--subdirs", "api,kits,arkts"], stdout=subprocess.PIPE, env=env)
p.wait()
def main():
"""主函数:解析命令行参数,执行 runtimeapi 拷贝和 @unpublished 处理。
执行流程:
1. 从原始 static SDK 拷贝到 output-path(保留 @unpublished 标签,供 tag-and-api 使用)
2. 对 static SDK 执行 tag-only(仅删标签,保留 API,暴露给其他部件)
3. 从 tag-only 后的 static SDK 拷贝到 runtimeapi-path(供 ets-loader/runtimeapi)
4. 对 output-path 执行 tag-and-api(删标签+API,供 ets/static/api、arkts、kits)
Returns:
int: 退出码
"""
parser = argparse.ArgumentParser()
parser.add_argument('--static-sdk-path', required=True, help='path to static SDK output')
parser.add_argument('--output-path', required=True, help='path to tag-and-api output directory (for ets/static/api,arkts,kits)')
parser.add_argument('--runtimeapi-path', required=True, help='path to tag-only output directory (for ets-loader/runtimeapi)')
parser.add_argument('--node-js', required=True, help='path to nodejs executable')
parser.add_argument('--unpublished-tool', required=True, help='path to delete_unpublished_plugin.js')
parser.add_argument('--sdk-path', required=True, help='SDK build tools path for libarkts resolution')
options = parser.parse_args()
static_sdk_path = os.path.abspath(options.static_sdk_path)
output_path = os.path.abspath(options.output_path)
runtimeapi_path = os.path.abspath(options.runtimeapi_path)
sdk_path = os.path.abspath(options.sdk_path)
if not os.path.exists(static_sdk_path):
print(f"ERROR: static SDK path does not exist: {static_sdk_path}")
sys.exit(1)
if os.path.exists(output_path):
shutil.rmtree(output_path)
os.makedirs(output_path, exist_ok=True)
print(f"[copy_runtimeapi] copying original static SDK to output-path: {output_path}")
copy_subdirs(static_sdk_path, STATIC_SUBDIRS, output_path)
if os.path.exists(runtimeapi_path):
shutil.rmtree(runtimeapi_path)
os.makedirs(runtimeapi_path, exist_ok=True)
print(f"[copy_runtimeapi] copying result to runtimeapi-path: {runtimeapi_path}")
copy_subdirs(static_sdk_path, STATIC_SUBDIRS, runtimeapi_path)
print(f"[copy_runtimeapi] processing output @unpublished tag-and-api on {output_path}")
run_unpublished_tool(options.node_js, options.unpublished_tool, output_path, output_path, "tag-and-api", sdk_path)
if __name__ == '__main__':
sys.exit(main())