# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. set-strictmode -version latest $global:_init_path = "${env:PWD}" $global:_git_branch = $null $global:_local = $null $global:_local_srcdir = $null $global:_repository_root = $null $global:_verbosity = $null $global:colors = @{ error = 'Red' high = 'Cyan' low = 'DarkGray' medium = 'DarkBlue' test = @{ failed = 'Red' passed = 'Green' } title = 'Blue' warning = 'Yellow' } function cleanup_after { write-debug "" $(reset_environment) } function configure_debug([bool] $enabled) { write-debug " enabled = '${enabled}'." if ($enabled) { # Notify user if any environment variables which could affect the build outcome are set prior to the build script running. $overrides = @() foreach ($entry in $(& get-childitem env:)) { # We're only looking for environment variables which are used directly by the build scripts (starts with 'NVBUILD_`); # and we're looking at environment variables which would indirectly affect the build scripts (i.e. `PATH`). if ($entry.key.startswith('NVBUILD_')) { # No reason to display values which are displayed when the build start, often time provided by the user. if ($entry.key.endswith('_COMMAND') -or $entry.key.endswith('_VERBOSITY')) { continue } $overrides += $entry } } if ($overrides.count -gt 0) { write-low ' Overriding environment variables:' foreach ($entry in $overrides) { write-low " $($entry.key) = $($entry.Value)" } } } } function create_directory([string] $path, [switch] $recreate) { write-debug " path = '${path}'." write-debug " recreate = ${recreate}" $path_local = $(to_local_path $path) write-debug " path_local = '${path_local}'." if (test-path $path_local -pathType Container) { if ($recreate) { remove-item $path_local -Recurse | out-null new-item $path_local -itemtype Directory | out-null } } else { new-item $path_local -itemtype Directory | out-null } } function default_git_branch { if (is_installed 'git') { $value = "$(git branch --show-current)" } else { $value = 'main' } write-debug " -> '${value}'." return $value } function default_local_srcdir { $value = $(& git rev-parse --show-toplevel) write-debug " -> '${value}'." return $value; } function default_verbosity { $value = 'NORMAL' write-debug " -> '${value}'." return $value } function env_get_git_branch { $value = $env:NVBUILD_GIT_BRANCH write-debug " -> '${value}'." return $value } function env_get_local_srcdir { $value = $env:NVBUILD_LOCAL_SRCDIR write-debug " -> '${value}'." return $value } function env_get_verbosity { $value = $env:NVBUILD_VERBOSITY write-debug " -> '${value}'." return $value } function env_set_git_branch([string] $value) { if ($null -eq $env:NVBUILD_NOSET) { write-debug " value: '${value}'." $env:NVBUILD_GIT_BRANCH = $value } } function env_set_local_srcdir([string] $value) { if ($null -eq $env:NVBUILD_NOSET) { write-debug " value: '${value}'." $env:NVBUILD_LOCAL_SRCDIR = $value } } function env_set_verbosity([string] $value) { if ($null -eq $env:NVBUILD_NOSET) { write-debug " value: '${value}'." $env:NVBUILD_VERBOSITY = $value } } function fatal_exit([string] $message) { write-error "fatal: ${message}" exit 1 } function get_git_branch { if ($null -eq $global:_git_branch) { $value = $(env_set_git_branch) if ($null -ne $value) { set_git_branch $value } else { set_git_branch $(default_git_branch) } } write-debug " -> '${global:_git_branch}'." return $global:_git_branch } function get_local_srcdir { if ($null -eq $global:_local_srcdir) { $value = $(env_get_local_srcdir) if ($null -ne $value) { set_local_srcdir $value } else { set_local_srcdir $(default_local_srcdir) } } write-debug " -> '${global:_local_srcdir}'." return $global:_local_srcdir } function get_repository_root { if ($null -eq $global:_repository_root) { $path = $(& git rev-parse --show-toplevel) $global:_repository_root = $(normalize_path $path) } write-debug " '${global:_repository_root}'." return $global:_repository_root } function get_verbosity { if ($null -eq $global:_verbosity) { $value = $(env_get_verbosity) if ($null -ne $value) { set_verbosity $value } else { set_verbosity $(default_verbosity) } } write-debug " -> '${global:_verbosity}'." return $global:_verbosity } function is_debug { $value = $($null -ne $env:NVBUILD_DEBUG_TRACE) write-debug " -> ${value}." return $value } function is_empty([string] $value) { return [System.String]::IsNullOrWhiteSpace($value) } function is_git_ignored([string] $path) { $repo_root = $(get_repository_root) if ($path.startswith($repo_root)) { $path = $path.substring($repo_root.length) } if ($path.startswith('/')) { $path = $path.substring(1) } $result = $(& git check-ignore $path) return (0 -eq $result) } function is_installed([string] $command) { write-debug " command = '${command}'." $out = $null -ne $(get-command "${command}" -errorAction SilentlyContinue) write-debug " -> ${out}." return $out } function is_tty { return -not(([System.Console]::IsOutputRedirected) -or ([System.Console]::IsErrorRedirected)) } function is_verbosity_valid([string] $value) { return (('NORMAL' -eq $value) -or ('MINIMAL' -eq $value) -or ('DETAILED' -eq $value)) } function normalize_path([string] $path) { write-debug " path: '${path}'." $out = "$(resolve-path "${path}" -erroraction 'Ignore')" if (($null -eq $out) -or ($out.length -eq 0)) { if ($path.startswith($(get_repository_root))) { $out = $path } else { $out = "$(get_repository_root)/${path}" } } if ($IsWindows) { if ($out -match "^[A-Z]:") { $out = $out.substring(2) } $out = $out.replace('\', '/') } write-debug " '${path}' -> '${out}'." return $out } function read_content([string] $path, [switch] $lines, [switch] $bytes) { if (is_empty $path -or ($lines -and $bytes)) { write-error 'usage: read_content {path} [(-bytes|-lines)]' -category InvalidArgument write-error ' {path} file system path of the file to read contents from.' write-error ' -bytes when provided content is returned as an array of bytes. mutually exclusive with -lines.' write-error ' -lines when provided content is returned as an array of strings. mutually exclusive with -bytes.' write-error ' ' usage_exit 'read_content {path} [(-bytes|-lines)]' } write-debug " path: '${path}'." write-debug " bytes: ${bytes}." write-debug " lines: ${lines}." $path = normalize_path $path if ($bytes) { return get-content -path $path -asbytestream -raw } if ($lines) { return get-content -path $path } return get-content -path $path -raw } function reset_environment { write-debug "" $overrides = @() foreach ($entry in $(& get-childitem env:)) { # We're only looking for environment variables which are used directly by the build scripts (starts with 'NVBUILD_`); # and we're looking at environment variables which would indirectly affect the build scripts (i.e. `PATH`). if ($entry.key.startswith('NVBUILD_')) { $overrides += $entry } } if ($overrides.count -gt 0) { foreach ($entry in $overrides) { $expression = '$env:' + "$($entry.Key)" + ' = $null' invoke-expression "${expression}" if ("$($entry.Key)" -ne 'NVBUILD_NOSET') { write-debug " removed '$($entry.Key)'." } } } } function run([string] $command) { if ($null -eq $command) { write-error 'usage: run {command}' -category InvalidArgument write-error ' {command} is the command to execute.' write-error ' ' usage_exit 'run {command}' } write-debug " command = '${command}'." if ('MINIMAL' -ne $(get_verbosity)) { write-high "${command}" } invoke-expression "${command}" | out-default $exit_code = $LASTEXITCODE write-debug " exit_code = ${exit_code}." if ($exit_code -ne 0) { write-error "fatal: Command ""${command}"" failed, returned ${exit_code}." -category fromStdErr exit $exit_code } } function set_git_branch([string] $value) { write-debug " value = '${value}'." $global:_git_branch = $value env_set_git_branch $value } function set_local_srcdir([string] $value) { write-debug " value: '${value}'." $global:_local_srcdir = $value env_set_local_srcdir $value } function set_verbosity([string] $value) { write-debug " '${value}'." if (-not(is_verbosity_valid $value)) { throw "Invalid verbosity value '${value}'." } $global:_verbosity = $value env_set_verbosity $value } function to_local_path([string] $path) { write-debug " path: '${path}'." if ($null -eq $path) { return $(get_local_srcdir) } $out = $path.trim() $out = $out.trim('/','\') $out = join-path $(get_local_srcdir) $out $out = $(normalize_path $out) return $out } function typeof($object) { if ($null -eq $object) { return 'null' } return $object.gettype().name } function usage_exit([string] $message) { write-error "usage: $message" exit 254 } function value_or_default([string] $value, [string] $default) { if (($null -eq $value) -or ($value.Length -eq 0)) { return $default } return $value } function write_content([string] $content, [string] $path, [switch] $overwrite) { if (($null -eq $path) -or ($path.length -eq 0)) { write-error 'usage: write_content {content} {path}' write-error ' {content} is the content to be written to a file.' write-error ' {path} is the path to file into which to write content.' usage_exit 'write_content {content} {path}' } write-debug " content = $($content.length) bytes." write-debug " path = '${path}'." $path_local = normalize_path $path write-debug " '${path_local}'." if ($null -eq $content) { $content = '' } if ($overwrite -and (test-path $path_local)) { remove-item $path_local | out-null } $content | out-file $path_local } function __write([string] $value, [string] $color, [bool] $no_newline) { if (is_tty) { $opts = @{ NoNewline = $no_newline } if (($null -ne $color) -and ($color.length -gt 0)) { $opts.ForegroundColor = $color } write-host $value @opts } else { if (-not($no_newline)) { $value = "${value}`n" } write-output $value } } function write-detailed { param([string] $value, [string] $color = $null, [switch] $no_newline) if ('DETAILED' -eq $(get_verbosity)) { __write $value $color $no_newline } } function write-error([string] $value) { $opts = @{ color = $global:colors.error no_newline = $false } write-minimal $value @opts } function write-failed([string] $value) { if (is_tty) { write-normal ' [Failed]' $global:colors.test.failed -no_newline write-normal " ${value}" } else { write-output " Test: [Failed] ${value}" } } function write-high { param([string] $value, [switch] $no_newline) $opts = @{ color = $global:colors.high no_newline = $no_newline } write-minimal $value @opts } function write-low { param([string] $value, [switch] $no_newline) $opts = @{ color = $global:colors.low no_newline = $no_newline } write-detailed $value @opts } function write-medium { param([string] $value, [switch] $no_newline) $opts = @{ color = $global:colors.medium no_newline = $no_newline } write-normal $value @opts } function write-minimal { param([string] $value, [string] $color = $null, [switch] $no_newline) __write $value $color $no_newline } function write-normal { param([string] $value, [string] $color = $null, [switch] $no_newline) if ('MINIMAL' -ne $(get_verbosity)) { $opts = @{ color = $color no_newline = $no_newline } __write $value @opts } } function write-passed([string] $value) { if (is_tty) { write-detailed ' [Passed]' $global:colors.test.passed -no_newline write-detailed " ${value}" } else { write-output " Test: [Passed] ${value}" } } function write-title([string] $value) { write-minimal $value $global:colors.title } function write-warning([string] $value) { write-minimal $value $global:colors.warning }