diff --git a/.github/workflows/nightly-win-x86.yml b/.github/workflows/nightly-win-x86.yml new file mode 100644 index 000000000000..4ab80c34b71b --- /dev/null +++ b/.github/workflows/nightly-win-x86.yml @@ -0,0 +1,53 @@ +name: nightly-win-x86_64 + +on: + schedule: + - cron: '0 5 * * *' + workflow_dispatch: + +jobs: + build-windows: + runs-on: windows-latest + env: + ARTIFACT_DIR: ${{ github.workspace }}/nightly-toolchain + + steps: + - name: Preconfigure Git (LF line endings, long paths) + shell: bash + run: | + git config --global core.autocrlf false + git config --global core.eol lf + git config --global core.longpaths true + + - name: Checkout source (to src/) + uses: actions/checkout@v4 + with: + path: src + + - name: Install PyYAML + run: pip install pyyaml + + - name: Verify PyYAML + run: python -c "import yaml; print('PyYAML OK:', yaml.__version__)" + + - name: Build + working-directory: src + shell: pwsh + env: + GIT_AUTHOR_NAME: Qualcomm CI + GIT_AUTHOR_EMAIL: ci@qti.qualcomm.com + GIT_COMMITTER_NAME: Qualcomm CI + GIT_COMMITTER_EMAIL: ci@qti.qualcomm.com + run: | + ./qualcomm-software/embedded/scripts/build.ps1 + + - name: Upload Artifact + if: ${{ success() }} + uses: actions/upload-artifact@v4 + with: + name: cpullvm-toolchain-${{ github.run_id }}-Windows-x86 + path: | + ${{ env.ARTIFACT_DIR }}/*.txz + ${{ env.ARTIFACT_DIR }}/*.tgz + if-no-files-found: ignore + retention-days: 7 diff --git a/.github/workflows/pre-checkin.yml b/.github/workflows/pre-checkin.yml index 22effe76738f..f041d6d5965c 100644 --- a/.github/workflows/pre-checkin.yml +++ b/.github/workflows/pre-checkin.yml @@ -2,6 +2,10 @@ name: pre-checkin on: pull_request: + paths-ignore: + - 'qualcomm-software/embedded/scripts/build.ps1' + - '.github/workflows/nightly-win-x86.yml' + jobs: base: diff --git a/qualcomm-software/embedded/scripts/build.ps1 b/qualcomm-software/embedded/scripts/build.ps1 new file mode 100644 index 000000000000..8ce86bcf5a91 --- /dev/null +++ b/qualcomm-software/embedded/scripts/build.ps1 @@ -0,0 +1,312 @@ +# build.ps1 + +# Fail fast on errors thrown by PowerShell cmdlets +$ErrorActionPreference = "Stop" + +# === Derive directories === +$SCRIPT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Definition +$REPO_ROOT = (git -C $SCRIPT_DIR rev-parse --show-toplevel).Trim() +$WORKSPACE = (Resolve-Path "$REPO_ROOT\..").Path + +$SRC_DIR = $REPO_ROOT +$BUILD_DIR = "$WORKSPACE\build" +$INSTALL_DIR = "$WORKSPACE\install" +$ELD_DIR = "$REPO_ROOT\llvm\tools\eld" + +# === Config defaults === +if (-not $env:JOBS) { $env:JOBS = $env:NUMBER_OF_PROCESSORS } +if (-not $env:BUILD_MODE) { $env:BUILD_MODE = "Release" } +if (-not $env:ASSERTION_MODE) { $env:ASSERTION_MODE = "OFF" } + +# === Constants === +$ELD_REPO_URL = "https://github.com/qualcomm/eld.git" +$ELD_BRANCH = "main" +$ELD_COMMIT = "96a7dffdf65a68714c8311111d6a6d54a3a150db" + +$MUSL_EMBEDDED_REPO_URL = "https://github.com/qualcomm/musl-embedded.git" +$MUSL_EMBEDDED_BRANCH = "main" + +Write-Host "[log] SCRIPT_DIR = $SCRIPT_DIR" +Write-Host "[log] REPO_ROOT = $REPO_ROOT" +Write-Host "[log] WORKSPACE = $WORKSPACE" +Write-Host "[log] BUILD_DIR = $BUILD_DIR" +Write-Host "[log] INSTALL_DIR = $INSTALL_DIR" +Write-Host "[log] ELD_DIR = $ELD_DIR" +Write-Host "[log] BUILD_MODE = $env:BUILD_MODE" +Write-Host "[log] ASSERTIONS = $env:ASSERTION_MODE" +Write-Host "[log] JOBS = $env:JOBS" + +# === Resolve Visual Studio (vcvarsall.bat) === +$vswhere = Join-Path ${env:ProgramFiles(x86)} "Microsoft Visual Studio\Installer\vswhere.exe" +if (-not (Test-Path $vswhere)) { + $vswhere = Join-Path ${env:ProgramFiles} "Microsoft Visual Studio\Installer\vswhere.exe" +} +if (-not (Test-Path $vswhere)) { + $cmd = Get-Command vswhere -ErrorAction Ignore + if ($cmd) { $vswhere = $cmd.Source } +} +if (-not (Test-Path $vswhere)) { + Write-Error "*** ERROR: vswhere.exe not found in Program Files (x86), Program Files, or PATH ***" + exit 1 +} + +# Query the latest VS with VC tools component +$VS_INSTALL = & $vswhere -latest -products * ` + -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ` + -property installationPath +if (-not $VS_INSTALL) { + Write-Error "*** ERROR: Visual Studio installation not found via vswhere ***" + exit 1 +} + +# Get vcvarsall.bat and import the environment for x64 +$VCVARSALL = Join-Path $VS_INSTALL "VC\Auxiliary\Build\vcvarsall.bat" +if (-not (Test-Path $VCVARSALL)) { + Write-Error "*** ERROR: vcvarsall.bat not found at $VCVARSALL ***" + exit 1 +} + +# Load VS environment into the current PowerShell process +cmd /c "call `"$VCVARSALL`" x64 && set" | ForEach-Object { + if ($_ -match '^(.*?)=(.*)$') { + [System.Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process') + } +} + +# Tool sanity checks +foreach ($tool in @("git","python","cmake","ninja","clang-cl")) { + if (-not (Get-Command $tool -ErrorAction SilentlyContinue)) { + Write-Error "*** ERROR: $tool not found on PATH ***" + exit 1 + } +} + +# === Clean === +Write-Host "[log] Cleaning $BUILD_DIR and $INSTALL_DIR" +Remove-Item -Recurse -Force $BUILD_DIR,$INSTALL_DIR -ErrorAction SilentlyContinue + +# === Prepare workspace === +Write-Host "[log] Preparing workspace at: $WORKSPACE" +New-Item -ItemType Directory -Force -Path $BUILD_DIR,$INSTALL_DIR | Out-Null + +# === Clone repos === +if (-not (Test-Path "$WORKSPACE\musl-embedded\.git")) { + Write-Host "[log] Cloning musl-embedded..." + git clone $MUSL_EMBEDDED_REPO_URL "$WORKSPACE\musl-embedded" -b $MUSL_EMBEDDED_BRANCH +} + +if (-not (Test-Path "$ELD_DIR\.git")) { + Write-Host "[log] Cloning ELD..." + git clone $ELD_REPO_URL $ELD_DIR + Push-Location $ELD_DIR + git checkout $ELD_COMMIT + Pop-Location +} + +# === Apply patches === +Push-Location $SRC_DIR +python "qualcomm-software/embedded/tools/patchctl.py" apply -f "qualcomm-software/embedded/patchsets.yml" + +if ($LASTEXITCODE -ne 0) { + Write-Error "*** ERROR: Patch apply failed (exit=$LASTEXITCODE) ***" + exit $LASTEXITCODE +} + +Pop-Location + +# === Build === +Write-Host "[log] Configuring CMake..." + +# Provide Python to CMake/lit if available +$pythonExe = (Get-Command python -ErrorAction SilentlyContinue).Source +if ($pythonExe) { Write-Host "[log] Using Python: $pythonExe" } else { Write-Host "[warn] Python not found via Get-Command; relying on PATH" } + +# --- Prefer llvm-rc over Windows rc.exe to avoid cmcldeps/rc.exe hangs --- +$llvmRcCandidates = @( + (Join-Path $VS_INSTALL 'VC\Tools\Llvm\x64\bin\llvm-rc.exe'), # VS-bundled LLVM + 'C:\Program Files\LLVM\bin\llvm-rc.exe' # Standalone LLVM on GH runner +) +$llvmRc = $llvmRcCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1 + +$cmakeRcArg = '' +if ($llvmRc) { + Write-Host "[log] Using llvm-rc: $llvmRc" + # Normalize to forward slashes to keep CMake from parsing backslash escapes + $llvmRcForCMake = $llvmRc -replace '\\','/' + # FILEPATH type prevents quoting glitches in the generated CMakeRCCompiler.cmake + $cmakeRcArg = "-DCMAKE_RC_COMPILER:FILEPATH=$llvmRcForCMake" + Write-Host "[diag] CMAKE_RC_COMPILER = $llvmRcForCMake" +} else { + Write-Warning "[warn] llvm-rc.exe not found; falling back to Windows rc.exe (may hang)." +} + +# --- Generation --- +cmake -G "Ninja" ` + -S "$SRC_DIR\llvm" ` + -B "$BUILD_DIR\llvm" ` + -DCMAKE_INSTALL_PREFIX="$INSTALL_DIR" ` + -DLLVM_TARGETS_TO_BUILD="ARM;AArch64" ` + -DLLVM_EXTERNAL_PROJECTS="eld" ` + -DLLVM_EXTERNAL_ELD_SOURCE_DIR="$ELD_DIR" ` + -DLLVM_DEFAULT_TARGET_TRIPLE="aarch64-unknown-linux-gnu" ` + -DLIBCLANG_BUILD_STATIC=ON ` + -DLLVM_POLLY_LINK_INTO_TOOLS=ON ` + -DCMAKE_C_COMPILER=clang-cl ` + -DCMAKE_CXX_COMPILER=clang-cl ` + -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL ` + -DLLVM_ENABLE_ASSERTIONS="$env:ASSERTION_MODE" ` + -DLLVM_ENABLE_PROJECTS="llvm;clang;polly;lld;mlir" ` + $(if ($pythonExe) { "-DPython3_EXECUTABLE=`"$pythonExe`"" } else { "" }) ` + $cmakeRcArg ` + -DCMAKE_BUILD_TYPE="$env:BUILD_MODE" + +Push-Location "$BUILD_DIR\llvm" + +# --- Build (Ninja) --- +Write-Host "[log] Building LLVM with Ninja..." +& ninja +if ($LASTEXITCODE -ne 0) { Write-Error "*** ERROR: build failed (exit=$LASTEXITCODE) ***"; exit $LASTEXITCODE } + +# --- Install (Ninja) --- +Write-Host "[log] Install target..." +& ninja install +if ($LASTEXITCODE -ne 0) { Write-Error "*** ERROR: install failed (exit=$LASTEXITCODE) ***"; exit $LASTEXITCODE } + +# === Prefer our build bin and ensure Git Unix tools are available === +$env:PATH = "$BUILD_DIR\llvm\bin;$env:PATH" +$gitUsr = Join-Path ${env:ProgramFiles} "Git\usr\bin" +if (Test-Path $gitUsr) { + $env:PATH = "$env:PATH;$gitUsr" + Write-Host "[log] Added Git Unix tools to PATH: $gitUsr" +} else { + Write-Warning "[warn] Git usr\bin not found; polly-check-format may fail (missing diff)." +} + +# === Tests === +Write-Host "[log] ===== BEGIN TEST SUITE =====" +$FAIL_COUNT = 0 +foreach ($test in @("llvm","lld","eld","clang","polly")) { + Write-Host "[log] Running $test tests..." + & ninja -v "check-$test" + if ($LASTEXITCODE -ne 0) { + Write-Host "[ERROR] $test tests failed! (exit=$LASTEXITCODE)" + $FAIL_COUNT++ + } else { + Write-Host "[log] $test tests completed." + } +} + +Write-Host "[log] ===== END TEST SUITE =====" +Pop-Location + +if ($FAIL_COUNT -ne 0) { + Write-Host "[log] Build completed, but $FAIL_COUNT test suite(s) failed." + exit 1 +} +Write-Host "[log] Build and all tests completed successfully!" + +# --- Create artifact (PowerShell) --- + +# Simple local log helpers +$__w_log = { param($m) Write-Host "[log] $m" } +$__w_warn = { param($m) Write-Warning "[warn] $m" } + + +# Compute identifiers +$short_sha = (git -C $SRC_DIR rev-parse --short HEAD).Trim() +$suffix = Get-Date -Format "yyyyMMdd" + +# Artifact roots and name +$archive_root = "$WORKSPACE\artifacts" +$archive_dir = $INSTALL_DIR +$base_name = "cpullvm-toolchain-$($ELD_BRANCH.Split('/')[-1])-Windows-x86_64-$short_sha-$suffix" + +& $__w_log "Applying NIGHTLY compression settings" +$COMPRESS_EXT = "txz" +$archive_name = "${base_name}_nightly.$COMPRESS_EXT" + +$env:XZ_OPT = "--threads=$JOBS" + +# Ensure output directory exists +if (-not (Test-Path $archive_root)) { New-Item -ItemType Directory -Force -Path $archive_root | Out-Null } + +$tar_file = Join-Path $archive_root $archive_name +& $__w_log "Compressing '$archive_dir' into '$tar_file'" + +function Test-TarSupportsXz { + try { + $help = & tar --help 2>&1 + if ($LASTEXITCODE -ne 0) { return $false } + return ($help -match '-J' -or $help -match 'xz') + } catch { return $false } +} + +function Get-7ZipPath { + $candidates = @( + (Get-Command 7z -ErrorAction SilentlyContinue | ForEach-Object { $_.Source }), + "C:\Program Files\7-Zip\7z.exe", + "C:\Program Files (x86)\7-Zip\7z.exe" + ) | Where-Object { $_ -and (Test-Path $_) } | Select-Object -First 1 + return $candidates +} + +$usedTool = $null + +# Preferred: tar with xz support (Git for Windows ships bsdtar) +$tarCmd = Get-Command tar -ErrorAction SilentlyContinue +if ($tarCmd) { + if (Test-TarSupportsXz) { + # tar -cJf -C . + & tar -cJf "$tar_file" -C "$archive_dir" . + if ($LASTEXITCODE -ne 0) { throw "tar failed with exit code $LASTEXITCODE" } + $usedTool = "tar -cJf" + } else { + & $__w_warn "tar found but XZ (-J) not supported; falling back to 7‑Zip." + } +} else { + & $__w_warn "tar not found; attempting 7‑Zip fallback." +} + +# Fallback: 7‑Zip (create .tar, then compress to .xz -> .txz) +if (-not $usedTool) { + $sevenZip = Get-7ZipPath + if (-not $sevenZip) { + throw "No tar with xz support and no 7‑Zip found. Install Git for Windows (bsdtar) or 7‑Zip." + } + + $tempTar = [System.IO.Path]::ChangeExtension($tar_file, ".tar") + $tempXz = [System.IO.Path]::ChangeExtension($tar_file, ".xz") + if (Test-Path $tempTar) { Remove-Item -Force $tempTar } + if (Test-Path $tempXz) { Remove-Item -Force $tempXz } + + & $__w_log "7‑Zip: creating tar archive '$tempTar'" + Push-Location $archive_dir + try { + & "$sevenZip" a -bso0 -bse1 -ttar "$tempTar" "." + if ($LASTEXITCODE -ne 0) { throw "7z (create tar) failed with exit code $LASTEXITCODE" } + } finally { + Pop-Location + } + + & $__w_log "7‑Zip: compressing to XZ '$tempXz' (threads=$JOBS)" + & "$sevenZip" a -bso0 -bse1 -txz -mx=9 -mmt=$JOBS "$tempXz" "$tempTar" + if ($LASTEXITCODE -ne 0) { throw "7z (xz compress) failed with exit code $LASTEXITCODE" } + + Move-Item -Force "$tempXz" "$tar_file" + Remove-Item -Force "$tempTar" + $usedTool = "7z (tar + xz)" +} + +& $__w_log "Artifact created with: $usedTool" +& $__w_log "Artifact path: $tar_file" + +# copy to ARTIFACT_DIR +if ($env:ARTIFACT_DIR -and $env:ARTIFACT_DIR.Trim().Length -gt 0) { + $destDir = $env:ARTIFACT_DIR + if (-not (Test-Path $destDir)) { New-Item -ItemType Directory -Force -Path $destDir | Out-Null } + $destFile = Join-Path $destDir (Split-Path -Leaf $tar_file) + Copy-Item -Force "$tar_file" "$destFile" + & $__w_log "Artifact copied to $destFile" +} else { + & $__w_warn "Artifact left at $tar_file" +}