437 lines
14 KiB
PowerShell
437 lines
14 KiB
PowerShell
|
||
# build.ps1 - 智能 WASM 构建脚本
|
||
param(
|
||
[switch]$Clean,
|
||
[switch]$Serve,
|
||
[switch]$Test,
|
||
[string]$BuildType = "Release"
|
||
)
|
||
|
||
Write-Host "=========================================" -ForegroundColor Cyan
|
||
Write-Host " 智能 JSON-WASM 项目构建系统 " -ForegroundColor Cyan
|
||
Write-Host "=========================================" -ForegroundColor Cyan
|
||
Write-Host ""
|
||
|
||
# 1. 设置环境变量
|
||
$emsdkCandidates = @()
|
||
|
||
if ($env:EMSDK) {
|
||
$emsdkCandidates += $env:EMSDK
|
||
}
|
||
|
||
$emsdkCandidates += "E:\emsdk"
|
||
$emsdkCandidates += (Join-Path (Split-Path $PSScriptRoot -Parent) "..\emsdk")
|
||
$emsdkCandidates += (Join-Path (Split-Path $PSScriptRoot -Parent) "emsdk")
|
||
|
||
$emccCommand = Get-Command emcc -ErrorAction SilentlyContinue
|
||
if ($emccCommand -and $emccCommand.Source) {
|
||
$emccSourceDir = Split-Path $emccCommand.Source -Parent
|
||
if (Test-Path (Join-Path $emccSourceDir "emcc.ps1")) {
|
||
$emsdkCandidates += (Split-Path (Split-Path $emccSourceDir -Parent) -Parent)
|
||
}
|
||
}
|
||
|
||
$EmsdkPath = $null
|
||
foreach ($candidate in $emsdkCandidates | Select-Object -Unique) {
|
||
if (-not [string]::IsNullOrWhiteSpace($candidate)) {
|
||
try {
|
||
if (Test-Path $candidate) {
|
||
$resolvedCandidate = [System.IO.Path]::GetFullPath($candidate)
|
||
if (Test-Path (Join-Path $resolvedCandidate "upstream\emscripten\emcc.ps1")) {
|
||
$EmsdkPath = $resolvedCandidate
|
||
break
|
||
}
|
||
}
|
||
} catch {
|
||
continue
|
||
}
|
||
}
|
||
}
|
||
|
||
if (-not $EmsdkPath) {
|
||
Write-Host "[错误] 未找到 Emscripten" -ForegroundColor Red
|
||
Write-Host "请设置 EMSDK 环境变量,或确认 emsdk 已安装。" -ForegroundColor Yellow
|
||
exit 1
|
||
}
|
||
|
||
# 设置 PATH
|
||
$env:PATH = "$EmsdkPath\upstream\emscripten;$env:PATH"
|
||
Write-Host "[✓] 设置 Emscripten 环境: $EmsdkPath" -ForegroundColor Green
|
||
|
||
# 2. 清理旧构建
|
||
if ($Clean) {
|
||
Write-Host "[ ] 清理构建文件..." -ForegroundColor Cyan
|
||
Remove-Item -Path "build", "public/wasm" -Recurse -Force -ErrorAction SilentlyContinue
|
||
Write-Host "[✓] 清理完成" -ForegroundColor Green
|
||
}
|
||
|
||
# 3. 创建目录
|
||
New-Item -Path "build", "public/wasm" -ItemType Directory -Force | Out-Null
|
||
|
||
# 4. 编译 WASM
|
||
Write-Host "[ ] 编译智能 WASM 模块..." -ForegroundColor Cyan
|
||
$startTime = Get-Date
|
||
|
||
# 编译命令 - 使用当前真实业务模块源码
|
||
$compileResult = emcc `
|
||
src/KinematicsWebAPI.cpp `
|
||
src/main.cpp `
|
||
src/Robot.cpp `
|
||
src/spc_core.cpp `
|
||
src/QuadrupedRobotSimulation/RobotConfig.cpp `
|
||
src/QuadrupedRobotSimulation/BaseClass.cpp `
|
||
src/QuadrupedRobotSimulation/KinematicsSimulation.cpp `
|
||
src/QuadrupedRobotSimulation/CompleteJsonExporter.cpp `
|
||
src/QuadrupedRobotSimulation/KinematicsReverse.cpp `
|
||
src/QuadrupedRobotSimulation/KinematicsHelper.cpp `
|
||
src/QuadrupedRobotSimulation/SharedGeometry.cpp `
|
||
src/FourBarMechanism/CrankSliderMechanism.cpp `
|
||
src/FourBarMechanism/CrankRockingBlockMechanism_Forward.cpp `
|
||
src/FourBarMechanism/CrankRockingBlockMechanism_Inverse.cpp `
|
||
src/FourBarMechanism/FourBarMechanism.cpp `
|
||
src/FourBarMechanism/SliderCrankMechanism.cpp `
|
||
src/RobotManager.cpp `
|
||
src/utils.cpp `
|
||
src/math_utils.cpp `
|
||
src/smart_json_wrapper.cpp `
|
||
src/kdl_parser/src/kdl_parser.cpp `
|
||
src/kdl_parser/src/joint.cpp `
|
||
src/kdl_parser/src/link.cpp `
|
||
src/kdl_parser/src/model.cpp `
|
||
src/kdl_parser/src/pose.cpp `
|
||
src/kdl_parser/src/tinystr.cpp `
|
||
src/kdl_parser/src/tinyxml.cpp `
|
||
src/kdl_parser/src/tinyxml2.cpp `
|
||
src/kdl_parser/src/tinyxmlerror.cpp `
|
||
src/kdl_parser/src/tinyxmlparser.cpp `
|
||
src/kdl_parser/src/twist.cpp `
|
||
src/kdl_parser/src/world.cpp `
|
||
-I./inc `
|
||
-I./inc/QuadrupedRobotSimulation `
|
||
-I./inc/FourBarMechanism `
|
||
-I./inc/SharedGeometry `
|
||
-I./src/kdl_parser/include `
|
||
-I./KDL/install_wasm/include `
|
||
-I./Eigen3 `
|
||
-I./Eigen3/eigen3 `
|
||
-L./KDL/install_wasm/lib `
|
||
-lorocos-kdl `
|
||
-std=c++17 `
|
||
-s WASM=1 `
|
||
-s EXPORTED_FUNCTIONS='["_init_func","_func","_smart_process_json","_smart_get_function_list","_smart_get_function_info","_smart_test_match","_smart_get_version","_smart_free_string","_malloc","_free","_add","_subtract","_multiply","_divide","_fibonacci","_create_buffer","_destroy_buffer","_compute_sum","_get_greeting","_main"]' `
|
||
-s EXPORTED_RUNTIME_METHODS='["UTF8ToString","stringToUTF8","lengthBytesUTF8","ccall","cwrap","HEAPU8","HEAP8","HEAPF32","HEAPF64"]' `
|
||
-s MODULARIZE=1 `
|
||
-s EXPORT_NAME='createSmartMathModule' `
|
||
-s ALLOW_MEMORY_GROWTH=1 `
|
||
-s ENVIRONMENT='web,node,worker' `
|
||
-s ASSERTIONS=1 `
|
||
-s DISABLE_EXCEPTION_CATCHING=0 `
|
||
-s INITIAL_MEMORY=67108864 `
|
||
-s MAXIMUM_MEMORY=268435456 `
|
||
-s STACK_SIZE=5242880 `
|
||
-s USE_PTHREADS=0 `
|
||
-O3 `
|
||
-Wno-deprecated-literal-operator `
|
||
-o public/wasm/smart_math.js 2>&1
|
||
|
||
$endTime = Get-Date
|
||
$duration = ($endTime - $startTime).TotalSeconds
|
||
|
||
if ($LASTEXITCODE -ne 0) {
|
||
Write-Host "[✗] 编译失败" -ForegroundColor Red
|
||
Write-Host $compileResult -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
|
||
Write-Host "[✓] 编译完成" -ForegroundColor Green
|
||
|
||
# 5. 检查生成的文件
|
||
$jsFile = Get-Item "public/wasm/smart_math.js" -ErrorAction SilentlyContinue
|
||
$wasmFile = Get-Item "public/wasm/smart_math.wasm" -ErrorAction SilentlyContinue
|
||
|
||
if (-not $jsFile -or -not $wasmFile) {
|
||
Write-Host "[✗] 未找到生成文件" -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
|
||
$jsSize = $jsFile.Length / 1KB
|
||
$wasmSize = $wasmFile.Length / 1KB
|
||
|
||
# 6. 显示构建结果
|
||
Write-Host ""
|
||
Write-Host "构建成功" -ForegroundColor Green
|
||
Write-Host ("=" * 50) -ForegroundColor DarkGray
|
||
Write-Host "生成文件:" -ForegroundColor White
|
||
Write-Host " - smart_math.js ($($jsSize.ToString('F1')) KB)" -ForegroundColor Gray
|
||
Write-Host " - smart_math.wasm ($($wasmSize.ToString('F1')) KB)" -ForegroundColor Gray
|
||
Write-Host ""
|
||
Write-Host "功能特性:" -ForegroundColor White
|
||
Write-Host " - 机器人正逆解业务接口 (func/init_func)" -ForegroundColor Gray
|
||
Write-Host " - SPC / 四足机器人 / 连杆机构业务接口" -ForegroundColor Gray
|
||
Write-Host " - 智能 JSON 数学测试接口" -ForegroundColor Gray
|
||
Write-Host " - Node / Web 双环境加载" -ForegroundColor Gray
|
||
Write-Host " - 与 Emscripten 内存管理兼容" -ForegroundColor Gray
|
||
Write-Host " - 批量回归测试可直接调用" -ForegroundColor Gray
|
||
Write-Host ""
|
||
Write-Host "输出目录: $((Get-Location).Path)\public\wasm" -ForegroundColor Gray
|
||
Write-Host "编译耗时: $($duration.ToString('F2')) 秒" -ForegroundColor Gray
|
||
Write-Host ""
|
||
|
||
# 7. 生成 JavaScript 包装器(可选)
|
||
Write-Host "[ ] 生成 JavaScript 包装器..." -ForegroundColor Cyan
|
||
|
||
$jsWrapper = @'
|
||
// Smart WASM JSON API JavaScript 包装器
|
||
class SmartWasmAPI {
|
||
constructor() {
|
||
this.module = null;
|
||
this.initialized = false;
|
||
}
|
||
|
||
allocString(value) {
|
||
const size = this.module.lengthBytesUTF8(value) + 1;
|
||
const ptr = this.module._malloc(size);
|
||
this.module.stringToUTF8(value, ptr, size);
|
||
return ptr;
|
||
}
|
||
|
||
async initialize() {
|
||
if (this.initialized) return;
|
||
|
||
// 加载 WASM 模块
|
||
this.module = await createSmartMathModule();
|
||
this.initialized = true;
|
||
|
||
console.log('Smart WASM API 初始化完成');
|
||
return this;
|
||
}
|
||
|
||
async initializeBusinessApi() {
|
||
if (!this.initialized) {
|
||
await this.initialize();
|
||
}
|
||
|
||
let responsePtr = null;
|
||
|
||
try {
|
||
responsePtr = this.module._init_func();
|
||
const responseStr = this.module.UTF8ToString(responsePtr);
|
||
return JSON.parse(responseStr);
|
||
} finally {
|
||
if (responsePtr) {
|
||
this.module._smart_free_string(responsePtr);
|
||
}
|
||
}
|
||
}
|
||
|
||
async processBusinessRequest(jsonRequest) {
|
||
if (!this.initialized) {
|
||
await this.initialize();
|
||
}
|
||
|
||
let requestPtr = null;
|
||
let responsePtr = null;
|
||
|
||
try {
|
||
requestPtr = this.allocString(JSON.stringify(jsonRequest));
|
||
responsePtr = this.module._func(requestPtr);
|
||
const responseStr = this.module.UTF8ToString(responsePtr);
|
||
return JSON.parse(responseStr);
|
||
} catch (error) {
|
||
console.error('处理业务 JSON 请求时出错:', error);
|
||
throw error;
|
||
} finally {
|
||
if (requestPtr) {
|
||
this.module._free(requestPtr);
|
||
}
|
||
if (responsePtr) {
|
||
this.module._smart_free_string(responsePtr);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 处理 JSON 请求
|
||
async processJsonRequest(jsonRequest) {
|
||
if (!this.initialized) {
|
||
await this.initialize();
|
||
}
|
||
|
||
let requestPtr = null;
|
||
let responsePtr = null;
|
||
|
||
try {
|
||
// 将 JSON 字符串转换为 WASM 内存中的字符串
|
||
requestPtr = this.allocString(JSON.stringify(jsonRequest));
|
||
|
||
// 调用 WASM 函数
|
||
responsePtr = this.module._smart_process_json(requestPtr);
|
||
|
||
// 将结果转换回 JavaScript 字符串
|
||
const responseStr = this.module.UTF8ToString(responsePtr);
|
||
|
||
// 解析 JSON 结果
|
||
return JSON.parse(responseStr);
|
||
} catch (error) {
|
||
console.error('处理 JSON 请求时出错:', error);
|
||
throw error;
|
||
} finally {
|
||
// 释放内存
|
||
if (requestPtr) {
|
||
this.module._free(requestPtr);
|
||
}
|
||
if (responsePtr) {
|
||
this.module._smart_free_string(responsePtr);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 获取函数列表
|
||
async getFunctionList() {
|
||
if (!this.initialized) {
|
||
await this.initialize();
|
||
}
|
||
|
||
let responsePtr = null;
|
||
|
||
try {
|
||
responsePtr = this.module._smart_get_function_list();
|
||
const responseStr = this.module.UTF8ToString(responsePtr);
|
||
return JSON.parse(responseStr);
|
||
} catch (error) {
|
||
console.error('获取函数列表时出错:', error);
|
||
throw error;
|
||
} finally {
|
||
if (responsePtr) {
|
||
this.module._smart_free_string(responsePtr);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 调用特定函数
|
||
async callFunction(funcName, params = {}) {
|
||
const request = {
|
||
req_cmd: funcName,
|
||
...params
|
||
};
|
||
|
||
return await this.processJsonRequest(request);
|
||
}
|
||
|
||
// 测试智能匹配
|
||
async testSmartMatch(jsonRequest) {
|
||
if (!this.initialized) {
|
||
await this.initialize();
|
||
}
|
||
|
||
let requestPtr = null;
|
||
let responsePtr = null;
|
||
|
||
try {
|
||
requestPtr = this.allocString(JSON.stringify(jsonRequest));
|
||
responsePtr = this.module._smart_test_match(requestPtr);
|
||
const responseStr = this.module.UTF8ToString(responsePtr);
|
||
return JSON.parse(responseStr);
|
||
} catch (error) {
|
||
console.error('测试智能匹配时出错:', error);
|
||
throw error;
|
||
} finally {
|
||
if (requestPtr) {
|
||
this.module._free(requestPtr);
|
||
}
|
||
if (responsePtr) {
|
||
this.module._smart_free_string(responsePtr);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 获取版本信息
|
||
async getVersion() {
|
||
if (!this.initialized) {
|
||
await this.initialize();
|
||
}
|
||
|
||
let responsePtr = null;
|
||
|
||
try {
|
||
responsePtr = this.module._smart_get_version();
|
||
const responseStr = this.module.UTF8ToString(responsePtr);
|
||
return JSON.parse(responseStr);
|
||
} catch (error) {
|
||
console.error('获取版本信息时出错:', error);
|
||
throw error;
|
||
} finally {
|
||
if (responsePtr) {
|
||
this.module._smart_free_string(responsePtr);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 直接调用数学函数(绕过 JSON 处理)
|
||
callMathFunction(name, ...args) {
|
||
if (!this.initialized) {
|
||
throw new Error('WASM 模块未初始化');
|
||
}
|
||
|
||
switch (name.toLowerCase()) {
|
||
case 'add':
|
||
return this.module._add(args[0] || 0, args[1] || 0);
|
||
case 'subtract':
|
||
return this.module._subtract(args[0] || 0, args[1] || 0);
|
||
case 'multiply':
|
||
return this.module._multiply(args[0] || 0, args[1] || 0);
|
||
case 'divide':
|
||
return this.module._divide(args[0] || 0, args[1] || 1);
|
||
case 'fibonacci':
|
||
return this.module._fibonacci(args[0] || 0);
|
||
default:
|
||
throw new Error('未知的数学函数: ' + name);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 创建全局实例
|
||
if (typeof window !== 'undefined') {
|
||
window.SmartWasmAPI = SmartWasmAPI;
|
||
}
|
||
|
||
export default SmartWasmAPI;
|
||
'@
|
||
|
||
$jsWrapper | Out-File -FilePath "public/wasm/smart_api_wrapper.js" -Encoding UTF8
|
||
Write-Host "[✓] 生成 JavaScript 包装器" -ForegroundColor Green
|
||
|
||
# 8. 本地测试(可选)
|
||
if ($Test) {
|
||
Write-Host "[ ] 运行本地测试..." -ForegroundColor Cyan
|
||
|
||
try {
|
||
node --version 2>&1 | Out-Null
|
||
if ($LASTEXITCODE -eq 0) {
|
||
Write-Host "[ ] 执行 WASM 回归测试..." -ForegroundColor Cyan
|
||
node scripts/run_wasm_tests.js
|
||
}
|
||
} catch {
|
||
Write-Host "[!] 本地测试跳过(需要 Node.js)" -ForegroundColor Yellow
|
||
}
|
||
}
|
||
|
||
# 9. 启动开发服务器(可选)
|
||
if ($Serve) {
|
||
Write-Host "[ ] 启动开发服务器..." -ForegroundColor Cyan
|
||
Write-Host " 访问: http://localhost:8080/smart_test.html" -ForegroundColor Yellow
|
||
Write-Host " 按 Ctrl+C 停止服务器" -ForegroundColor Yellow
|
||
Write-Host ""
|
||
|
||
Set-Location "public"
|
||
python -m http.server 8080
|
||
}
|
||
|
||
Write-Host ""
|
||
Write-Host "使用提示:" -ForegroundColor White
|
||
Write-Host " - 在 VS Code 中按 F5 启动调试" -ForegroundColor Gray
|
||
Write-Host " - 使用 Ctrl+Shift+B 快速构建" -ForegroundColor Gray
|
||
Write-Host " - 查看 public/wasm/smart_api_wrapper.js 了解 JavaScript API 使用" -ForegroundColor Gray
|
||
Write-Host " - 运行 npm run serve 启动开发服务器" -ForegroundColor Gray
|
||
Write-Host ""
|
||
|