build: téléchargement CUDA avec reprise et vérification SHA256

L'installateur (~2,7 Go) est téléchargé par curl -C - dans un cache local et reprend après interruption ou relance du script ; URL et SHA256 lus dans le manifeste winget ; options -DryRun et -DownloadOnly ; SHA256 calculé via .NET.
This commit is contained in:
Ange-Marie MAURIN - A2M Systèmes committed 2026-11-06 19:36:18 +01:00
1 parent 9678c27888
commit 1ec6443f14
1 file changed
+120 -17
+120 -17
View File
@@ -1,22 +1,29 @@
# SPDX-License-Identifier: MPL-2.0
#
# Installe le CUDA Toolkit NVIDIA via winget, pour le prototype prototypes/gpu_interop
# Installe le CUDA Toolkit NVIDIA, pour le prototype prototypes/gpu_interop
# (etapes 2 et suivantes). CUDA est un composant proprietaire : il reste un plugin
# facultatif de SEQUA (docs, par. 10.2) et sa licence est acceptee par l'utilisateur
# lui-meme pendant l'installation (pas d'acceptation automatique ici).
# lui-meme dans l'installateur NVIDIA (pas d'acceptation automatique ici).
#
# A lancer dans une fenetre PowerShell externe (installation longue, demande UAC) :
# powershell -ExecutionPolicy Bypass -File scripts\install-cuda.ps1 -DryRun # verifier sans installer
# powershell -ExecutionPolicy Bypass -File scripts\install-cuda.ps1 # installer
# powershell -ExecutionPolicy Bypass -File scripts\install-cuda.ps1 -Version 13.5
# L'installateur (~2,8 Go) est telecharge avec reprise : si le telechargement est
# interrompu, relancer simplement le script, il repart du dernier octet recu.
# L'URL et le SHA256 viennent du manifeste winget officiel (Nvidia.CUDA).
#
# A lancer dans une fenetre PowerShell externe (telechargement long, UAC) :
# powershell -ExecutionPolicy Bypass -File scripts\install-cuda.ps1 -DryRun # verifier sans rien faire
# powershell -ExecutionPolicy Bypass -File scripts\install-cuda.ps1 -DownloadOnly # telecharger seulement
# powershell -ExecutionPolicy Bypass -File scripts\install-cuda.ps1 # telecharger puis installer
#
# Messages en ASCII : compatible Windows PowerShell 5.1 sans BOM.
[CmdletBinding()]
param(
[string]$Version = "13.5",
[string]$CacheDir = (Join-Path $env:LOCALAPPDATA "SEQUA\downloads\cuda"),
[switch]$DryRun,
[switch]$Force
[switch]$DownloadOnly,
[switch]$Force,
[int]$MaxAttempts = 50
)
$ErrorActionPreference = "Stop"
@@ -48,6 +55,66 @@ function Get-Winget {
throw "winget introuvable. Installer 'App Installer' depuis le Microsoft Store."
}
# Lit l'URL et le SHA256 de l'installateur dans le manifeste winget
# (analyse independante de la langue : on cherche l'URL .exe et une empreinte de 64 hex).
function Get-InstallerInfo([string]$winget, [string]$version) {
$lines = & $winget show --id Nvidia.CUDA --version $version --exact --source winget --accept-source-agreements 2>&1
if ($LASTEXITCODE -ne 0) { throw "Version $version introuvable dans winget (winget show --id Nvidia.CUDA --versions)." }
$text = $lines -join "`n"
$url = [regex]::Match($text, 'https://\S+?\.exe').Value
$sha = [regex]::Match($text, '\b[0-9a-fA-F]{64}\b').Value
if (-not $url -or -not $sha) { throw "URL ou SHA256 de l'installateur absents du manifeste winget." }
[pscustomobject]@{ Url = $url; Sha256 = $sha.ToUpperInvariant() }
}
# SHA256 via .NET : Get-FileHash manque dans certains Windows PowerShell 5.1
# (PSModulePath pointant vers les modules de PowerShell 7).
function Get-Sha256([string]$path) {
$stream = [System.IO.File]::OpenRead($path)
$sha = [System.Security.Cryptography.SHA256]::Create()
try {
([System.BitConverter]::ToString($sha.ComputeHash($stream))).Replace("-", "")
}
finally {
$sha.Dispose()
$stream.Dispose()
}
}
function Get-RemoteSize([string]$url) {
$headers = & curl.exe -sIL --fail $url
if ($LASTEXITCODE -ne 0) { throw "Serveur injoignable : $url" }
$length = $headers | Select-String -Pattern '^Content-Length:\s*(\d+)' | Select-Object -Last 1
if (-not $length) { throw "Taille du fichier inconnue (pas de Content-Length)." }
[int64]$length.Matches[0].Groups[1].Value
}
# Telechargement avec reprise : curl -C - repart de la taille du fichier .part.
function Invoke-ResumableDownload([string]$url, [string]$destination, [int64]$expectedSize, [int]$maxAttempts) {
$part = "$destination.part"
for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) {
$have = if (Test-Path $part) { (Get-Item $part).Length } else { 0 }
if ($have -eq $expectedSize) { break }
if ($have -gt $expectedSize) {
Write-Host " Fichier partiel plus grand que prevu : on recommence." -ForegroundColor Yellow
Remove-Item $part -Force
$have = 0
}
$pct = [math]::Round(100.0 * $have / $expectedSize, 1)
Write-Host (" Tentative {0}/{1} : {2:N0} / {3:N0} octets ({4} %)" -f $attempt, $maxAttempts, $have, $expectedSize, $pct)
& curl.exe -L --fail -C - --retry 5 --retry-delay 5 --retry-all-errors --speed-limit 1024 --speed-time 60 -o $part $url
if ($LASTEXITCODE -ne 0) {
Write-Host " curl interrompu (code $LASTEXITCODE), reprise dans 10 s..." -ForegroundColor Yellow
Start-Sleep -Seconds 10
}
}
$final = if (Test-Path $part) { (Get-Item $part).Length } else { 0 }
if ($final -ne $expectedSize) {
throw "Telechargement incomplet apres $maxAttempts tentatives ($final / $expectedSize octets). Relancer le script pour reprendre."
}
Move-Item $part $destination -Force
}
# --- Verifications ----------------------------------------------------------
Write-Step "Pilote NVIDIA"
$driverCuda = Get-DriverCudaVersion
@@ -71,22 +138,57 @@ if ($same -and -not $Force) {
exit 0
}
$winget = Get-Winget
Write-Step "Paquet winget Nvidia.CUDA $Version"
& $winget show --id Nvidia.CUDA --version $Version --exact --source winget --accept-source-agreements |
Select-String -Pattern '^(Found|Trouv|Version|Publisher|Editeur|License|Licence|Installer Url|URL)' |
ForEach-Object { Write-Host " $($_.Line.Trim())" }
if ($LASTEXITCODE -ne 0) { throw "Version $Version introuvable dans winget (winget show --id Nvidia.CUDA --versions)." }
Write-Step "Manifeste winget Nvidia.CUDA $Version"
$info = Get-InstallerInfo (Get-Winget) $Version
$size = Get-RemoteSize $info.Url
$fileName = [System.IO.Path]::GetFileName(([uri]$info.Url).AbsolutePath)
$installer = Join-Path $CacheDir $fileName
Write-Host " URL : $($info.Url)"
Write-Host " SHA256 : $($info.Sha256)"
Write-Host (" Taille : {0:N1} Go" -f ($size / 1GB))
Write-Host " Cache : $installer"
if ($DryRun) {
Write-Host "DryRun : aucune installation effectuee." -ForegroundColor Yellow
$partial = "$installer.part"
if (Test-Path $installer) { Write-Host " Installateur deja telecharge." }
elseif (Test-Path $partial) { Write-Host (" Telechargement partiel : {0:N0} octets." -f (Get-Item $partial).Length) }
Write-Host "DryRun : rien n'a ete telecharge ni installe." -ForegroundColor Yellow
exit 0
}
# --- Telechargement ---------------------------------------------------------
New-Item -ItemType Directory -Force -Path $CacheDir | Out-Null
if (Test-Path $installer) {
Write-Step "Installateur deja present dans le cache"
}
else {
$drive = Get-PSDrive -Name ([System.IO.Path]::GetPathRoot($CacheDir).Substring(0, 1))
if ($drive.Free -lt ($size * 2)) {
throw ("Espace disque insuffisant sur {0}: ({1:N1} Go libres, {2:N1} Go conseilles)." -f $drive.Name, ($drive.Free / 1GB), ($size * 2 / 1GB))
}
Write-Step "Telechargement avec reprise"
Invoke-ResumableDownload $info.Url $installer $size $MaxAttempts
}
Write-Step "Verification SHA256"
$hash = Get-Sha256 $installer
if ($hash -ne $info.Sha256) {
Remove-Item $installer -Force
throw "SHA256 incorrect ($hash) : fichier supprime, relancer le script pour le retelecharger."
}
Write-Host " OK"
if ($DownloadOnly) {
Write-Host "Installateur pret : $installer" -ForegroundColor Green
exit 0
}
# --- Installation -----------------------------------------------------------
Write-Step "Installation (UAC et acceptation de la licence NVIDIA demandees)"
& $winget install --id Nvidia.CUDA --version $Version --exact --source winget --accept-source-agreements --interactive
if ($LASTEXITCODE -ne 0) { throw "winget install a echoue (code $LASTEXITCODE)." }
Write-Host " Choisir l'installation PERSONNALISEE et decocher tout composant pilote graphique" -ForegroundColor Yellow
Write-Host " s'il est propose, pour conserver le pilote actuel." -ForegroundColor Yellow
$process = Start-Process -FilePath $installer -Wait -PassThru
if ($process.ExitCode -ne 0) { throw "L'installateur NVIDIA a retourne le code $($process.ExitCode)." }
# --- Verification -----------------------------------------------------------
Write-Step "Verification"
@@ -99,5 +201,6 @@ if (-not $nvcc -or -not (Test-Path $nvcc)) {
}
& $nvcc --version
Write-Host ""
Write-Host "CUDA installe. Ouvrir un NOUVEAU terminal (PATH et CUDA_PATH mis a jour), puis :" -ForegroundColor Green
Write-Host "CUDA installe. L'installateur peut etre supprime du cache : $installer" -ForegroundColor Green
Write-Host "Ouvrir un NOUVEAU terminal (PATH et CUDA_PATH mis a jour), puis :"
Write-Host " .\scripts\build.ps1 -Preset windows-msvc-prototypes"