mirror of
https://github.com/apache/nuttx.git
synced 2025-12-06 09:01:15 +08:00
512 lines
14 KiB
PowerShell
512 lines
14 KiB
PowerShell
#!/usr/bin/env pswd
|
|
############################################################################
|
|
# tools/testbuild.ps1
|
|
# PowerShell script for CI on Windows Native
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
# contributor license agreements. See the NOTICE file distributed with
|
|
# this work for additional information regarding copyright ownership. The
|
|
# ASF licenses this file to you 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-PSDebug -Trace 0
|
|
|
|
$progname = $($MyInvocation.MyCommand.Name)
|
|
|
|
$WD = Resolve-Path("Get-Location\..\..\..\..")
|
|
$nuttx = "$WD\nuttx"
|
|
$global:fail = 0
|
|
$APPSDIR = "$WD\apps"
|
|
|
|
if ($null -eq $ARTIFACTDIR) {
|
|
$ARTIFACTDIR = "$WD\buildartifacts"
|
|
}
|
|
|
|
$PRINTLISTONLY = 0
|
|
$GITCLEAN = 0
|
|
$SAVEARTIFACTS = 0
|
|
$CHECKCLEAN = 1
|
|
$CODECHECKER = 0
|
|
$NINJACMAKE = 0
|
|
$RUN = 0
|
|
$MSVC = 0
|
|
|
|
function showusage {
|
|
Write-Host ""
|
|
Write-Host "USAGE: $progname -h [-n] [-A] [-G] [-N]"
|
|
Write-Host "Where:"
|
|
Write-Host " -h will show this help test and terminate"
|
|
Write-Host " -n selects Windows native"
|
|
Write-Host " -p only print the list of configs without running any builds"
|
|
Write-Host " -A store the build executable artifact in ARTIFACTDIR (defaults to ../buildartifacts"
|
|
Write-Host " -C Skip tree cleanness check."
|
|
Write-Host " -G Use `"git clean -xfdq`" instead of `"make distclean`" to clean the tree."
|
|
Write-Host " -N Use CMake with Ninja as the backend."
|
|
Write-Host " <testlist-file> selects the list of configurations to test. No default"
|
|
Write-Host ""
|
|
exit 1
|
|
}
|
|
|
|
# Define a function to search for Visual Studio 2022 installation
|
|
function Find-VisualStudio {
|
|
|
|
# Check common installation paths
|
|
$commonPaths = @(
|
|
"C:\Program Files\Microsoft Visual Studio\2022\Community",
|
|
"C:\Program Files\Microsoft Visual Studio\2022\Professional",
|
|
"C:\Program Files\Microsoft Visual Studio\2022\Enterprise"
|
|
)
|
|
|
|
foreach ($path in $commonPaths) {
|
|
if (Test-Path $path) {
|
|
$MSVC = 1
|
|
}
|
|
}
|
|
|
|
if ($MSVC -eq 1) {
|
|
Write-Host "Found Visual Studio 2022 installations"
|
|
return $MSVC = 1
|
|
}
|
|
else {
|
|
Write-Host "Visual Studio 2022 is not installed on this system."
|
|
return $MSVC = 0
|
|
}
|
|
|
|
}
|
|
|
|
$MSVC = Find-VisualStudio
|
|
|
|
if (!$args[0]) {
|
|
showusage
|
|
}
|
|
for ( $i = 0; $i -lt $args.count; $i++ ) {
|
|
switch -regex -casesensitive ($($args[$i])) {
|
|
'-h' {
|
|
showusage
|
|
}
|
|
'-p' {
|
|
$PRINTLISTONLY = 1
|
|
}
|
|
'-G' {
|
|
$GITCLEAN = 1
|
|
}
|
|
'-A' {
|
|
$SAVEARTIFACTS = 1
|
|
}
|
|
'-C' {
|
|
$CHECKCLEAN = 0
|
|
}
|
|
'-N' {
|
|
$NINJACMAKE = 1
|
|
}
|
|
default {
|
|
Write-Host "File $($args[$i])" -ForegroundColor Green
|
|
$testfile = $($args[$i])
|
|
}
|
|
}
|
|
}
|
|
|
|
# Check if testfile file exists
|
|
if (-not (Test-Path -Path "$testfile")) {
|
|
Write-Host "ERROR: Missing test list file" -ForegroundColor Red
|
|
showusage
|
|
}
|
|
# Check if nuttx directory exists
|
|
if (-Not (Test-Path -Path $nuttx)) {
|
|
Write-Host "ERROR: Expected to find nuttx/ at $nuttx" -ForegroundColor Red
|
|
showusage
|
|
}
|
|
|
|
# Check if apps directory exists
|
|
if (-Not (Test-Path -Path $APPSDIR)) {
|
|
Write-Host "ERROR: No directory found at $APPSDIR" -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
|
|
$patternallitem = '^(-|\\)|^[C|c][M|m][A|a][K|k][E|e]'
|
|
|
|
$patterntestlist = '^\\'
|
|
|
|
$patternblacklist = '^-'
|
|
|
|
if ($NINJACMAKE -eq 1) {
|
|
$patterncmakelist = '^[C|c][M|m][A|a][K|k][E|e][,]'
|
|
}
|
|
|
|
$content = Get-Content .\$testfile
|
|
$content = $content -replace '/', '\'
|
|
|
|
Set-Location "$nuttx"
|
|
|
|
$listfull = $content | Select-String $patternallitem -AllMatches
|
|
|
|
$testlist = $listfull | Select-String $patterntestlist -AllMatches
|
|
|
|
$blacklist = $listfull | Select-String $patternblacklist -AllMatches
|
|
|
|
if ($NINJACMAKE -eq 1) {
|
|
$cmakelist = $listfull | Select-String $patterncmakelist -AllMatches
|
|
}
|
|
|
|
# Clean up after the last build
|
|
function distclean {
|
|
Write-Host " Cleaning..."
|
|
if ((Test-Path ".config") -or (Test-Path "build\.config")) {
|
|
if (($GITCLEAN -eq 1) -or ($cmake)) {
|
|
git -C $nuttx clean -xfdq
|
|
git -C $APPSDIR clean -xfdq
|
|
}
|
|
else {
|
|
# Remove .version manually because this file is shipped with
|
|
# the release package and then distclean has to keep it.
|
|
if ($CHECKCLEAN -ne 0) {
|
|
if ((Test-Path -Path "$nuttx\.git") -or (Test-Path -Path "$APPSDIR\.git")) {
|
|
try {
|
|
if (git -C $nuttx status --ignored -s 2>$null) {
|
|
git -C $nuttx status --ignored -s
|
|
$global:fail = 1
|
|
}
|
|
if (git -C $APPSDIR status --ignored -s 2>$null) {
|
|
git -C $APPSDIR status --ignored -s
|
|
$global:fail = 1
|
|
}
|
|
}
|
|
catch {
|
|
Write-Host "Git is not installed. Please install Git to use this script." -ForegroundColor Red
|
|
$global:fail = 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function run_command ($command) {
|
|
invoke-expression "$command" *>$null
|
|
Write-Host "run_command $_"
|
|
return $_
|
|
}
|
|
|
|
function configure_cmake {
|
|
# Run CMake with specified configurations
|
|
|
|
try {
|
|
$tmpconfig = $config -replace '\\', ':'
|
|
|
|
# cmake -B vs2022 -DBOARD_CONFIG=sim/windows -G"Visual Studio 17 2022" -A Win32
|
|
# cmake --build vs2022
|
|
if (($tmpconfig -match "windows") -and ($MSVC -eq 1)) {
|
|
if (cmake -B build -DBOARD_CONFIG="$tmpconfig" -G"Visual Studio 17 2022" -A Win32 1>$null) {
|
|
cmake -B build -DBOARD_CONFIG="$tmpconfig" -G"Visual Studio 17 2022" -A Win32
|
|
$global:fail = 1
|
|
}
|
|
}
|
|
else {
|
|
if (cmake -B build -DBOARD_CONFIG="$tmpconfig" -GNinja 1>$null) {
|
|
cmake -B build -DBOARD_CONFIG="$tmpconfig" -GNinja
|
|
Write-Host "cmake -B build -DBOARD_CONFIG=$tmpconfig -GNinja"
|
|
$global:fail = 1
|
|
}
|
|
}
|
|
Write-Host " CMake configuration completed successfully."
|
|
}
|
|
catch {
|
|
Write-Host " CMake configuration failed: $_"
|
|
$global:fail = 1
|
|
}
|
|
|
|
if ($toolchain) {
|
|
$patternallitem = '_TOOLCHAIN_'
|
|
$contentconfig = Get-Content "$nuttx\build\.config"
|
|
|
|
$listtoolchain = $contentconfig | Select-String $patternallitem -AllMatches
|
|
$listtoolchain = $listtoolchain | Select-String 'CONFIG_TOOLCHAIN_WINDOWS', 'CONFIG_ARCH_TOOLCHAIN_*' -NotMatch | Select-String '=y' -AllMatches
|
|
$toolchainarr = $listtoolchain -split '='
|
|
$original_toolchain = $($toolchainarr[0])
|
|
|
|
if ($original_toolchain) {
|
|
Write-Host " Disabling $original_toolchain"
|
|
kconfig-tweak.ps1 --file "$nuttx\build\.config" -d $original_toolchain
|
|
}
|
|
|
|
Write-Host " Enabling $toolchain"
|
|
kconfig-tweak.ps1 --file "$nuttx\build\.config" -e $toolchain
|
|
}
|
|
}
|
|
|
|
function configure {
|
|
|
|
Write-Host " Configuring..."
|
|
if ($cmake) {
|
|
configure_cmake
|
|
}
|
|
else {
|
|
# configure_default to-do
|
|
Write-Host " configure_default" -ForegroundColor Green
|
|
}
|
|
|
|
}
|
|
|
|
# Perform the next build
|
|
|
|
function build_default {
|
|
# make build_default to-do
|
|
}
|
|
|
|
function build_cmake {
|
|
|
|
# Build the project
|
|
try {
|
|
$errorcmakelist = @()
|
|
# $ErrorActionPreference = 'Stop'
|
|
$ErrorActionPreference = "Continue"
|
|
$errorcmakelist = (cmake --build build 2>$null)
|
|
if ($lastExitCode -ne 0) {
|
|
foreach ($errorline in $errorcmakelist) {
|
|
Write-Host "$errorline"
|
|
}
|
|
}
|
|
else {
|
|
Write-Host " Build completed successfully."
|
|
}
|
|
}
|
|
catch {
|
|
Write-Error "Build failed: $_"
|
|
$global:fail = 1
|
|
}
|
|
if ($SAVEARTIFACTS -eq 1) {
|
|
$artifactconfigdir = "$ARTIFACTDIR\$config"
|
|
# Write-Host "Copy in artifactconfigdir: $artifactconfigdir"
|
|
New-Item -Force -ItemType directory -Path $artifactconfigdir > $null
|
|
try {
|
|
$contentmanifest = $null
|
|
$contentmanifest = Get-Content "$nuttx\build\nuttx.manifest"
|
|
$tmpconfig = $config -replace '\\', ':'
|
|
if (($tmpconfig -match "windows") -and ($MSVC -eq 1)) {
|
|
Copy-Item -Path "$nuttx\build\Debug\nuttx.exe" -Destination $artifactconfigdir -Force -ErrorAction Stop
|
|
Copy-Item -Path "$nuttx\build\Debug\nuttx.pdb" -Destination $artifactconfigdir -Force -ErrorAction Stop
|
|
}
|
|
else {
|
|
foreach ($ma in $contentmanifest) {
|
|
Copy-Item -Path "$nuttx\build\$ma" -Destination $artifactconfigdir -Force -ErrorAction Stop
|
|
}
|
|
}
|
|
}
|
|
catch {
|
|
Write-Host " An error occurred while copying files: $_" -ForegroundColor Red
|
|
$global:fail = 1
|
|
}
|
|
}
|
|
}
|
|
|
|
function build {
|
|
Write-Host " Building NuttX..."
|
|
if ($cmake) {
|
|
# Write-Host " build_cmake" -ForegroundColor Green
|
|
build_cmake
|
|
}
|
|
else {
|
|
# make build_default to-do
|
|
Write-Host " build_default to-do" -ForegroundColor Green
|
|
}
|
|
}
|
|
|
|
function refresh_default {
|
|
# make refresh_default to-do
|
|
}
|
|
|
|
function refresh_cmake {
|
|
# Ensure defconfig in the canonical form
|
|
if ($toolchain) {
|
|
if ($original_toolchain) {
|
|
kconfig-tweak.ps1 --file "$nuttx\build\.config" -e $original_toolchain
|
|
}
|
|
kconfig-tweak.ps1 --file "$nuttx\build\.config" -d $toolchain
|
|
}
|
|
|
|
try {
|
|
if (cmake --build build -t refreshsilent 1>$null) {
|
|
cmake --build build -t refreshsilent
|
|
$global:fail = 1
|
|
}
|
|
Write-Host " Refresh completed successfully."
|
|
}
|
|
catch {
|
|
Write-Error "Refresh failed: $_"
|
|
$global:fail = 1
|
|
}
|
|
|
|
try {
|
|
Remove-Item build -Recurse -Force
|
|
}
|
|
catch {
|
|
Write-Error "Remove-Item failed: $_"
|
|
}
|
|
|
|
# Ensure nuttx and apps directory in clean state
|
|
|
|
if ($CHECKCLEAN -ne 0) {
|
|
if ((Test-Path -Path "$nuttx\.git") -or (Test-Path -Path "$APPSDIR\.git")) {
|
|
try {
|
|
if (git -C $nuttx status -s 2>$null) {
|
|
Write-Host "Git $nuttx status " -ForegroundColor Yellow
|
|
git -C $nuttx status -s
|
|
$global:fail = 1
|
|
}
|
|
if (git -C $APPSDIR status -s 2>$null) {
|
|
Write-Host "Git $APPSDIR status " -ForegroundColor Yellow
|
|
git -C $APPSDIR status -s
|
|
$global:fail = 1
|
|
}
|
|
}
|
|
catch {
|
|
Write-Host "Git is not installed. Please install Git to use this script." -ForegroundColor Red
|
|
$global:fail = 1
|
|
}
|
|
}
|
|
}
|
|
|
|
# Use -f option twice to remove git sub-repository
|
|
|
|
git -C $nuttx clean -f -xfdq
|
|
git -C $APPSDIR clean -f -xfdq
|
|
}
|
|
|
|
function refresh {
|
|
|
|
if ($cmake) {
|
|
refresh_cmake
|
|
}
|
|
else {
|
|
# make refresh_default to-do
|
|
}
|
|
}
|
|
|
|
function run {
|
|
# run to-do
|
|
}
|
|
|
|
# Coordinate the steps for the next build test
|
|
|
|
function dotest {
|
|
param (
|
|
[string]$configfull
|
|
)
|
|
|
|
Write-Host "===================================================================================="
|
|
$configarr = $configfull -split ','
|
|
$config = $($configarr[0])
|
|
|
|
$check = "Windows," + $config -replace '\\', ':'
|
|
|
|
$skip = 0
|
|
foreach ($re in $blacklist) {
|
|
if ("-$check" -eq "$re") {
|
|
$skip = 1
|
|
}
|
|
}
|
|
|
|
$cmake = $null
|
|
if ($NINJACMAKE -eq 1) {
|
|
foreach ($l in $cmakelist) {
|
|
if ("Cmake," + $config -replace '\\', ':' -eq "$l") {
|
|
$cmake = 1
|
|
}
|
|
}
|
|
}
|
|
|
|
Write-Host "Configuration/Tool: $configfull" -ForegroundColor Yellow
|
|
if ($PRINTLISTONLY -eq 1) {
|
|
return
|
|
}
|
|
|
|
$tmparr = $config -split '\\'
|
|
$configdir = $($tmparr[1])
|
|
|
|
$boarddir = $($tmparr[0]).Trim()
|
|
|
|
|
|
if (($boarddir -eq "sim") -and ($MSVC -ne 1)) {
|
|
$skip = 1
|
|
}
|
|
|
|
$path = "$nuttx\boards\*\*\$boarddir\configs\$configdir"
|
|
|
|
if (-Not (Test-Path -Path $path)) {
|
|
Write-Host "ERROR: no configuration found at $path" -ForegroundColor Red
|
|
showusage
|
|
}
|
|
|
|
$toolchain = $null
|
|
$original_toolchain = $null
|
|
if ($config -ne $configfull) {
|
|
$toolchain = $($configarr[1])
|
|
}
|
|
|
|
Write-Host (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") -ForegroundColor Yellow
|
|
Write-Host "------------------------------------------------------------------------------------"
|
|
|
|
distclean
|
|
if ($skip -ne 1 ) {
|
|
configure
|
|
build
|
|
refresh
|
|
}
|
|
else {
|
|
Write-Host " Skipping: $config" -ForegroundColor Green
|
|
}
|
|
}
|
|
|
|
foreach ($line in $testlist) {
|
|
|
|
$firstch = [string[]]$line | ForEach-Object { $_[0] }
|
|
|
|
$arr = $line -split ','
|
|
if ($firstch -eq '\') {
|
|
$dir = $arr
|
|
|
|
if (!$dir[1]) {
|
|
$cnftoolchain = ""
|
|
}
|
|
else {
|
|
$cnftoolchain = "," + $dir[1]
|
|
}
|
|
|
|
$filePath = Get-ChildItem -Path "boards$($dir[0])" -Recurse -ErrorAction SilentlyContinue | Where-Object { $_.Name -eq "defconfig" }
|
|
if ($filePath) {
|
|
foreach ($i in $filePath) {
|
|
$arrpath = $($i.FullName) -split '\\'
|
|
$list = "$($arrpath[$arrpath.count - 4])\$($arrpath[$arrpath.count - 2])"
|
|
|
|
dotest "$list$cnftoolchain"
|
|
}
|
|
}
|
|
else {
|
|
Write-Host "File '$FileName' not found in '$list'." -ForegroundColor Yellow
|
|
}
|
|
}
|
|
else {
|
|
dotest "$line"
|
|
}
|
|
|
|
}
|
|
|
|
Write-Host "------------------------------------------------------------------------------------"
|
|
$timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
|
|
Write-Host "End: $timestamp" -ForegroundColor Yellow
|
|
Write-Host "===================================================================================="
|
|
exit $global:fail
|