# 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/api/KinematicsWebAPI.Core.cpp ` src/api/KinematicsWebAPI.RobotCommands.cpp ` src/api/KinematicsWebAPI.SpcCommands.cpp ` src/api/KinematicsWebAPI.FourBarCommands.cpp ` src/api/KinematicsWebAPI.QuadrupedCommands.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 ` third_party/kdl_parser/src/kdl_parser.cpp ` third_party/kdl_parser/src/joint.cpp ` third_party/kdl_parser/src/link.cpp ` third_party/kdl_parser/src/model.cpp ` third_party/kdl_parser/src/pose.cpp ` third_party/kdl_parser/src/tinystr.cpp ` third_party/kdl_parser/src/tinyxml.cpp ` third_party/kdl_parser/src/tinyxml2.cpp ` third_party/kdl_parser/src/tinyxmlerror.cpp ` third_party/kdl_parser/src/tinyxmlparser.cpp ` third_party/kdl_parser/src/twist.cpp ` third_party/kdl_parser/src/world.cpp ` -I./include ` -I./third_party ` -I./third_party/kdl_parser/include ` -I./third_party/orocos_kdl/install_wasm/include ` -I./third_party/eigen3 ` -L./third_party/orocos_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 ""