1+ name : Build and Package
2+
3+ on :
4+ push :
5+ branches : [ main, develop ]
6+ tags : [ 'v*' ]
7+ pull_request :
8+ branches : [ main ]
9+
10+ env :
11+ NODE_VERSION : ' 18'
12+
13+ jobs :
14+ build :
15+ name : Build on ${{ matrix.os }} (${{ matrix.arch }})
16+ runs-on : ${{ matrix.os }}
17+ strategy :
18+ fail-fast : false
19+ matrix :
20+ include :
21+ # Linux builds
22+ - os : ubuntu-latest
23+ arch : x64
24+ node_arch : x64
25+ cmake_arch : x86_64
26+
27+ # macOS builds
28+ - os : macos-latest
29+ arch : arm64
30+ node_arch : arm64
31+ cmake_arch : arm64
32+
33+ # Windows builds
34+ - os : windows-latest
35+ arch : x64
36+ node_arch : x64
37+ cmake_arch : x64
38+
39+ steps :
40+ # 1. 检出代码
41+ - name : Checkout code
42+ uses : actions/checkout@v4
43+ with :
44+ submodules : recursive
45+ fetch-depth : 0
46+
47+ # 2. 设置 Node.js 环境
48+ - name : Setup Node.js
49+ id : setup_node
50+ uses : actions/setup-node@v4
51+ with :
52+ node-version : ${{ env.NODE_VERSION }}
53+ architecture : ${{ matrix.node_arch }}
54+
55+ # 3. 安装系统依赖 - Linux
56+ - name : Install Linux dependencies
57+ if : runner.os == 'Linux'
58+ run : |
59+ sudo apt-get update
60+ sudo apt-get install -y \
61+ cmake \
62+ build-essential \
63+ gfortran \
64+ libfftw3-dev \
65+ libboost-all-dev \
66+ pkg-config
67+
68+ # 3a. Linux ARM64 交叉编译设置
69+ - name : Setup Linux ARM64 cross-compilation
70+ if : runner.os == 'Linux' && matrix.arch == 'arm64'
71+ run : |
72+ sudo apt-get install -y \
73+ gcc-aarch64-linux-gnu \
74+ g++-aarch64-linux-gnu \
75+ gfortran-aarch64-linux-gnu
76+ # 添加 ARM64 架构支持
77+ sudo dpkg --add-architecture arm64
78+ sudo apt-get update
79+ sudo apt-get install -y \
80+ libfftw3-dev:arm64 \
81+ libboost-all-dev:arm64
82+ # 设置交叉编译环境变量
83+ echo "CC=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
84+ echo "CXX=aarch64-linux-gnu-g++" >> $GITHUB_ENV
85+ echo "FC=aarch64-linux-gnu-gfortran" >> $GITHUB_ENV
86+
87+ # 3. 安装系统依赖 - macOS
88+ - name : Install macOS dependencies
89+ if : runner.os == 'macOS'
90+ run : |
91+ brew install cmake fftw boost gcc pkg-config
92+
93+ # 根据架构设置不同的路径
94+ if [ "${{ matrix.arch }}" = "arm64" ]; then
95+ # Apple Silicon (ARM64)
96+ BREW_PREFIX="/opt/homebrew"
97+ else
98+ # Intel (x64)
99+ BREW_PREFIX="/usr/local"
100+ fi
101+
102+ # 确保brew路径在PATH中
103+ echo "${BREW_PREFIX}/bin" >> $GITHUB_PATH
104+
105+ # 验证gfortran安装并设置环境变量
106+ echo "Checking gfortran installation..."
107+ ls -la ${BREW_PREFIX}/bin/gfortran* || echo "gfortran not found"
108+
109+ # 找到正确的gfortran路径
110+ GFORTRAN_PATH=$(find ${BREW_PREFIX}/bin -name "gfortran*" | head -1)
111+ if [ -n "$GFORTRAN_PATH" ] && [ -x "$GFORTRAN_PATH" ]; then
112+ echo "Found gfortran at: $GFORTRAN_PATH"
113+ echo "FC=$GFORTRAN_PATH" >> $GITHUB_ENV
114+ echo "CMAKE_Fortran_COMPILER=$GFORTRAN_PATH" >> $GITHUB_ENV
115+
116+ # 测试gfortran
117+ $GFORTRAN_PATH --version || echo "gfortran test failed"
118+ else
119+ echo "ERROR: gfortran not found or not executable"
120+ exit 1
121+ fi
122+
123+ # 设置库路径
124+ echo "LIBRARY_PATH=${BREW_PREFIX}/lib:$LIBRARY_PATH" >> $GITHUB_ENV
125+ echo "LD_LIBRARY_PATH=${BREW_PREFIX}/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV
126+
127+ # 3. 安装系统依赖 - Windows
128+ - name : Setup MSYS2 for Windows build
129+ if : runner.os == 'Windows'
130+ uses : msys2/setup-msys2@v2
131+ with :
132+ msystem : MINGW64
133+ update : true
134+ path-type : inherit
135+ install : >-
136+ mingw-w64-x86_64-gcc
137+ mingw-w64-x86_64-gcc-fortran
138+ mingw-w64-x86_64-cmake
139+ mingw-w64-x86_64-ninja
140+ mingw-w64-x86_64-pkg-config
141+ mingw-w64-x86_64-fftw
142+ mingw-w64-x86_64-boost
143+
144+ - name : Setup Windows environment
145+ if : runner.os == 'Windows'
146+ shell : msys2 {0}
147+ run : |
148+ echo "/c/msys64/mingw64/bin" >> $GITHUB_PATH
149+ echo "Verifying pkg-config installation..."
150+ which pkg-config || (echo "pkg-config not found, reinstalling..." && pacman -S --noconfirm mingw-w64-x86_64-pkg-config)
151+ pkg-config --version || (echo "Unable to run pkg-config, reinstalling..." && pacman -S --noconfirm mingw-w64-x86_64-pkg-config)
152+
153+ echo "CC=gcc" >> $GITHUB_ENV
154+ echo "CXX=g++" >> $GITHUB_ENV
155+ echo "FC=gfortran" >> $GITHUB_ENV
156+ echo "CMAKE_Fortran_COMPILER=gfortran" >> $GITHUB_ENV
157+ echo "CMAKE_GENERATOR=MinGW Makefiles" >> $GITHUB_ENV
158+
159+ gcc --version
160+ g++ --version
161+ gfortran --version
162+ cmake --version
163+
164+ # 4. 安装 npm 依赖
165+ - name : Install npm dependencies
166+ run : npm ci --ignore-scripts
167+
168+ # 5. 构建 TypeScript
169+ - name : Build TypeScript
170+ run : npm run build:ts
171+
172+ # 6. 构建原生模块 - Linux/macOS
173+ - name : Build native module (Linux/macOS)
174+ if : runner.os != 'Windows'
175+ run : |
176+ if [ "${{ matrix.arch }}" = "arm64" ] && [ "${{ runner.os }}" = "Linux" ]; then
177+ # Linux ARM64 交叉编译
178+ npx cmake-js compile --arch=${{ matrix.cmake_arch }} \
179+ --CDCMAKE_SYSTEM_NAME=Linux \
180+ --CDCMAKE_SYSTEM_PROCESSOR=aarch64 \
181+ --CDCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \
182+ --CDCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ \
183+ --CDCMAKE_Fortran_COMPILER=aarch64-linux-gnu-gfortran
184+ else
185+ # 本地编译
186+ npx cmake-js compile --arch=${{ matrix.cmake_arch }}
187+ fi
188+
189+ # 6. 构建原生模块 - Windows
190+ - name : Build native module (Windows)
191+ if : runner.os == 'Windows'
192+ shell : msys2 {0}
193+ run : |
194+ echo "--- Checking Node.js and npx in MSYS2 (with path-type: inherit) ---"
195+ echo "PATH: $PATH"
196+
197+ echo "which node:"
198+ which node || echo "node not found"
199+ echo "node --version:"
200+ node --version || echo "node not runnable"
201+
202+ echo "which npx:"
203+ which npx || echo "npx not found"
204+ echo "npx --version:"
205+ npx --version || echo "npx not runnable"
206+
207+ echo "Attempting to run npx cmake-js compile..."
208+ npx cmake-js compile --arch=${{ matrix.cmake_arch }} \
209+ -G "MinGW Makefiles" \
210+ --CDCMAKE_C_COMPILER=gcc \
211+ --CDCMAKE_CXX_COMPILER=g++ \
212+ --CDCMAKE_Fortran_COMPILER=gfortran \
213+ --CDCMAKE_SHARED_LINKER_FLAGS='' \
214+ --CDCMAKE_MODULE_LINKER_FLAGS='' \
215+ --CDCMAKE_EXE_LINKER_FLAGS='' \
216+ --CDCMAKE_JS_SRC='' \
217+ --verbose
218+
219+ # 7. 运行测试
220+ - name : Run tests
221+ run : |
222+ # 显示编译后的文件结构
223+ echo "📁 Checking compiled files structure:"
224+ ls -la dist/ || echo "dist directory not found"
225+ find dist -name "*.js" -type f || echo "No JS files found in dist"
226+
227+ # 检查测试文件是否存在
228+ if [ -f "dist/test/wsjtx.basic.test.js" ]; then
229+ echo "✅ Basic test file found: dist/test/wsjtx.basic.test.js"
230+
231+ # 检查原生模块是否存在
232+ if [ -f "build/Release/wsjtx_lib_nodejs.node" ]; then
233+ echo "✅ Native module found: build/Release/wsjtx_lib_nodejs.node"
234+ # 运行基础测试
235+ npm test
236+ else
237+ echo "❌ Native module not found! Cannot run tests."
238+ exit 1
239+ fi
240+ else
241+ echo "❌ Basic test file not found!"
242+ exit 1
243+ fi
244+
245+ # 8. 创建预构建二进制文件
246+ - name : Create prebuilt binaries
247+ run : |
248+ # 创建目标目录
249+ mkdir -p prebuilds/${{ matrix.os }}-${{ matrix.arch }}
250+
251+ # 复制构建的 .node 文件
252+ if [ "${{ runner.os }}" = "Windows" ]; then
253+ cp build/Release/*.node prebuilds/${{ matrix.os }}-${{ matrix.arch }}/
254+ else
255+ cp build/Release/*.node prebuilds/${{ matrix.os }}-${{ matrix.arch }}/
256+ fi
257+
258+ # 显示构建结果
259+ echo "构建完成的文件:"
260+ ls -la prebuilds/${{ matrix.os }}-${{ matrix.arch }}/
261+ shell : bash
262+
263+ # 9. 上传构建产物到 artifacts
264+ - name : Upload build artifacts
265+ uses : actions/upload-artifact@v4
266+ with :
267+ name : prebuilt-${{ matrix.os }}-${{ matrix.arch }}
268+ path : prebuilds/
269+ retention-days : 30
270+ if-no-files-found : error
271+
272+ # 10. 上传完整构建目录(用于调试)
273+ - name : Upload build directory for debugging
274+ if : failure()
275+ uses : actions/upload-artifact@v4
276+ with :
277+ name : build-debug-${{ matrix.os }}-${{ matrix.arch }}
278+ path : build/
279+ retention-days : 7
280+
281+ # 汇总所有构建产物
282+ collect-artifacts :
283+ name : Collect All Artifacts
284+ needs : build
285+ runs-on : ubuntu-latest
286+ if : always() && needs.build.result == 'success'
287+
288+ steps :
289+ - name : Download all build artifacts
290+ uses : actions/download-artifact@v4
291+ with :
292+ path : all-artifacts
293+
294+ - name : Organize artifacts
295+ run : |
296+ mkdir -p final-prebuilds
297+
298+ # 合并所有预构建文件
299+ for artifact_dir in all-artifacts/prebuilt-*; do
300+ if [ -d "$artifact_dir" ]; then
301+ echo "处理 $artifact_dir"
302+ cp -r "$artifact_dir"/* final-prebuilds/
303+ fi
304+ done
305+
306+ # 显示最终结果
307+ echo "所有平台的构建产物:"
308+ find final-prebuilds -name "*.node" -exec ls -la {} \;
309+
310+ # 创建构建摘要
311+ echo "# 构建摘要" > build-summary.md
312+ echo "构建时间: $(date)" >> build-summary.md
313+ echo "## 支持的平台:" >> build-summary.md
314+ find final-prebuilds -name "*.node" | while read file; do
315+ platform=$(echo "$file" | cut -d'/' -f2)
316+ echo "- $platform" >> build-summary.md
317+ done
318+
319+ - name : Upload combined artifacts
320+ uses : actions/upload-artifact@v4
321+ with :
322+ name : all-prebuilds
323+ path : |
324+ final-prebuilds/
325+ build-summary.md
326+ retention-days : 90
0 commit comments