[CmdletBinding()] param( [ValidateSet('all', 'combined', 'heater', 'fan', 'move')] [string]$Profile = 'combined', [string]$Configuration = 'rev_d', [string]$SdkRoot = 'C:\Users\D30042075206\Desktop\T2G_Sample_Driver_Library_7.9.0', [string]$RepositoryRoot = '', [string]$IarBuild = 'D:\Program Files\IAR Systems\Embedded Workbench 9.2\common\bin\iarbuild.exe' ) $ErrorActionPreference = 'Stop' $resolvedSdk = (Resolve-Path -LiteralPath $SdkRoot).Path $repositoryCandidate = if ($RepositoryRoot) { $RepositoryRoot } else { Join-Path $PSScriptRoot '..' } $resolvedRepository = (Resolve-Path -LiteralPath $repositoryCandidate).Path $resolvedIarBuild = (Resolve-Path -LiteralPath $IarBuild).Path $projects = [ordered]@{ combined = 'Seat_Controller_demo' heater = 'Seat_Backrest_Heater_demo' fan = 'Seat_Fan_demo' move = 'Seat_Move_demo' } $selected = if ($Profile -eq 'all') { @($projects.Keys) } else { @($Profile) } function Invoke-IarBuild { param( [string]$ProjectName, [string]$ProjectPath ) Write-Host "Building $ProjectName ($Configuration)..." & $resolvedIarBuild $ProjectPath -build $Configuration -log all if ($LASTEXITCODE -ne 0) { throw "IAR build failed for $ProjectName with exit code $LASTEXITCODE" } } function Write-ImageSummary { param( [string]$ProjectName, [string]$ImagePath ) if (-not (Test-Path -LiteralPath $ImagePath -PathType Leaf)) { throw "Build completed but HEX image was not found: $ImagePath" } $hash = Get-FileHash -LiteralPath $ImagePath -Algorithm SHA256 Write-Host "$ProjectName HEX: $ImagePath" Write-Host "$ProjectName SHA256: $($hash.Hash.ToLowerInvariant())" } foreach ($name in $selected) { $projectName = $projects[$name] if ($name -ne 'combined') { $project = Join-Path $resolvedSdk "$projectName\IAR\$projectName.ewp" if (-not (Test-Path -LiteralPath $project -PathType Leaf)) { throw "IAR project not found: $project" } Invoke-IarBuild -ProjectName $projectName -ProjectPath $project $image = Join-Path $resolvedSdk "$projectName\IAR\$Configuration\Exe\$projectName.hex" Write-ImageSummary -ProjectName $projectName -ImagePath $image continue } $repositoryFirmware = Join-Path $resolvedRepository 'firmware\t2g\Seat_Controller_demo' $repositoryProject = Join-Path $repositoryFirmware 'IAR\Seat_Controller_demo.ewp' if (-not (Test-Path -LiteralPath $repositoryProject -PathType Leaf)) { throw "Repository IAR project not found: $repositoryProject" } # The IAR project intentionally keeps the vendor-library relative layout. # Stage the repository-owned project beside junctions to the external SDK so # common/ and tviibh8m/ remain vendor dependencies rather than copied source. $temporaryParent = Join-Path $resolvedRepository '.codex_tmp' New-Item -ItemType Directory -Path $temporaryParent -Force | Out-Null $stagingRoot = Join-Path $temporaryParent ("seat-firmware-build-" + [guid]::NewGuid().ToString('N')) $stagingRootFull = [System.IO.Path]::GetFullPath($stagingRoot) $temporaryParentFull = [System.IO.Path]::GetFullPath($temporaryParent) if (-not $stagingRootFull.StartsWith( $temporaryParentFull + [System.IO.Path]::DirectorySeparatorChar, [System.StringComparison]::OrdinalIgnoreCase)) { throw "Firmware staging directory escaped repository temporary root: $stagingRootFull" } try { New-Item -ItemType Directory -Path $stagingRootFull | Out-Null $stagingProjectRoot = Join-Path $stagingRootFull 'Seat_Controller_demo' Copy-Item -LiteralPath $repositoryFirmware -Destination $stagingProjectRoot -Recurse New-Item -ItemType Junction -Path (Join-Path $stagingRootFull 'common') -Target (Join-Path $resolvedSdk 'common') | Out-Null New-Item -ItemType Junction -Path (Join-Path $stagingRootFull 'tviibh8m') -Target (Join-Path $resolvedSdk 'tviibh8m') | Out-Null $stagedProject = Join-Path $stagingProjectRoot 'IAR\Seat_Controller_demo.ewp' Invoke-IarBuild -ProjectName $projectName -ProjectPath $stagedProject $stagedExe = Join-Path $stagingProjectRoot "IAR\$Configuration\Exe" $repositoryExe = Join-Path $repositoryFirmware "IAR\$Configuration\Exe" New-Item -ItemType Directory -Path $repositoryExe -Force | Out-Null foreach ($artifact in @('Seat_Controller_demo.hex', 'Seat_Controller_demo.out')) { $sourceArtifact = Join-Path $stagedExe $artifact if (-not (Test-Path -LiteralPath $sourceArtifact -PathType Leaf)) { throw "IAR build did not produce $sourceArtifact" } Copy-Item -LiteralPath $sourceArtifact -Destination (Join-Path $repositoryExe $artifact) -Force } Write-ImageSummary -ProjectName $projectName -ImagePath (Join-Path $repositoryExe 'Seat_Controller_demo.hex') } finally { if (Test-Path -LiteralPath $stagingRootFull) { foreach ($dependencyLink in @('common', 'tviibh8m')) { $linkPath = Join-Path $stagingRootFull $dependencyLink if (Test-Path -LiteralPath $linkPath) { $link = Get-Item -LiteralPath $linkPath -Force if (($link.Attributes -band [System.IO.FileAttributes]::ReparsePoint) -eq 0) { throw "Refusing to remove non-junction dependency path: $linkPath" } [System.IO.Directory]::Delete($linkPath, $false) } } $remainingLinks = @( Get-ChildItem -LiteralPath $stagingRootFull -Recurse -Force -Attributes ReparsePoint -ErrorAction SilentlyContinue ) if ($remainingLinks.Count -ne 0) { throw "Refusing recursive cleanup because a reparse point remains in $stagingRootFull" } [System.IO.Directory]::Delete($stagingRootFull, $true) } } } Write-Host 'Build complete. This script never flashes or starts a physical actuator.'