diff --git a/build.bat b/build.bat index 5b213c7..1959af5 100644 --- a/build.bat +++ b/build.bat @@ -1,58 +1,243 @@ @echo off setlocal enabledelayedexpansion +:: ============================================================ +:: YAPF build script — Clang / LLVM only +:: Windows x64 and ARM64 +:: ============================================================ +:: +:: Usage: +:: build.bat [options] +:: +:: Options: +:: --debug Debug build (no optimisation, full symbols) +:: --simd Enable SIMD paths (-DYAPF_USE_SIMD) +:: --static-only Build only static libraries +:: --shared-only Build only shared libraries (DLL) +:: --help Show this message +:: +:: Requirements: +:: clang from https://github.com/llvm/llvm-project/releases +:: or installed via: winget install LLVM.LLVM +:: llvm-ar bundled with LLVM +:: llvm-dlltool bundled with LLVM (generates .lib import library) +:: lld-link bundled with LLVM (linker, used via clang -fuse-ld=lld) +:: +:: All tools must be on PATH. The LLVM installer adds them automatically +:: when "Add LLVM to the system PATH" is selected. +:: ============================================================ -REM ZIG IS REQUIRED TO COMPILE -REM Pikture Build Script - Fast, Small, Easy +:: ── ANSI colour support (Windows 10 1511+, Windows Terminal) ──────── +for /f "tokens=4-5 delims=. " %%i in ('ver') do set WIN_VER=%%i.%%j +set ANSI_OK=0 +if !WIN_VER! GEQ 10.0 set ANSI_OK=1 -echo ====================================== -echo PIKTURE BUILD CONFIG -echo ====================================== - -set EXTRA_FLAGS= - -set /p USE_SIMD="Enable SIMD acceleration (AVX/NEON)? [y/N]: " -if /i "%USE_SIMD%"=="y" ( - set EXTRA_FLAGS=!EXTRA_FLAGS! -DPIKT_USE_SIMD +if !ANSI_OK!==1 ( + set "C_RED=[31m" + set "C_GRN=[32m" + set "C_YLW=[33m" + set "C_CYN=[36m" + set "C_BLD=[1m" + set "C_RST=[0m" +) else ( + set "C_RED=" & set "C_GRN=" & set "C_YLW=" + set "C_CYN=" & set "C_BLD=" & set "C_RST=" ) -set /p USE_OMP="Enable OpenMP multithreading? [y/N]: " -if /i "%USE_OMP%"=="y" ( - set EXTRA_FLAGS=!EXTRA_FLAGS! -DPIKT_USE_THREADS -fopenmp +:: ── Option parsing ─────────────────────────────────────────────────── +set OPT_DEBUG=0 +set OPT_SIMD=0 +set OPT_STATIC_ONLY=0 +set OPT_SHARED_ONLY=0 + +for %%A in (%*) do ( + if /i "%%A"=="--debug" set OPT_DEBUG=1 + if /i "%%A"=="--simd" set OPT_SIMD=1 + if /i "%%A"=="--static-only" set OPT_STATIC_ONLY=1 + if /i "%%A"=="--shared-only" set OPT_SHARED_ONLY=1 + if /i "%%A"=="--help" goto :show_help ) +if !OPT_STATIC_ONLY!==1 if !OPT_SHARED_ONLY!==1 ( + echo !C_RED![fail]!C_RST! --static-only and --shared-only are mutually exclusive. + exit /b 1 +) +goto :after_help + +:show_help + findstr /n "^" "%~f0" | findstr /r "^[3-9]:" | findstr /r "^1[0-9]:" > nul + more +2 "%~f0" | findstr /r "^::" | findstr /v "^:: ====" | ^ + for /f "delims=:" %%L in ('findstr /n "^"') do echo %%L + exit /b 0 + +:after_help + +:: ── Tool detection ─────────────────────────────────────────────────── echo. -echo Building with flags: -O3 -fPIC !EXTRA_FLAGS! -echo ====================================== +echo !C_BLD!──── Detecting tools ────!C_RST! -if not exist dist\windows_x64 mkdir dist\windows_x64 -if not exist dist\windows_arm64 mkdir dist\windows_arm64 -if not exist dist\macos_x64 mkdir dist\macos_x64 -if not exist dist\macos_arm64 mkdir dist\macos_arm64 -if not exist dist\linux_x64 mkdir dist\linux_x64 -if not exist dist\linux_arm64 mkdir dist\linux_arm64 +where clang >nul 2>&1 +if errorlevel 1 ( + echo !C_RED![fail]!C_RST! clang not found. + echo Install LLVM: winget install LLVM.LLVM + echo Then add it to PATH and reopen this terminal. + exit /b 1 +) +for /f "delims=" %%V in ('clang --version 2^>^&1 ^| findstr /r "clang version"') do ( + echo !C_CYN![info]!C_RST! Compiler : %%V +) -set FLAGS=-O3 -fPIC !EXTRA_FLAGS! +where llvm-ar >nul 2>&1 +if errorlevel 1 ( + echo !C_RED![fail]!C_RST! llvm-ar not found. Make sure LLVM is fully installed. + exit /b 1 +) +echo !C_CYN![info]!C_RST! Archiver : llvm-ar (LLVM) -REM Windows (Shared + Import Lib) -zig cc -target x86_64-windows %FLAGS% -shared pikture.c -o dist\windows_x64\pikture.dll -Wl,--out-implib,dist\windows_x64\pikture.lib -zig cc -target aarch64-windows %FLAGS% -shared pikture.c -o dist\windows_arm64\pikture.dll -Wl,--out-implib,dist\windows_arm64\pikture.lib +set HAVE_DLLTOOL=0 +where llvm-dlltool >nul 2>&1 +if not errorlevel 1 ( + set HAVE_DLLTOOL=1 + echo !C_CYN![info]!C_RST! DllTool : llvm-dlltool (LLVM) +) else ( + echo !C_YLW![warn]!C_RST! llvm-dlltool not found — .lib import library will be skipped +) -REM macOS (Shared) -zig cc -target x86_64-macos %FLAGS% -shared pikture.c -o dist\macos_x64\libpikture.dylib -zig cc -target aarch64-macos %FLAGS% -shared pikture.c -o dist\macos_arm64\libpikture.dylib +:: ── Compiler flags ─────────────────────────────────────────────────── +set CFLAGS=-std=c99 -Wall -Wextra -Wpedantic +set LFLAGS=-fuse-ld=lld -REM Linux (Shared) -zig cc -target x86_64-linux-gnu %FLAGS% -shared pikture.c -o dist\linux_x64\libpikture.so -zig cc -target aarch64-linux-gnu %FLAGS% -shared pikture.c -o dist\linux_arm64\libpikture.so +if !OPT_DEBUG!==1 ( + set CFLAGS=!CFLAGS! -O0 -g + echo !C_CYN![info]!C_RST! Mode : debug +) else ( + set CFLAGS=!CFLAGS! -O3 -DNDEBUG + set LFLAGS=!LFLAGS! -Wl,/OPT:REF,/OPT:ICF + echo !C_CYN![info]!C_RST! Mode : release +) -REM Linux (Static) -zig cc -target x86_64-linux-musl %FLAGS% -c pikture.c -o pikture_x64.o -zig ar rcs dist\linux_x64\libpikture.a pikture_x64.o +if !OPT_SIMD!==1 ( + set CFLAGS=!CFLAGS! -DYAPF_USE_SIMD + echo !C_CYN![info]!C_RST! SIMD : enabled +) -zig cc -target aarch64-linux-musl %FLAGS% -c pikture.c -o pikture_arm64.o -zig ar rcs dist\linux_arm64\libpikture.a pikture_arm64.o +set BUILD_SHARED=1 +set BUILD_STATIC=1 +if !OPT_STATIC_ONLY!==1 set BUILD_SHARED=0 +if !OPT_SHARED_ONLY!==1 set BUILD_STATIC=0 -del /q *.o +:: ── Output directories ─────────────────────────────────────────────── +if not exist dist\include mkdir dist\include +if not exist dist\windows-x64 mkdir dist\windows-x64 +if not exist dist\windows-arm64 mkdir dist\windows-arm64 -echo Build complete. +copy /y yapf.h dist\include\yapf.h >nul +echo !C_GRN![ ok ]!C_RST! Header ^→ dist\include\yapf.h + +:: ── Write module definition file ───────────────────────────────────── +:: Used by llvm-dlltool to generate a MSVC-compatible import library. +( + echo LIBRARY yapf + echo EXPORTS + echo yapf_load + echo yapf_save + echo yapf_free +) > dist\_yapf.def + +:: ==================================================================== +:: Build: Windows x64 +:: ==================================================================== +echo. +echo !C_BLD!──── Building Windows x64 ────!C_RST! + +if !BUILD_SHARED!==1 ( + clang --target=x86_64-w64-windows-gnu !CFLAGS! !LFLAGS! ^ + -shared yapf.c -o dist\windows-x64\yapf.dll + if errorlevel 1 ( + echo !C_RED![fail]!C_RST! Windows x64 shared build failed. + del /q dist\_yapf.def 2>nul + exit /b 1 + ) + echo !C_GRN![ ok ]!C_RST! dist\windows-x64\yapf.dll + + if !HAVE_DLLTOOL!==1 ( + llvm-dlltool -m i386:x86-64 -D yapf.dll ^ + -d dist\_yapf.def -l dist\windows-x64\yapf.lib + if not errorlevel 1 ( + echo !C_GRN![ ok ]!C_RST! dist\windows-x64\yapf.lib (import library) + ) else ( + echo !C_YLW![warn]!C_RST! Import library generation failed (non-fatal) + ) + ) +) + +if !BUILD_STATIC!==1 ( + clang --target=x86_64-w64-windows-gnu !CFLAGS! ^ + -c yapf.c -o dist\windows-x64\_yapf.obj + if errorlevel 1 ( + echo !C_RED![fail]!C_RST! Windows x64 static compile failed. + del /q dist\_yapf.def dist\windows-x64\_yapf.obj 2>nul + exit /b 1 + ) + llvm-ar rcs dist\windows-x64\libyapf.a dist\windows-x64\_yapf.obj + del /q dist\windows-x64\_yapf.obj + echo !C_GRN![ ok ]!C_RST! dist\windows-x64\libyapf.a (static) +) + +:: ==================================================================== +:: Build: Windows ARM64 +:: ==================================================================== +echo. +echo !C_BLD!──── Building Windows ARM64 ────!C_RST! + +:: Probe whether Clang can target ARM64 Windows without errors. +echo int x; | clang --target=aarch64-w64-windows-gnu -x c - -c -o nul >nul 2>&1 +if errorlevel 1 ( + echo !C_YLW![warn]!C_RST! ARM64 target not available in this Clang build — skipping. + echo If you need ARM64, install a full LLVM release from llvm.org. + goto :skip_arm64 +) + +if !BUILD_SHARED!==1 ( + clang --target=aarch64-w64-windows-gnu !CFLAGS! !LFLAGS! ^ + -shared yapf.c -o dist\windows-arm64\yapf.dll + if errorlevel 1 ( + echo !C_YLW![warn]!C_RST! Windows ARM64 shared build failed — skipping. + goto :skip_arm64 + ) + echo !C_GRN![ ok ]!C_RST! dist\windows-arm64\yapf.dll + + if !HAVE_DLLTOOL!==1 ( + llvm-dlltool -m arm64 -D yapf.dll ^ + -d dist\_yapf.def -l dist\windows-arm64\yapf.lib + if not errorlevel 1 ( + echo !C_GRN![ ok ]!C_RST! dist\windows-arm64\yapf.lib (import library) + ) + ) +) + +if !BUILD_STATIC!==1 ( + clang --target=aarch64-w64-windows-gnu !CFLAGS! ^ + -c yapf.c -o dist\windows-arm64\_yapf.obj + if not errorlevel 1 ( + llvm-ar rcs dist\windows-arm64\libyapf.a dist\windows-arm64\_yapf.obj + del /q dist\windows-arm64\_yapf.obj + echo !C_GRN![ ok ]!C_RST! dist\windows-arm64\libyapf.a (static) + ) else ( + echo !C_YLW![warn]!C_RST! Windows ARM64 static compile failed — skipping. + ) +) + +:skip_arm64 + +:: ── Cleanup temp files ─────────────────────────────────────────────── +del /q dist\_yapf.def 2>nul + +:: ── Summary ────────────────────────────────────────────────────────── +echo. +echo !C_BLD!──── Summary ────!C_RST! +for /r dist %%F in (*) do ( + echo !C_GRN!%%F!C_RST! +) +echo. +echo !C_GRN![ ok ]!C_RST! Done. endlocal