Skip to content

1.1.8

1.1.8 #160

Workflow file for this run

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
# macOS Intel builds
- os: macos-15-intel
arch: x64
node_arch: x64
cmake_arch: x86_64
# 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 (基于 build_mingw.sh)
- name: Verify build environment (Windows MSYS2)
if: runner.os == 'Windows'
shell: msys2 {0}
run: |
echo "=== Verifying essential tools ==="
which cmake && cmake --version || { echo "❌ CMake not found"; exit 1; }
which gcc && gcc --version || { echo "❌ GCC not found"; exit 1; }
which g++ && g++ --version || { echo "❌ G++ not found"; exit 1; }
which gfortran && gfortran --version || { echo "❌ gfortran not found"; exit 1; }
which pkg-config && pkg-config --version || { echo "❌ pkg-config not found"; exit 1; }
which node && node --version || { echo "❌ Node.js not found"; exit 1; }
which npm && npm --version || { echo "❌ npm not found"; exit 1; }
which npx && npx --version || { echo "❌ npx not found"; exit 1; }
echo -e "\n=== Checking node-addon-api headers ==="
if [ -d "node_modules/node-addon-api" ]; then
echo "✅ node-addon-api package found"
if [ -f "node_modules/node-addon-api/napi.h" ]; then
echo "✅ napi.h found"
else
echo "❌ napi.h not found"
exit 1
fi
else
echo "❌ node-addon-api package not found"
exit 1
fi
echo -e "\n=== Checking FFTW3 availability ==="
if pkg-config --exists fftw3f; then
echo "✅ FFTW3F found"
echo "FFTW3F libraries: $(pkg-config --libs fftw3f)"
else
echo "❌ FFTW3F not found"
exit 1
fi
echo -e "\n=== Checking Boost installation ==="
if [ -d "/mingw64/include/boost" ]; then
echo "✅ Boost headers found"
else
echo "❌ Boost headers not found"
exit 1
fi
if ls /mingw64/lib/libboost* >/dev/null 2>&1; then
echo "✅ Boost libraries found"
else
echo "❌ Boost libraries not found"
exit 1
fi
# 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
# 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 compiled files structure:"
if [ -d "dist" ]; then
find dist -name "*.js" -type f | head -10
else
echo "dist directory not found"
fi
# 检查测试文件是否存在
if [ -f "dist/test/wsjtx.basic.test.js" ]; then
echo "✅ Basic test file found: dist/test/wsjtx.basic.test.js"
# 检查原生模块是否存在(统一要求 build/Release)
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
# 检查模块依赖
echo "🔍 Checking module dependencies..."
if command -v ldd >/dev/null 2>&1; then
ldd build/Release/wsjtx_lib_nodejs.node || echo "ldd failed, trying objdump"
fi
echo ""
echo "🔍 Checking DLL dependencies with objdump:"
objdump -p build/Release/wsjtx_lib_nodejs.node | grep "DLL Name" || echo "objdump failed"
# 检查关键库是否在PATH中可用
echo ""
echo "🔍 Checking library availability in MinGW environment:"
echo "PATH directories with libraries:"
echo $PATH | tr ':' '\n' | while read dir; do
if [ -d "$dir" ] && ls "$dir"/*.dll >/dev/null 2>&1; then
echo " 📁 $dir"
ls "$dir"/libfftw* "$dir"/libgfortran* "$dir"/libgcc* 2>/dev/null | head -3 || true
fi
done
# 设置环境变量以确保库能被找到
echo ""
echo "🔧 Setting up library paths for testing..."
export PATH="/mingw64/bin:$PATH"
export LD_LIBRARY_PATH="/mingw64/lib:$LD_LIBRARY_PATH"
echo "Updated PATH (first few entries):"
echo $PATH | tr ':' '\n' | head -3
# 验证Node.js版本兼容性
echo ""
echo "🔍 Verifying Node.js environment:"
echo "MinGW Node.js version:"
which node && node --version || echo "Node.js not found in MinGW PATH"
# 强制使用GitHub Actions安装的Node.js版本(与构建时一致)
echo ""
echo "🔧 Ensuring Node.js version consistency..."
echo "Expected Node.js version: ${{ env.NODE_VERSION }}"
# 查找GitHub Actions安装的Node.js路径
GITHUB_NODE_PATH=""
if [ -f "/c/hostedtoolcache/node/${{ env.NODE_VERSION }}"*/x64/node.exe ]; then
GITHUB_NODE_PATH=$(dirname $(find /c/hostedtoolcache/node -name "node.exe" | grep "${{ env.NODE_VERSION }}" | head -1))
echo "Found GitHub Actions Node.js at: $GITHUB_NODE_PATH"
elif [ -f "/c/Program Files/nodejs/node.exe" ]; then
GITHUB_NODE_PATH="/c/Program Files/nodejs"
echo "Using system Node.js at: $GITHUB_NODE_PATH"
fi
# 设置PATH,确保使用正确的Node.js版本,但保持MinGW库路径
if [ -n "$GITHUB_NODE_PATH" ]; then
export PATH="$GITHUB_NODE_PATH:/mingw64/bin:$PATH"
echo "Updated PATH to use GitHub Actions Node.js"
echo "Active Node.js version: $(node --version)"
echo "Active npm version: $(npm --version)"
else
echo "⚠️ Warning: Could not find GitHub Actions Node.js, using MinGW Node.js"
echo "This may cause version mismatch issues"
fi
# 运行测试
echo ""
echo "🧪 Running tests with version-matched Node.js..."
npm test
test_result=$?
if [ $test_result -eq 0 ]; then
echo "✅ Tests passed!"
else
echo "❌ Test failed with exit code: $test_result"
# 尝试直接加载模块
echo "🔍 Trying to load module directly..."
node -e "try { require('./build/Release/wsjtx_lib_nodejs.node'); console.log('✅ Module loaded successfully'); } catch(e) { console.error('❌ Load error:', e.message); console.error(' Code:', e.code); }"
exit $test_result
fi
else
echo "❌ Native module not found! Searching for .node files..."
find . -name "*.node" -type f || 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
# 11. 创建预构建二进制文件 - Linux/macOS
- name: Create prebuilt binaries (Linux/macOS)
if: runner.os != 'Windows'
run: |
# 映射GitHub Actions平台名称到Node.js标准平台名称
case "${{ matrix.os }}" in
ubuntu-latest|ubuntu-*) PLATFORM_NAME="linux" ;;
macos*) PLATFORM_NAME="darwin" ;;
windows-latest) PLATFORM_NAME="win32" ;;
*) PLATFORM_NAME="${{ matrix.os }}" ;;
esac
# 创建目标目录
TARGET_DIR="prebuilds/$PLATFORM_NAME-${{ matrix.arch }}"
echo "📁 Creating target directory: $TARGET_DIR"
echo " • GitHub runner: ${{ matrix.os }}"
echo " • Node.js platform: $PLATFORM_NAME"
echo " • Architecture: ${{ matrix.arch }}"
mkdir -p "$TARGET_DIR"
# 复制构建的 .node 文件(统一来自 build/Release)
if [ -f "build/Release/wsjtx_lib_nodejs.node" ]; then
cp build/Release/wsjtx_lib_nodejs.node "$TARGET_DIR/"
echo "Copied from build/Release/"
# 重要: NODE_FILE 必须指向目标目录中的文件,这样 dylibbundler 才会修改正确的文件
NODE_FILE="$TARGET_DIR/wsjtx_lib_nodejs.node"
else
echo "❌ Native module not found for packaging at build/Release!"
echo "当前 build 目录结构:"
find build -maxdepth 2 -type f -name "*.node" -print || true
exit 1
fi
# 检查并复制动态依赖库
echo "🔍 Checking dynamic dependencies..."
if [ "${{ runner.os }}" = "Linux" ]; then
echo "Checking Linux shared libraries..."
# 将依赖库与 .node 放在同级目录,与 macOS 和 Windows 保持一致
ldd "$NODE_FILE" | grep -v "linux-vdso\|ld-linux\|libc\|libm\|libpthread\|libdl" | awk '{print $3}' | grep -v "not found" | while read lib; do
if [ -f "$lib" ] && [[ "$lib" == *"libfftw"* || "$lib" == *"libgfortran"* || "$lib" == *"libgcc"* || "$lib" == *"libquadmath"* || "$lib" == *"libstdc++"* ]]; then
lib_name=$(basename "$lib")
echo "📦 Bundling: $lib_name -> $TARGET_DIR/"
cp -n "$lib" "$TARGET_DIR/" || cp "$lib" "$TARGET_DIR/"
fi
done
echo "Setting RPATH to \$ORIGIN (same directory as .node)"
patchelf --set-rpath '$ORIGIN' "$NODE_FILE" || true
echo "🔎 ldd after RPATH:"
ldd "$NODE_FILE" || true
echo ""
echo "📁 Bundled .so files in $TARGET_DIR:"
ls -la "$TARGET_DIR"/*.so* 2>/dev/null || echo "No .so files found"
elif [ "${{ runner.os }}" = "macOS" ]; then
echo "Bundling macOS dylibs with dylibbundler..."
# 优先在 Homebrew 的常见路径搜索
SEARCH_PATHS=(
"/opt/homebrew/opt/fftw/lib"
"/opt/homebrew/opt/gcc@14/lib/gcc/14"
"/opt/homebrew/opt/gcc/lib/gcc/current"
"/usr/local/opt/fftw/lib"
"/usr/local/opt/gcc@14/lib/gcc/14"
"/usr/local/opt/gcc/lib/gcc/current"
)
SP_ARGS=""
for p in "${SEARCH_PATHS[@]}"; do
if [ -d "$p" ]; then
SP_ARGS="$SP_ARGS -s $p"
fi
done
# 动态加入 Cellar 路径,避免某些环境下找不到实际文件
BREW_PREFIX=$(brew --prefix 2>/dev/null || echo "/opt/homebrew")
for p in "$BREW_PREFIX/Cellar/fftw"/*/lib "$BREW_PREFIX/Cellar/gcc"/*/lib/gcc/current; do
if [ -d "$p" ]; then
SP_ARGS="$SP_ARGS -s $p"
fi
done
# 将依赖库与 .node 放在同级目录,避免嵌套路径问题
# 注意: -od 会清空目标目录,但 .node 已经复制到 TARGET_DIR,dylibbundler 不会删除它
# 使用 -b 启用实际复制
dylibbundler -x "$NODE_FILE" -d "$TARGET_DIR" -p "@loader_path/" $SP_ARGS -b
echo ""
echo "📁 Bundled dylibs in $TARGET_DIR:"
ls -la "$TARGET_DIR"/*.dylib 2>/dev/null || echo "No dylib files found"
echo ""
echo "🔎 Final otool -L of packaged .node file ($NODE_FILE):"
otool -L "$NODE_FILE"
echo ""
echo "🔍 Verifying all dylib paths are relative:"
if otool -L "$NODE_FILE" | grep -E '^\s+(/opt/homebrew|/usr/local)'; then
echo "❌ ERROR: Found absolute Homebrew paths in final binary!"
exit 1
else
echo "✅ All dependency paths are relative"
fi
fi
# 显示构建结果
echo "📁 构建完成的文件:"
ls -la "$TARGET_DIR"
# 创建构建信息文件
cat > "$TARGET_DIR/build-info.json" << EOF
{
"platform": "$PLATFORM_NAME",
"github_runner": "${{ matrix.os }}",
"arch": "${{ matrix.arch }}",
"node_version": "${{ env.NODE_VERSION }}",
"build_time": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"cmake_arch": "${{ matrix.cmake_arch }}",
"file_size": $(stat -c%s "$TARGET_DIR"/*.node 2>/dev/null || stat -f%z "$TARGET_DIR"/*.node 2>/dev/null || echo "unknown"),
"bundled_libraries": $(ls "$TARGET_DIR" | grep -E "\\.(so|dylib)$" | wc -l)
}
EOF
echo "📋 构建信息:"
cat "$TARGET_DIR/build-info.json"
shell: bash
# 11a. 创建预构建二进制文件 - Windows (MSYS2)
- name: Create prebuilt binaries (Windows)
if: runner.os == 'Windows'
shell: msys2 {0}
run: |
echo "🔧 Windows prebuilt packaging started"
echo "Environment info:"
echo " • Shell: $0"
echo " • PWD: $(pwd)"
echo " • User: $(whoami)"
echo ""
# 映射GitHub Actions平台名称到Node.js标准平台名称
case "${{ matrix.os }}" in
ubuntu-latest|ubuntu-*) PLATFORM_NAME="linux" ;;
macos*) PLATFORM_NAME="darwin" ;;
windows-latest) PLATFORM_NAME="win32" ;;
*) PLATFORM_NAME="${{ matrix.os }}" ;;
esac
# 创建目标目录
TARGET_DIR="prebuilds/$PLATFORM_NAME-${{ matrix.arch }}"
echo "📁 Creating target directory: $TARGET_DIR"
echo " • GitHub runner: ${{ matrix.os }}"
echo " • Node.js platform: $PLATFORM_NAME"
echo " • Architecture: ${{ matrix.arch }}"
mkdir -p "$TARGET_DIR"
# 复制构建的 .node 文件 - 检查两个可能的位置
if [ -f "build/Release/wsjtx_lib_nodejs.node" ]; then
cp build/Release/wsjtx_lib_nodejs.node "$TARGET_DIR/"
echo "✅ Copied from build/Release/"
NODE_FILE="build/Release/wsjtx_lib_nodejs.node"
elif [ -f "build/wsjtx_lib_nodejs.node" ]; then
cp build/wsjtx_lib_nodejs.node "$TARGET_DIR/"
echo "✅ Copied from build/"
NODE_FILE="build/wsjtx_lib_nodejs.node"
else
echo "❌ Native module not found for packaging!"
exit 1
fi
# 检查并复制必要的DLL依赖
echo "🔍 Analyzing DLL dependencies..."
# 获取DLL依赖列表
REQUIRED_DLLS=$(objdump -p "$NODE_FILE" | grep "DLL Name" | awk '{print $3}' | grep -E "(libfftw|libgfortran|libgcc|libwinpthread|libstdc)")
echo "📦 Required DLLs to bundle:"
for dll in $REQUIRED_DLLS; do
echo " - $dll"
done
# 从MinGW复制必要的DLL(Windows 不使用子目录,需与 .node 同级)
echo ""
echo "📋 Copying DLLs from MinGW..."
bundled_count=0
missing_dlls=""
# 首先检查MinGW目录是否存在
echo "🔍 Checking MinGW directory..."
if [ -d "/mingw64/bin" ]; then
echo " ✅ /mingw64/bin exists"
echo " Available DLLs in /mingw64/bin:"
ls /mingw64/bin/lib*.dll | head -10 || echo " No lib*.dll files found"
else
echo " ❌ /mingw64/bin not found!"
exit 1
fi
echo ""
echo "📋 Processing each required DLL..."
for dll in $REQUIRED_DLLS; do
echo " 🔍 Checking: $dll"
if [ -f "/mingw64/bin/$dll" ]; then
if cp "/mingw64/bin/$dll" "$TARGET_DIR/" 2>/dev/null; then
echo " ✅ Bundled: $dll"
bundled_count=$((bundled_count + 1))
else
echo " ❌ Copy failed: $dll"
missing_dlls="$missing_dlls $dll"
fi
else
echo " ❌ Missing: $dll"
missing_dlls="$missing_dlls $dll"
# 尝试查找类似名称的文件
echo " 🔍 Looking for similar files..."
find /mingw64/bin -name "*${dll%%-*}*" -type f | head -3 || echo " No similar files found"
fi
done
# 报告结果
echo ""
echo "📊 DLL bundling summary:"
echo " • Successfully bundled: $bundled_count DLLs"
if [ -n "$missing_dlls" ]; then
echo " • Missing DLLs:$missing_dlls"
echo " ⚠️ Some DLLs are missing, but continuing..."
fi
# 显示最终结果
echo ""
echo "📁 Final package contents:"
ls -la "$TARGET_DIR"
# 获取文件大小
node_size=$(stat -c%s "$TARGET_DIR"/*.node)
total_size=$(du -sb "$TARGET_DIR" | cut -f1)
# 创建构建信息文件
# 获取实际捆绑的DLL列表
bundled_dll_list=""
for dll_file in "$TARGET_DIR"/*.dll; do
if [ -f "$dll_file" ]; then
dll_name=$(basename "$dll_file")
if [ -z "$bundled_dll_list" ]; then
bundled_dll_list="\"$dll_name\""
else
bundled_dll_list="$bundled_dll_list, \"$dll_name\""
fi
fi
done
cat > "$TARGET_DIR/build-info.json" << EOF
{
"platform": "$PLATFORM_NAME",
"github_runner": "${{ matrix.os }}",
"arch": "${{ matrix.arch }}",
"node_version": "${{ env.NODE_VERSION }}",
"build_time": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"cmake_arch": "${{ matrix.cmake_arch }}",
"file_size": $node_size,
"bundled_libraries": $bundled_count,
"total_package_size": $total_size,
"required_dlls": [$(echo "$REQUIRED_DLLS" | sed 's/^/"/;s/$/"/' | paste -sd, -)],
"bundled_dlls": [$bundled_dll_list],
"missing_dlls": "$(echo $missing_dlls | sed 's/^ *//' | sed 's/ *$//')"
}
EOF
echo ""
echo "📋 构建信息:"
cat "$TARGET_DIR/build-info.json"
echo ""
echo "📊 Package summary:"
echo " • Native module: $(basename $NODE_FILE) ($(numfmt --to=iec $node_size))"
echo " • Bundled DLLs: $bundled_count"
echo " • Total size: $(numfmt --to=iec $total_size)"
# 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' || (startsWith(matrix.os, 'macos') && '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' || (startsWith(matrix.os, 'macos') && '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