Skip to content

Build Windows ARM64 (experimental) #3

Build Windows ARM64 (experimental)

Build Windows ARM64 (experimental) #3

name: Build Windows ARM64 (experimental)
# Experimental native Windows ARM64 build.
# - Runner: windows-11-arm (GitHub-hosted, public preview).
# - Harbour libs and Scintilla DLLs are built from source for ARM64.
# - Trigger is manual only until the pipeline stabilises; it is NOT
# wired to "release: published" to avoid breaking the release flow.
on:
workflow_dispatch:
inputs:
upload_to_release:
description: 'Upload artifact to a release tag (leave blank to skip)'
required: false
default: ''
permissions:
contents: write
env:
ASSET: HbBuilder-1.0.0-windows-arm64.zip
jobs:
build:
name: Build (arm64, experimental)
runs-on: windows-11-arm
steps:
- uses: actions/checkout@v4
- name: Set up MSVC (arm64)
uses: ilammy/msvc-dev-cmd@v1
with:
arch: arm64
- name: Show toolchain
shell: cmd
run: |
where cl.exe
where link.exe
where nmake.exe
cl.exe 2>&1 | findstr /C:"Version" /C:"ARM"
- name: Cache Harbour (ARM64)
id: cache-harbour
uses: actions/cache@v4
with:
path: C:\harbour
key: harbour-win-arm64-v1
- name: Locate GNU make on runner
id: findmake
shell: cmd
run: |
where mingw32-make 2>nul && (echo MAKE=mingw32-make>>%GITHUB_ENV%& goto :done)
where make 2>nul && (echo MAKE=make>>%GITHUB_ENV%& goto :done)
if exist "C:\Program Files\Git\usr\bin\make.exe" (
echo MAKE="C:\Program Files\Git\usr\bin\make.exe">>%GITHUB_ENV%
goto :done
)
if exist "C:\msys64\usr\bin\make.exe" (
echo MAKE=C:\msys64\usr\bin\make.exe>>%GITHUB_ENV%
goto :done
)
echo ERROR: no GNU make found on runner
exit /b 1
:done
echo MAKE found
- name: Build Harbour (ARM64) if cache miss
if: steps.cache-harbour.outputs.cache-hit != 'true'
shell: cmd
run: |
git clone --depth 1 https://github.com/harbour/core C:\harbour-src
cd /d C:\harbour-src
set HB_COMPILER=msvcarm64
set HB_PLATFORM=win
set HB_INSTALL_PREFIX=C:\harbour
set HB_BUILD_SHARED=no
set HB_BUILD_CONTRIBS=no
echo Using make: %MAKE%
REM Serialise (-j1) so harbour.exe in src/main is fully linked
REM before any sub-tree (src/vm, src/rtl, ...) tries to invoke it
REM to process .prg sources.
%MAKE% -j1 install
if errorlevel 1 (
echo Harbour build failed
exit /b 1
)
dir C:\harbour\lib\win\msvcarm64 2>nul || echo "No msvcarm64 lib dir — Harbour may have produced libs under a different name"
dir C:\harbour\lib\win 2>nul
dir C:\harbour\bin\win 2>nul
- name: Build Scintilla + Lexilla (ARM64)
shell: cmd
run: |
mkdir resources\scintilla_src 2>nul
cd resources\scintilla_src
if not exist scintilla\cocoa\ScintillaView.h (
curl -L -o scintilla556.tgz https://www.scintilla.org/scintilla556.tgz
curl -L -o lexilla520.tgz https://www.scintilla.org/lexilla520.tgz
tar xzf scintilla556.tgz
tar xzf lexilla520.tgz
del scintilla556.tgz lexilla520.tgz
)
REM Lexilla
cd lexilla\src
nmake -f lexilla.mak DIR_O=..\bin DIR_BIN=..\bin
if errorlevel 1 ( echo Lexilla build failed & exit /b 1 )
cd ..\..
REM Scintilla
cd scintilla\win32
nmake -f scintilla.mak DIR_O=..\bin DIR_BIN=..\bin
if errorlevel 1 ( echo Scintilla build failed & exit /b 1 )
cd ..\..
dir scintilla\bin
dir lexilla\bin
REM Stage DLLs where the loader expects them
mkdir ..\arm64 2>nul
copy /Y scintilla\bin\Scintilla.dll ..\arm64\
copy /Y lexilla\bin\Lexilla.dll ..\arm64\
- name: Build HbBuilder (ARM64)
shell: cmd
run: |
set HBDIR=C:\harbour
set HBBIN=%HBDIR%\bin\win\msvcarm64
if not exist "%HBBIN%\harbour.exe" set HBBIN=%HBDIR%\bin
set HBLIB=%HBDIR%\lib\win\msvcarm64
set HBINC=%HBDIR%\include
set SRCDIR=%CD%\source
set CPPDIR=%CD%\source\cpp
set INCDIR=%CD%\include
set OUTDIR=%CD%\bin
if not exist "%OUTDIR%" mkdir "%OUTDIR%"
echo === Step 1: Harbour PRG -> C ===
cd /d "%SRCDIR%"
"%HBBIN%\harbour.exe" hbbuilder_win.prg -n -w -es2 -q -I%HBINC% -I%INCDIR%
if errorlevel 1 ( echo HARBOUR FAILED & exit /b 1 )
echo === Step 2: cl.exe (arm64 host already set up by msvc-dev-cmd) ===
set CL_BASE=/c /O2 /W0 /EHsc /I"%HBINC%" /I"%INCDIR%"
cl.exe %CL_BASE% hbbuilder_win.c /Fohbbuilder_win.obj
if not exist hbbuilder_win.obj ( echo CL FAILED hbbuilder_win.c & exit /b 1 )
for %%f in (tform hbbridge tcontrol tcontrols hb_db_real) do (
if exist "%CPPDIR%\%%f.cpp" (
cl.exe %CL_BASE% "%CPPDIR%\%%f.cpp" /Fo%%f.obj
if not exist %%f.obj ( echo CL FAILED %%f.cpp & exit /b 1 )
)
)
echo === Step 2b: Resources ===
rc.exe /nologo /fohbbuilder_win.res hbbuilder_win.rc
set RES_OBJ=
if exist hbbuilder_win.res set RES_OBJ=hbbuilder_win.res
echo === Step 3: Link (arm64) ===
set OBJS=hbbuilder_win.obj tform.obj hbbridge.obj tcontrol.obj tcontrols.obj hb_db_real.obj %RES_OBJ%
link.exe /NOLOGO /SUBSYSTEM:WINDOWS /MACHINE:ARM64 /NODEFAULTLIB:LIBCMT ^
/OUT:"%OUTDIR%\hbbuilder_win_arm64.exe" ^
/LIBPATH:"%HBLIB%" ^
%OBJS% ^
hbrtl.lib hbvm.lib hbcpage.lib hblang.lib hbrdd.lib hbmacro.lib hbpp.lib ^
hbcommon.lib hbcplr.lib hbct.lib hbhsx.lib hbsix.lib hbusrrdd.lib ^
rddntx.lib rddnsx.lib rddcdx.lib rddfpt.lib hbdebug.lib hbpcre.lib ^
hbzlib.lib hbsqlit3.lib sqlite3.lib ^
gtwin.lib gtwvt.lib gtgui.lib ^
user32.lib gdi32.lib comctl32.lib comdlg32.lib shell32.lib ole32.lib ^
oleaut32.lib advapi32.lib ws2_32.lib winmm.lib msimg32.lib gdiplus.lib ^
winspool.lib ucrt.lib vcruntime.lib msvcrt.lib
if errorlevel 1 ( echo LINK FAILED & exit /b 1 )
dir "%OUTDIR%\hbbuilder_win_arm64.exe"
- name: Package
shell: pwsh
run: |
$stage = "HbBuilder-1.0.0-windows-arm64"
New-Item -ItemType Directory -Force -Path "$stage\bin","$stage\resources\arm64" | Out-Null
Copy-Item "bin\hbbuilder_win_arm64.exe" "$stage\bin\"
Copy-Item "resources\arm64\Scintilla.dll" "$stage\resources\arm64\"
Copy-Item "resources\arm64\Lexilla.dll" "$stage\resources\arm64\"
if (Test-Path "resources\icons") { Copy-Item -Recurse "resources\icons" "$stage\resources\" }
if (Test-Path "resources\harbour_logo.png") { Copy-Item "resources\harbour_logo.png" "$stage\resources\" }
@"
HbBuilder v1.0.0 — Windows ARM64 (experimental)
===============================================
Native Windows 11 ARM64 build. Requires an ARM64 PC
(Surface Pro X / 9 / 11, Snapdragon X, etc).
Run: bin\hbbuilder_win_arm64.exe
DLLs in resources\arm64\ must remain alongside the exe.
https://github.com/FiveTechSoft/HarbourBuilder
"@ | Set-Content "$stage\README.txt"
Compress-Archive -Path $stage -DestinationPath $env:ASSET -Force
Get-Item $env:ASSET | Select-Object Name,Length
- uses: actions/upload-artifact@v4
with:
name: ${{ env.ASSET }}
path: ${{ env.ASSET }}
- name: Upload to release
if: github.event_name == 'workflow_dispatch' && inputs.upload_to_release != ''
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ inputs.upload_to_release }}
files: ${{ env.ASSET }}