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:
1 parent
9678c27888
commit
1ec6443f14
1 file changed
+120
-17
+120
-17
@@ -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"
|
||||
Reference in new issue
Block a user