fix: update gendef command in CMakeLists.txt for proper output redire… #139
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and Package | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| tags: [ 'v*' ] | |
| pull_request: | |
| branches: [ main ] | |
| env: | |
| NODE_VERSION: '20' | |
| jobs: | |
| build: | |
| name: Build on ${{ matrix.os }} (${{ matrix.arch }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # Linux builds | |
| - os: ubuntu-latest | |
| arch: x64 | |
| node_arch: x64 | |
| cmake_arch: x86_64 | |
| # Linux ARM64 builds (native) | |
| - os: ubuntu-24.04-arm | |
| arch: arm64 | |
| node_arch: arm64 | |
| cmake_arch: arm64 | |
| # macOS builds | |
| - os: macos-latest | |
| arch: arm64 | |
| node_arch: arm64 | |
| cmake_arch: arm64 | |
| # Windows builds with MSYS2/MinGW-w64 | |
| - os: windows-latest | |
| arch: x64 | |
| node_arch: x64 | |
| cmake_arch: x64 | |
| steps: | |
| # 1. 检出代码 | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| fetch-depth: 0 | |
| # 2. 设置 Node.js 环境 | |
| - name: Setup Node.js | |
| id: setup_node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| architecture: ${{ matrix.node_arch }} | |
| # 3. 安装系统依赖 - Linux | |
| - name: Install Linux dependencies | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| cmake \ | |
| build-essential \ | |
| gfortran \ | |
| libfftw3-dev \ | |
| libboost-all-dev \ | |
| pkg-config \ | |
| patchelf | |
| # 3. 安装系统依赖 - macOS | |
| - name: Install macOS dependencies | |
| if: runner.os == 'macOS' | |
| run: | | |
| brew install cmake fftw boost gcc pkg-config dylibbundler | |
| # 根据架构设置不同的路径 | |
| if [ "${{ matrix.arch }}" = "arm64" ]; then | |
| # Apple Silicon (ARM64) | |
| BREW_PREFIX="/opt/homebrew" | |
| else | |
| # Intel (x64) | |
| BREW_PREFIX="/usr/local" | |
| fi | |
| # 确保brew路径在PATH中 | |
| echo "${BREW_PREFIX}/bin" >> $GITHUB_PATH | |
| # 验证gfortran安装并设置环境变量 | |
| echo "Checking gfortran installation..." | |
| ls -la ${BREW_PREFIX}/bin/gfortran* || echo "gfortran not found" | |
| # 找到正确的gfortran路径并设置为环境变量 | |
| GFORTRAN_PATH=$(find ${BREW_PREFIX}/bin -name "gfortran*" | head -1) | |
| if [ -n "$GFORTRAN_PATH" ] && [ -x "$GFORTRAN_PATH" ]; then | |
| echo "Found gfortran at: $GFORTRAN_PATH" | |
| echo "FC=$GFORTRAN_PATH" >> $GITHUB_ENV | |
| echo "CMAKE_Fortran_COMPILER=$GFORTRAN_PATH" >> $GITHUB_ENV | |
| # 测试gfortran | |
| $GFORTRAN_PATH --version || echo "gfortran test failed" | |
| else | |
| echo "ERROR: gfortran not found or not executable" | |
| exit 1 | |
| fi | |
| # 设置库路径 | |
| echo "LIBRARY_PATH=${BREW_PREFIX}/lib:$LIBRARY_PATH" >> $GITHUB_ENV | |
| echo "LD_LIBRARY_PATH=${BREW_PREFIX}/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV | |
| # 3. 设置 MSYS2 环境 - Windows | |
| - name: Setup MSYS2 (Windows) | |
| if: runner.os == 'Windows' | |
| uses: msys2/setup-msys2@v2 | |
| with: | |
| msystem: MINGW64 | |
| update: true | |
| install: >- | |
| base-devel | |
| mingw-w64-x86_64-toolchain | |
| mingw-w64-x86_64-cmake | |
| mingw-w64-x86_64-pkg-config | |
| mingw-w64-x86_64-fftw | |
| mingw-w64-x86_64-boost | |
| mingw-w64-x86_64-gcc-fortran | |
| mingw-w64-x86_64-nodejs | |
| # 4. 安装 npm 依赖 | |
| - name: Install npm dependencies | |
| run: npm ci --ignore-scripts | |
| # 5. 构建 TypeScript | |
| - name: Build TypeScript | |
| run: npm run build:ts | |
| # 6. 验证构建环境 - Windows | |
| - name: Verify build environment (Windows MSYS2) | |
| if: runner.os == 'Windows' | |
| shell: msys2 {0} | |
| run: | | |
| echo "🔍 Verifying Windows MSYS2 build environment..." | |
| # 验证必要工具 | |
| for tool in cmake gcc g++ gfortran pkg-config node npm npx; do | |
| which $tool > /dev/null || { echo "❌ $tool not found"; exit 1; } | |
| done | |
| echo "✅ All build tools available" | |
| # 验证依赖库 | |
| [ -f "node_modules/node-addon-api/napi.h" ] || { echo "❌ node-addon-api not found"; exit 1; } | |
| pkg-config --exists fftw3f || { echo "❌ FFTW3F not found"; exit 1; } | |
| [ -d "/mingw64/include/boost" ] || { echo "❌ Boost not found"; exit 1; } | |
| echo "✅ All dependencies available" | |
| # 7. 构建原生模块 - Linux/macOS | |
| - name: Build native module (Linux/macOS) | |
| if: runner.os != 'Windows' | |
| run: | | |
| # 清理可能存在的CMake缓存 | |
| rm -rf build/ | |
| # 原生编译(支持所有架构) | |
| npx cmake-js compile --arch=${{ matrix.cmake_arch }} | |
| # 8. 构建原生模块 - Windows MSYS2/MinGW-w64 (基于 build_mingw.sh) | |
| - name: Build native module (Windows MSYS2) | |
| if: runner.os == 'Windows' | |
| shell: msys2 {0} | |
| run: | | |
| echo "=== Building with MSYS2/MinGW-w64 toolchain ===" | |
| # 调试:检查关键DLL的存在 | |
| echo "🔍 Pre-build DLL availability check:" | |
| for dll in libfftw3f-3.dll libfftw3f_threads-3.dll libgfortran-5.dll libgcc_s_seh-1.dll libwinpthread-1.dll libstdc++-6.dll; do | |
| if [ -f "/mingw64/bin/$dll" ]; then | |
| echo " ✅ $dll: $(stat -c%s /mingw64/bin/$dll) bytes" | |
| else | |
| echo " ❌ $dll: NOT FOUND" | |
| fi | |
| done | |
| echo "" | |
| # 设置环境变量强制使用 MinGW 工具链 | |
| export PKG_CONFIG_PATH="/mingw64/lib/pkgconfig" | |
| export CMAKE_PREFIX_PATH="/mingw64" | |
| export CC="gcc" | |
| export CXX="g++" | |
| export FC="gfortran" | |
| export CMAKE_MAKE_PROGRAM="mingw32-make" | |
| # 禁用 Visual Studio 检测 | |
| unset VSINSTALLDIR | |
| unset VCINSTALLDIR | |
| unset WindowsSDKDir | |
| unset VCPKG_ROOT | |
| echo -e "\n=== Environment variables ===" | |
| echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH" | |
| echo "CMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH" | |
| echo "CC=$CC, CXX=$CXX, FC=$FC" | |
| # 清理构建目录 | |
| rm -rf build/ | |
| echo -e "\n=== Starting build process ===" | |
| npx cmake-js compile --arch=${{ matrix.cmake_arch }} \ | |
| --generator="MinGW Makefiles" \ | |
| --no-retry \ | |
| --verbose | |
| BUILD_EXIT_CODE=$? | |
| echo "Build exit code: $BUILD_EXIT_CODE" | |
| if [ $BUILD_EXIT_CODE -ne 0 ]; then | |
| echo "❌ Build failed with exit code $BUILD_EXIT_CODE" | |
| exit $BUILD_EXIT_CODE | |
| fi | |
| # 验证构建产物 | |
| echo -e "\n=== Verifying build output ===" | |
| if [ -f "build/Release/wsjtx_lib_nodejs.node" ]; then | |
| echo "✅ Native module created: build/Release/wsjtx_lib_nodejs.node" | |
| ls -lh build/Release/wsjtx_lib_nodejs.node | |
| FILE_SIZE=$(stat -c%s "build/Release/wsjtx_lib_nodejs.node") | |
| echo "File size: $FILE_SIZE bytes" | |
| if [ "$FILE_SIZE" -lt 10000 ]; then | |
| echo "❌ ERROR: Built file is too small ($FILE_SIZE bytes)!" | |
| echo "This indicates a build failure that wasn't caught." | |
| exit 1 | |
| fi | |
| echo "File type:" | |
| file build/Release/wsjtx_lib_nodejs.node || true | |
| else | |
| echo "❌ ERROR: Native module not found after build!" | |
| echo "Build directory contents:" | |
| find build -type f || true | |
| exit 1 | |
| fi | |
| # 10. 运行测试 - Linux/macOS | |
| - name: Run tests (Linux/macOS) | |
| if: runner.os != 'Windows' | |
| run: | | |
| echo "📁 Checking compiled files structure:" | |
| ls -la dist/ || echo "dist directory not found" | |
| find dist -name "*.js" -type f || echo "No JS files found in dist" | |
| # 检查测试文件是否存在 | |
| if [ -f "dist/test/wsjtx.basic.test.js" ]; then | |
| echo "✅ Basic test file found: dist/test/wsjtx.basic.test.js" | |
| # 检查原生模块是否存在 | |
| if [ -f "build/Release/wsjtx_lib_nodejs.node" ]; then | |
| echo "✅ Native module found: build/Release/wsjtx_lib_nodejs.node" | |
| ls -la build/Release/wsjtx_lib_nodejs.node | |
| # 运行基础测试 | |
| npm test | |
| elif [ -f "build/wsjtx_lib_nodejs.node" ]; then | |
| echo "✅ Native module found: build/wsjtx_lib_nodejs.node" | |
| ls -la build/wsjtx_lib_nodejs.node | |
| # 确保在正确位置,某些系统可能需要Release子目录 | |
| mkdir -p build/Release | |
| cp build/wsjtx_lib_nodejs.node build/Release/ | |
| # 运行基础测试 | |
| npm test | |
| else | |
| echo "❌ Native module not found! Searching for .node files..." | |
| find . -name "*.node" || echo "No .node files found" | |
| exit 1 | |
| fi | |
| else | |
| echo "❌ Basic test file not found!" | |
| echo "Available test files:" | |
| find dist -name "*.test.js" -type f || echo "No test files found" | |
| exit 1 | |
| fi | |
| shell: bash | |
| # 10a. 运行测试 - Windows (MSYS2/MinGW) | |
| - name: Run tests (Windows) | |
| if: runner.os == 'Windows' | |
| shell: msys2 {0} | |
| run: | | |
| echo "📁 Checking test environment..." | |
| # 检查测试文件 | |
| if [ ! -f "dist/test/wsjtx.basic.test.js" ]; then | |
| echo "❌ Test file not found!" | |
| find dist -name "*.test.js" -type f || echo "No test files found" | |
| exit 1 | |
| fi | |
| echo "✅ Test file: dist/test/wsjtx.basic.test.js" | |
| # 检查原生模块是否存在 | |
| if [ ! -f "build/Release/wsjtx_lib_nodejs.node" ]; then | |
| echo "❌ Native module not found at build/Release/" | |
| echo "🔍 Searching for .node files..." | |
| find . -name "*.node" -type f || echo "No .node files found" | |
| exit 1 | |
| fi | |
| # 验证原生模块文件 | |
| NODE_FILE="build/Release/wsjtx_lib_nodejs.node" | |
| echo "✅ Native module found: $NODE_FILE" | |
| # 检查文件大小 | |
| FILE_SIZE=$(stat -c%s "$NODE_FILE" 2>/dev/null || echo "0") | |
| echo "📊 File size: $FILE_SIZE bytes" | |
| if [ "$FILE_SIZE" -lt 10000 ]; then | |
| echo "❌ ERROR: File size too small ($FILE_SIZE bytes), likely a build failure!" | |
| echo "🔍 File details:" | |
| ls -lh "$NODE_FILE" | |
| echo "🔍 File type:" | |
| file "$NODE_FILE" || true | |
| echo "🔍 Checking build log for errors..." | |
| exit 1 | |
| fi | |
| # 检查文件类型 | |
| echo "🔍 File type check:" | |
| file "$NODE_FILE" || true | |
| # 检查 DLL 依赖 | |
| echo "" | |
| echo "🔍 DLL dependencies:" | |
| objdump -p "$NODE_FILE" | grep "DLL Name" || echo "Cannot check DLL dependencies" | |
| # 设置库路径 | |
| echo "" | |
| echo "🔧 Setting up environment..." | |
| export PATH="/mingw64/bin:$PATH" | |
| export LD_LIBRARY_PATH="/mingw64/lib:$LD_LIBRARY_PATH" | |
| # 验证关键 DLL 是否存在 | |
| echo "🔍 Checking critical DLLs..." | |
| for dll in libfftw3f-3.dll libgfortran-5.dll libgcc_s_seh-1.dll; do | |
| if [ -f "/mingw64/bin/$dll" ]; then | |
| echo " ✅ $dll" | |
| else | |
| echo " ❌ $dll NOT FOUND" | |
| fi | |
| done | |
| # 运行测试 | |
| echo "" | |
| echo "🧪 Running tests..." | |
| if npm test; then | |
| echo "✅ Tests passed!" | |
| else | |
| echo "❌ Test failed" | |
| echo "🔍 Attempting direct module load..." | |
| node -e "try { require('./build/Release/wsjtx_lib_nodejs.node'); console.log('✅ Module loads OK'); } catch(e) { console.error('❌ Error:', e.message); console.error('Stack:', e.stack); }" | |
| exit 1 | |
| fi | |
| # 11. 创建预构建二进制文件 - Linux/macOS | |
| - name: Create prebuilt binaries (Linux/macOS) | |
| if: runner.os != 'Windows' | |
| run: | | |
| # 加载辅助函数 | |
| source scripts/ci-helpers.sh | |
| # 获取平台名称 | |
| PLATFORM_NAME=$(get_platform_name "${{ matrix.os }}") | |
| TARGET_DIR="prebuilds/$PLATFORM_NAME-${{ matrix.arch }}" | |
| echo "=========================================" | |
| echo "📦 Creating prebuilt package" | |
| echo "=========================================" | |
| echo "Platform: $PLATFORM_NAME" | |
| echo "Architecture: ${{ matrix.arch }}" | |
| echo "Target: $TARGET_DIR" | |
| echo "=========================================" | |
| mkdir -p "$TARGET_DIR" | |
| # 复制 .node 文件 | |
| if [ ! -f "build/Release/wsjtx_lib_nodejs.node" ]; then | |
| echo "❌ Native module not found at build/Release/" | |
| find build -maxdepth 2 -name "*.node" -type f | |
| exit 1 | |
| fi | |
| cp build/Release/wsjtx_lib_nodejs.node "$TARGET_DIR/" | |
| NODE_FILE="$TARGET_DIR/wsjtx_lib_nodejs.node" | |
| echo "✅ Copied .node file to $TARGET_DIR" | |
| # 平台特定的依赖打包 | |
| if [ "${{ runner.os }}" = "Linux" ]; then | |
| bundle_linux_dependencies "$NODE_FILE" "$TARGET_DIR" | |
| elif [ "${{ runner.os }}" = "macOS" ]; then | |
| bundle_macos_dependencies "$NODE_FILE" "$TARGET_DIR" | |
| fi | |
| # 显示结果 | |
| show_package_summary "$TARGET_DIR" | |
| # 创建构建信息 | |
| create_build_info "$TARGET_DIR" "$PLATFORM_NAME" "${{ matrix.os }}" "${{ matrix.arch }}" "${{ env.NODE_VERSION }}" "${{ matrix.cmake_arch }}" | |
| shell: bash | |
| # 11a. 创建预构建二进制文件 - Windows (MSYS2) | |
| - name: Create prebuilt binaries (Windows) | |
| if: runner.os == 'Windows' | |
| shell: msys2 {0} | |
| run: | | |
| # 加载辅助函数 | |
| source scripts/ci-helpers.sh | |
| # 获取平台名称 | |
| PLATFORM_NAME=$(get_platform_name "${{ matrix.os }}") | |
| TARGET_DIR="prebuilds/$PLATFORM_NAME-${{ matrix.arch }}" | |
| echo "=========================================" | |
| echo "📦 Creating prebuilt package (Windows)" | |
| echo "=========================================" | |
| echo "Platform: $PLATFORM_NAME" | |
| echo "Architecture: ${{ matrix.arch }}" | |
| echo "Target: $TARGET_DIR" | |
| echo "=========================================" | |
| mkdir -p "$TARGET_DIR" | |
| # 复制 .node 文件 | |
| if [ -f "build/Release/wsjtx_lib_nodejs.node" ]; then | |
| cp build/Release/wsjtx_lib_nodejs.node "$TARGET_DIR/" | |
| NODE_FILE="build/Release/wsjtx_lib_nodejs.node" | |
| elif [ -f "build/wsjtx_lib_nodejs.node" ]; then | |
| cp build/wsjtx_lib_nodejs.node "$TARGET_DIR/" | |
| NODE_FILE="build/wsjtx_lib_nodejs.node" | |
| else | |
| echo "❌ Native module not found!" | |
| exit 1 | |
| fi | |
| echo "✅ Copied .node file to $TARGET_DIR" | |
| # 打包 DLL 依赖 | |
| bundle_windows_dependencies "$NODE_FILE" "$TARGET_DIR" | |
| # 显示结果 | |
| show_package_summary "$TARGET_DIR" | |
| # 创建构建信息 | |
| create_build_info "$TARGET_DIR" "$PLATFORM_NAME" "${{ matrix.os }}" "${{ matrix.arch }}" "${{ env.NODE_VERSION }}" "${{ matrix.cmake_arch }}" | |
| # 12. 上传构建产物到 artifacts | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: prebuilt-${{ matrix.os == 'ubuntu-24.04-arm' && 'linux' || (matrix.os == 'ubuntu-latest' && 'linux' || (matrix.os == 'macos-latest' && 'darwin' || 'win32')) }}-${{ matrix.arch }} | |
| path: prebuilds/ | |
| retention-days: 30 | |
| if-no-files-found: error | |
| # 13. 上传完整构建目录(用于调试) | |
| - name: Upload build directory for debugging | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: build-debug-${{ matrix.os == 'ubuntu-24.04-arm' && 'linux' || (matrix.os == 'ubuntu-latest' && 'linux' || (matrix.os == 'macos-latest' && 'darwin' || 'win32')) }}-${{ matrix.arch }} | |
| path: | | |
| build/ | |
| CMakeCache.txt | |
| cmake_install.cmake | |
| retention-days: 7 | |
| # 汇总所有构建产物 | |
| collect-artifacts: | |
| name: Collect All Artifacts | |
| needs: build | |
| runs-on: ubuntu-latest | |
| if: always() && needs.build.result == 'success' | |
| steps: | |
| - name: Download all build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: all-artifacts | |
| - name: Organize artifacts | |
| run: | | |
| mkdir -p final-prebuilds | |
| # 合并所有预构建文件 | |
| echo "📁 可用的构建产物目录:" | |
| ls -la all-artifacts/ || echo "No artifacts directory" | |
| for artifact_dir in all-artifacts/prebuilt-*; do | |
| if [ -d "$artifact_dir" ]; then | |
| echo "📦 处理 $artifact_dir" | |
| # 显示目录内容以便调试 | |
| echo " 内容:" | |
| ls -la "$artifact_dir" | |
| cp -r "$artifact_dir"/* final-prebuilds/ | |
| fi | |
| done | |
| echo "" | |
| echo "📋 合并后的final-prebuilds目录结构:" | |
| find final-prebuilds -type f | sort | |
| # 显示最终结果 | |
| echo "所有平台的构建产物:" | |
| find final-prebuilds -name "*.node" -exec ls -la {} \; | |
| # 汇总构建信息 | |
| echo "# 构建摘要" > build-summary.md | |
| echo "构建时间: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> build-summary.md | |
| echo "" >> build-summary.md | |
| echo "## 支持的平台:" >> build-summary.md | |
| for info_file in final-prebuilds/*/build-info.json; do | |
| if [ -f "$info_file" ]; then | |
| platform=$(jq -r '.platform' "$info_file") | |
| arch=$(jq -r '.arch' "$info_file") | |
| file_size=$(jq -r '.file_size' "$info_file") | |
| echo "- $platform-$arch ($(numfmt --to=iec $file_size 2>/dev/null || echo $file_size))" >> build-summary.md | |
| fi | |
| done | |
| echo "" >> build-summary.md | |
| echo "## 文件详情:" >> build-summary.md | |
| find final-prebuilds -name "*.node" | while read file; do | |
| size=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null || echo "unknown") | |
| size_human=$(numfmt --to=iec $size 2>/dev/null || echo "$size bytes") | |
| echo "- \`$(basename "$file")\`: $size_human" >> build-summary.md | |
| done | |
| - name: Upload combined artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: all-prebuilds | |
| path: | | |
| final-prebuilds/ | |
| build-summary.md | |
| retention-days: 90 |