build.ps1 (368 lines of code) (raw):

Param ( [parameter(HelpMessage = "Clean existing build output")] [switch] $Clean, [parameter(HelpMessage = "Build the device discovery library only, do not build the Kubernetes device plugins or container images")] [switch] $LibraryOnly, [parameter(HelpMessage = "Build the Kubernetes device plugins only, do not build the device discovery library or container images")] [switch] $PluginsOnly, [parameter(HelpMessage = "Build container images for the Kubernetes device plugins")] [switch] $Images, [parameter(HelpMessage = "Build container images for example workloads")] [switch] $Examples, [parameter(HelpMessage = "The prefix used for image tags when building container images")] $TagPrefix = 'index.docker.io/tensorworks', [parameter(HelpMessage = "Override the repository version string for computing container image tag suffixes")] $Version = '' ) # Halt execution if we encounter an error $ErrorActionPreference = 'Stop' # Executes a command and throws an error if it returns a non-zero exit code function Run-Command($command) { # Print the command and execute it $formatted = If ($args.Count -gt 0) { "$command $args" } Else { "$command"} Write-Host "[$formatted]" -ForegroundColor DarkYellow & "$command" @args # If the command terminated with a non-zero exit code then throw an error if ($LastExitCode -ne 0) { throw "Command '$formatted' terminated with exit code $LastExitCode" } } # Invokes the Crane image management tool function Invoke-Crane { Run-Command go run 'github.com/google/go-containerregistry/cmd/crane@latest' @args } # Builds a container image using Crane function Build-ContainerImage { Param ( $BaseImage, $Directory, $Entrypoint, $ImageTag, $Files ) # Create a tarball with the specified files $tarball = "$env:Temp\layer-$([guid]::NewGuid()).tar" Run-Command tar.exe --create --verbose --file="$tarball" --directory="$Directory" @Files # Append the filesystem layer to the base image and set the entrypoint Invoke-Crane append --platform=windows/amd64 -b "$BaseImage" -f "$tarball" -t "$ImageTag" Invoke-Crane mutate "$ImageTag" --entrypoint="$Entrypoint" # Perform cleanup Remove-Item -Path "$tarball" -Force # Print the container image tag Write-Host "Built image: $ImageTag" -ForegroundColor Cyan } # Resolve the path to the directories used during the build process $buildDir = "$PSScriptRoot\build" $binDir = "$PSScriptRoot\bin" $examplesDir = "$PSScriptRoot\examples" $externalDir = "$PSScriptRoot\external" $vcpkgDir = "$externalDir\vcpkg" # Determine whether we are cleaning the build output if ($Clean) { # Remove the build directory if it exists if ((Test-Path -Path $buildDir) -eq $true) { Write-Host 'Removing the build directory...' -ForegroundColor Green Remove-Item -Path $buildDir -Recurse -Force } # Remove all .dll and .exe files in the bin directory Write-Host 'Removing binaries from the bin directory...' -ForegroundColor Green Remove-Item -Path "$binDir\*.dll" -Force Remove-Item -Path "$binDir\*.exe" -Force Exit } # Install vcpkg if we don't already have it if ((Test-Path -Path $vcpkgDir) -eq $false) { Write-Host "`nInstalling a local copy of vcpkg..." -ForegroundColor Green Run-Command git clone 'https://github.com/Microsoft/vcpkg.git' "$vcpkgDir" Run-Command "$vcpkgDir\bootstrap-vcpkg.bat" } # Install vswhere if we don't already have it $vsWhere = "$externalDir\vswhere.exe" if ((Test-Path -Path $vsWhere) -eq $false) { Write-Host "`nInstalling a local copy of vswhere..." -ForegroundColor Green (New-Object System.Net.WebClient).DownloadFile( 'https://github.com/microsoft/vswhere/releases/download/3.0.3/vswhere.exe', "$vsWhere" ) } # Install the NuGet CLI tool if we don't already have it $nuget = "$externalDir\nuget.exe" $nugetConfig = "$externalDir\NuGet.Config" if ((Test-Path -Path $nuget) -eq $false) { # Install the CLI tool Write-Host "`nInstalling a local copy of the NuGet CLI tool..." -ForegroundColor Green (New-Object System.Net.WebClient).DownloadFile( 'https://dist.nuget.org/win-x86-commandline/v6.2.1/nuget.exe', "$nuget" ) # Configure the CLI tool with the nuget.org source Set-Content -Path "$nugetConfig" -Value '<configuration></configuration>' -Force Run-Command "$nuget" sources add -Name 'nuget.org' -Source 'https://api.nuget.org/v3/index.json' -ConfigFile "$nugetConfig" Run-Command "$nuget" sources enable -Name 'nuget.org' -ConfigFile "$nugetConfig" } # Use vswhere to determine the version of Visual Studio that is installed (2019, 2022, etc.) $vsVersion = & "$vswhere" -latest -products * -requires Microsoft.Component.MSBuild -property 'catalog_productLineVersion' if (!$vsVersion) { throw "Failed to determine the version of Visual Studio" } # Determine the platform toolset version that corresponds to the Visual Studio version $toolsetVersions = @{ "2019" = "v142"; "2022" = "v143" } $platformToolset = $toolsetVersions[$vsVersion] if (!$platformToolset) { throw "Failed to determine the platform toolset version that corresponds to the version of Visual Studio" } # Use vswhere to locate MSBuild $msBuild = & "$vswhere" -latest -products * -requires Microsoft.Component.MSBuild -find 'MSBuild\**\Bin\MSBuild.exe' if (!$msBuild) { throw "Failed to locate MSBuild" } # Use vswhere to locate the MSBuild `BuildCustomizations` directory for the latest toolchain $vsCustomisations = & "$vswhere" -latest -products * -requires Microsoft.Component.MSBuild -find 'MSBuild\Microsoft\VC\*\BuildCustomizations' if (!$vsCustomisations) { throw "Failed to locate the MSBuild BuildCustomizations directory" } # If a version override was not specified then calculate it from the Git commit details if (!$Version) { # Set the version string to the commit hash $Version = & git rev-parse HEAD # Determine whether the current commit is a tagged release $gitTag = & git name-rev --name-only --tags HEAD if ($gitTag -ne 'undefined') { $Version = $gitTag } } # Report the detected values Write-Host "Repository version: $Version" -ForegroundColor Cyan Write-Host "Detected Visual Studio $vsVersion (platform toolset $platformToolset)" -ForegroundColor Cyan Write-Host "Found MSBuild: $msBuild" -ForegroundColor Cyan if (!$PluginsOnly) { # Create the build directory if it doesn't already exist if ((Test-Path -Path $buildDir) -eq $false) { Write-Host "`nCreating the build directory..." -ForegroundColor Green New-Item -Path $buildDir -ItemType Directory -Force | Out-Null } # Build the device discovery library (vcpkg will automatically install all required dependencies) Write-Host "`nBuilding the device discovery library..." -ForegroundColor Green Push-Location "$buildDir" Run-Command cmake "$PSScriptRoot/library" ` -A x64 -DVCPKG_TARGET_TRIPLET=x64-windows ` "-DCMAKE_INSTALL_PREFIX=$PSScriptRoot" ` "-DCMAKE_TOOLCHAIN_FILE=$vcpkgDir\scripts\buildsystems\vcpkg.cmake" Run-Command cmake --build . --target install --config Release Pop-Location } if (!$LibraryOnly) { # Build the Kubernetes device plugins and strip the debug symbols from the executables Write-Host "`nBuilding the Kubernetes device plugins..." -ForegroundColor Green Push-Location "$PSScriptRoot/plugins" $env:CGO_ENABLED=0 Run-Command go build -o "$PSScriptRoot\bin" -ldflags '-s -w' ./... Pop-Location } if (!$PluginsOnly -and !$LibraryOnly -and $Images) { # Use Crane to build the container image for the MCDM device plugin Write-Host "`nBuilding and pushing the container image for the MCDM device plugin..." -ForegroundColor Green Build-ContainerImage ` -ImageTag "$TagPrefix/mcdm-device-plugin:$Version" ` -BaseImage 'mcr.microsoft.com/windows/nanoserver:ltsc2022' ` -Files @('directx-device-discovery.dll', 'device-plugin-mcdm.exe') ` -Entrypoint 'device-plugin-mcdm.exe' ` -Directory $binDir # Use Crane to build the container image for the WDDM device plugin Write-Host "`nBuilding and pushing the container image for the WDDM device plugin..." -ForegroundColor Green Build-ContainerImage ` -ImageTag "$TagPrefix/wddm-device-plugin:$Version" ` -BaseImage 'mcr.microsoft.com/windows/nanoserver:ltsc2022' ` -Files @('directx-device-discovery.dll', 'device-plugin-wddm.exe') ` -Entrypoint 'device-plugin-wddm.exe' ` -Directory $binDir } if (!$PluginsOnly -and !$LibraryOnly -and $Examples) { # Use Crane to build the container image for the device discovery example Write-Host "`nBuilding and pushing the container image for the device discovery example..." -ForegroundColor Green Build-ContainerImage ` -ImageTag "$TagPrefix/example-device-discovery:$Version" ` -BaseImage 'mcr.microsoft.com/windows/servercore:ltsc2022' ` -Files @('directx-device-discovery.dll', 'test-device-discovery-cpp.exe') ` -Entrypoint 'C:\test-device-discovery-cpp.exe,--verbose' ` -Directory $binDir # Clone the DirectML repository if we don't already have a copy $directMLDir = "$externalDir\DirectML" $directMLCommit = '3c5a947e0e4f8115dd5dd2fea00ac545120052ac' if ((Test-Path -Path $directMLDir) -eq $false) { Write-Host "`nDownloading the DirectML repository..." -ForegroundColor Green New-Item -Path $directMLDir -ItemType Directory -Force | Out-Null Push-Location "$directMLDir" Run-Command git init Run-Command git remote add origin 'https://github.com/microsoft/DirectML.git' Run-Command git fetch --depth=1 origin "$directMLCommit" Run-Command git checkout "$directMLCommit" Pop-Location } # Build the HelloDirectML sample if it hasn't already been built $helloDirectMLDir = "$directMLDir\Samples\HelloDirectML" $helloDirectMLBin = "$helloDirectMLDir\HelloDirectML\x64\Release" $helloDirectMLExe = "$helloDirectMLBin\HelloDirectML.exe" if ((Test-Path -Path $helloDirectMLExe) -eq $false) { # Build the sample Write-Host "`nBuilding the HelloDirectML sample..." -ForegroundColor Green $env:_CL_='/MT' Push-Location "$helloDirectMLDir" Run-Command "$nuget" restore -ConfigFile "$nugetConfig" Run-Command "$msBuild" HelloDirectML.vcxproj ` /property:Configuration=Release ` /property:Platform=x64 ` "/property:PlatformToolset=$platformToolset" ` /property:WindowsTargetPlatformVersion=10.0 Pop-Location # Copy DirectML.dll from the NuGet package to the sample bin directory Copy-Item -Path "$helloDirectMLDir\packages\Microsoft.AI.DirectML.1.7.0\bin\x64-win\DirectML.dll" -Destination "$helloDirectMLBin" -Force } # Use Crane to build the container image for the DirectML example Write-Host "`nBuilding and pushing the container image for the DirectML example..." -ForegroundColor Green Build-ContainerImage ` -ImageTag "$TagPrefix/example-directml:$Version" ` -BaseImage 'mcr.microsoft.com/windows/servercore:ltsc2022' ` -Files @('DirectML.dll', 'HelloDirectML.exe') ` -Entrypoint 'C:\HelloDirectML.exe' ` -Directory $helloDirectMLBin # Clone the OpenCL SDK repository if we don't already have a copy $openCLSDK = "$externalDir\OpenCL-SDK" if ((Test-Path -Path $openCLSDK) -eq $false) { Write-Host "`nDownloading the OpenCL SDK repository..." -ForegroundColor Green Run-Command git clone -b 'v2022.05.18' --depth=1 --recursive 'https://github.com/KhronosGroup/OpenCL-SDK.git' "$openCLSDK" } # Build the enumopencl sample if it hasn't already been built $openCLBuild = "$openCLSDK\build" $openCLBin = "$openCLBuild\bin\Release" $enumOpenCL = "$openCLBin\enumopencl.exe" if ((Test-Path -Path $enumOpenCL) -eq $false) { # Create a vcpkg manifest file to install the dependencies for the OpenCL samples Set-Content -Force -Path "$openCLSDK\vcpkg.json" -Value '{"name":"opencl","version":"0.0.0","dependencies":["glm","sfml","tclap"]}' # Build the samples Write-Host "`nBuilding the enumopencl sample..." -ForegroundColor Green New-Item -Path $openCLBuild -ItemType Directory -Force | Out-Null Push-Location "$openCLBuild" Run-Command cmake "$openCLSDK" ` -A x64 -DVCPKG_TARGET_TRIPLET=x64-windows ` '-DCMAKE_CXX_FLAGS_RELEASE=/MT /O2 /Ob2 /DNDEBUG' ` '-DCMAKE_C_FLAGS_RELEASE=/MT /O2 /Ob2 /DNDEBUG' ` "-DCMAKE_INSTALL_PREFIX=$openCLSDK" ` "-DCMAKE_TOOLCHAIN_FILE=$vcpkgDir\scripts\buildsystems\vcpkg.cmake" ` -DBUILD_TESTING=OFF ` -DBUILD_DOCS=OFF ` -DBUILD_EXAMPLES=OFF ` -DBUILD_TESTS=OFF ` -DOPENCL_SDK_BUILD_SAMPLES=ON ` -DOPENCL_SDK_TEST_SAMPLES=OFF Run-Command cmake --build . --target enumopencl --config Release Pop-Location } # Use Crane to build the container image for the enumopencl example Write-Host "`nBuilding and pushing the container image for the enumopencl example..." -ForegroundColor Green Build-ContainerImage ` -ImageTag "$TagPrefix/example-opencl-enum:$Version" ` -BaseImage 'mcr.microsoft.com/windows/servercore:ltsc2022' ` -Files @('enumopencl.exe') ` -Entrypoint 'C:\enumopencl.exe' ` -Directory $openCLBin # Determine whether the CUDA Toolkit v11.6 is installed if ($env:CUDA_PATH_V11_6) { # Copy the Visual Studio integration files from the CUDA Toolkit to the MSBuild `BuildCustomizations` directory Copy-Item -Path "$env:CUDA_PATH\extras\visual_studio_integration\MSBuildExtensions\*" -Destination "$vsCustomisations" -Force # Clone the CUDA samples repository if we don't already have a copy $cudaSamples = "$externalDir\cuda-samples" $cudaSamplesBin = "$cudaSamples\bin\win64\Release" if ((Test-Path -Path $cudaSamples) -eq $false) { Write-Host "`nDownloading the CUDA samples repository..." -ForegroundColor Green Run-Command git clone -b 'v11.6' --depth=1 'https://github.com/NVIDIA/cuda-samples.git' "$cudaSamples" } # Build the CUDA deviceQuery sample if it hasn't already been built $deviceQuery = "$cudaSamplesBin\deviceQuery.exe" if ((Test-Path -Path $deviceQuery) -eq $false) { Write-Host "`nBuilding the CUDA deviceQuery sample..." -ForegroundColor Green Run-Command "$msBuild" "$cudaSamples\Samples\1_Utilities\deviceQuery\deviceQuery_vs${vsVersion}.sln" /property:Configuration=Release } # Build the CUDA MC_EstimatePiP sample if it hasn't already been built $monteCarlo = "$cudaSamplesBin\MC_EstimatePiP.exe" if ((Test-Path -Path $monteCarlo) -eq $false) { # Build the sample Write-Host "`nBuilding the CUDA MC_EstimatePiP sample..." -ForegroundColor Green Run-Command "$msBuild" "$cudaSamples\Samples\2_Concepts_and_Techniques\MC_EstimatePiP\MC_EstimatePiP_vs${vsVersion}.sln" /property:Configuration=Release # Copy curand64_10.dll from the CUDA Toolkit bin directory to the sample bin directory Copy-Item -Path "$env:CUDA_PATH_V11_6\bin\curand64_10.dll" -Destination "$cudaSamplesBin" -Force } # Use Crane to build the container image for the CUDA deviceQuery example Write-Host "`nBuilding and pushing the container image for the CUDA deviceQuery example..." -ForegroundColor Green Build-ContainerImage ` -ImageTag "$TagPrefix/example-cuda-devicequery:$Version" ` -BaseImage 'mcr.microsoft.com/windows/servercore:ltsc2022' ` -Files @('deviceQuery.exe') ` -Entrypoint 'C:\deviceQuery.exe' ` -Directory $cudaSamplesBin # Use Crane to build the container image for the CUDA MC_EstimatePiP example Write-Host "`nBuilding and pushing the container image for the CUDA MC_EstimatePiP example..." -ForegroundColor Green Build-ContainerImage ` -ImageTag "$TagPrefix/example-cuda-montecarlo:$Version" ` -BaseImage 'mcr.microsoft.com/windows/servercore:ltsc2022' ` -Files @('curand64_10.dll', 'MC_EstimatePiP.exe') ` -Entrypoint 'C:\MC_EstimatePiP.exe' ` -Directory $cudaSamplesBin } else { Write-Host "`nCUDA Toolkit v11.6 was not detected, not building CUDA examples" -ForegroundColor Cyan } # Install FFmpeg if we don't already have it $ffmpegDir = "$externalDir\ffmpeg" if ((Test-Path -Path $ffmpegDir) -eq $false) { # Download the FFmpeg release archive Write-Host "`nInstalling a local copy of FFmpeg..." -ForegroundColor Green $ffmpegZip = "$externalDir\ffmpeg.zip" (New-Object System.Net.WebClient).DownloadFile( 'https://www.gyan.dev/ffmpeg/builds/packages/ffmpeg-5.1.2-essentials_build.zip', "$ffmpegZip" ) # Extract the archive Expand-Archive -Path "$ffmpegZip" -DestinationPath "$ffmpegDir" -Force } # Download a sample video for use with FFmpeg if we don't already have it $ffmpegBin = "$ffmpegDir\ffmpeg-5.1.2-essentials_build\bin" $sampleVideo = "$ffmpegBin\sample-video.mp4" if ((Test-Path -Path $sampleVideo) -eq $false) { Write-Host "`nDownloading a sample video for use with FFmpeg..." -ForegroundColor Green (New-Object System.Net.WebClient).DownloadFile( 'https://raw.githubusercontent.com/SPBTV/video_av1_samples/master/spbtv_sample_bipbop_av1_960x540_25fps.mp4', "$sampleVideo" ) } # Use Crane to build the container image for the FFmpeg examples Write-Host "`nBuilding and pushing the container image for the FFmpeg examples..." -ForegroundColor Green Copy-Item -Path "$examplesDir\ffmpeg-autodetect\autodetect-encoder.ps1" -Destination "$ffmpegBin" -Force Build-ContainerImage ` -ImageTag "$TagPrefix/example-ffmpeg:$Version" ` -BaseImage 'mcr.microsoft.com/windows/server:ltsc2022' ` -Files @('ffmpeg.exe', 'sample-video.mp4', 'autodetect-encoder.ps1') ` -Entrypoint 'C:\ffmpeg.exe' ` -Directory "$ffmpegBin" }