I am trying to set up a command line build, and thanks to the documentation I have been successful.
To improve this, I would like to not commit my dependencies, such as stacks/lwip/ gptp_stack/ and FreeRTOS/ to git.
For this to work, I need to import these dependencies from the command line, replicating one of the two steps that "Update Code" does in the S32DS GUI.
I've looked at manual copies, but it seems it is not this straight forward, especially for RTD/
Attached is my script, which works but does not import the dependencies.
Pasting here since I can't attach a powershell script!
param(
[switch]$SkipMex = $false,
[switch]$Clean = $false,
[string]$S32DSRoot = ""
)
# Auto-detect project root (script can be in project root or scripts subdirectory)
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
if (Test-Path "$ScriptDir\.cproject") {
$ProjectRoot = $ScriptDir
} elseif (Test-Path "$ScriptDir\..\.cproject") {
$ProjectRoot = Resolve-Path "$ScriptDir\.."
} else {
throw "Cannot find project root (no .cproject found)"
}
# S32DS installation path (check parameter, then environment variable, then default)
if (-not $S32DSRoot) {
if ($env:S32DS_ROOT) {
$S32DSRoot = $env:S32DS_ROOT
} else {
$S32DSRoot = "C:\NXP\S32DS.3.6.4"
}
}
if (-not (Test-Path "$S32DSRoot\eclipse\s32dsc.exe")) {
throw "S32DS not found at: $S32DSRoot`nSet S32DSRoot parameter or S32DS_ROOT environment variable"
}
# Workspace directory (must be OUTSIDE project to avoid recursive scanning)
$ProjectName = Split-Path -Leaf $ProjectRoot
$WorkspaceDir = Join-Path (Split-Path -Parent $ProjectRoot) ".s32ds_workspace_$ProjectName"
# Build output directory
$BuildOutputDir = "$ProjectRoot\Debug_FLASH"
if (-not (Test-Path $BuildOutputDir)) {
New-Item -ItemType Directory -Path $BuildOutputDir -Force | Out-Null
}
# Set environment variables
$env:RTD_PATH = "$S32DSRoot\S32DS\software\PlatformSDK_S32K3"
$env:BASE_PLATFORMSDK_S32K3 = "$S32DSRoot\S32DS\software\PlatformSDK_S32K3\RTD\BaseNXP_TS_T40D34M60I0R0"
$env:PLATFORM_PLATFORMSDK_S32K3 = "$S32DSRoot\S32DS\software\PlatformSDK_S32K3\RTD\Platform_TS_T40D34M60I0R0"
$env:PlatformSDK_S32K3 = "$S32DSRoot\S32DS\software\PlatformSDK_S32K3"
Write-Host "`n============================================================"
Write-Host " S32DS Headless Build Script"
Write-Host "============================================================"
Write-Host "Project: $ProjectRoot"
Write-Host "Workspace: $WorkspaceDir"
Write-Host "Skip MEX: $SkipMex"
Write-Host "Clean: $Clean"
Write-Host "============================================================`n"
Push-Location "$S32DSRoot\eclipse"
try {
# Step 1: MEX Code Generation
if (-not $SkipMex) {
Write-Host "[1/3] Running MEX code generation..."
# Delete auto-generated S32K358.mex if it exists
$autoMexPath = "$ProjectRoot\S32K358.mex"
if (Test-Path $autoMexPath) {
Write-Host " --> Removing auto-generated S32K358.mex"
Remove-Item $autoMexPath -Force
}
$mexArgs = @(
'-noSplash'
'-application', 'com.nxp.swtools.framework.application'
'--launcher.suppressErrors'
'--launcher.ini', '.\s32ds.ini'
'-HeadlessTool', 'Peripherals'
'-data', $WorkspaceDir
'-SDKPath', "$S32DSRoot\S32DS\software\PlatformSDK_S32K3"
'-Load', "$ProjectRoot\dag_tactile_agg_fw.mex"
'-ExportAll', $ProjectRoot
)
Write-Host " --> Running MEX tool..."
& .\s32dsc.exe $mexArgs 2>&1 | Tee-Object -FilePath "$BuildOutputDir\mex_generation.log" | ForEach-Object {
if ($_ -match "Processing|Generating|ERROR|WARNING|Finished") {
Write-Host " $_"
}
}
# Delete S32K358.mex again if it was created during generation
if (Test-Path $autoMexPath) {
Write-Host " --> Removing auto-generated S32K358.mex"
Remove-Item $autoMexPath -Force
}
# Move HTML report to Debug_FLASH if it exists
$htmlReport = "$ProjectRoot\html_report_Peripherals"
if (Test-Path $htmlReport) {
$htmlReportDest = "$BuildOutputDir\html_report_Peripherals"
if (Test-Path $htmlReportDest) {
Remove-Item $htmlReportDest -Recurse -Force
}
Move-Item $htmlReport $htmlReportDest -Force
Write-Host " --> Moved html_report_Peripherals to Debug_FLASH"
}
Write-Host " [OK] MEX generation completed (log: Debug_FLASH\mex_generation.log)"
} else {
Write-Host "[1/3] Skipping MEX code generation"
}
# Step 2: Import project
Write-Host "`n[2/3] Ensuring project is imported..."
$projectMetadata = "$WorkspaceDir\.metadata\.plugins\org.eclipse.core.resources\.projects\dag_tactile_agg_fw"
if (-not (Test-Path $projectMetadata)) {
Write-Host " --> Importing project into workspace..."
$importArgs = @(
'-noSplash'
'-application', 'org.eclipse.cdt.managedbuilder.core.headlessbuild'
'-data', $WorkspaceDir
'-import', $ProjectRoot
)
Write-Host " --> Importing into workspace..."
& .\s32dsc.exe $importArgs 2>&1 | Tee-Object -FilePath "$BuildOutputDir\import.log" | ForEach-Object {
if ($_ -match "Importing|Project|ERROR|WARNING") {
Write-Host " $_"
}
}
if ($LASTEXITCODE -ne 0) {
Write-Host " [ERROR] Import failed with exit code $LASTEXITCODE"
Write-Host " Check Debug_FLASH\import.log for details"
Write-Host "`nLast 20 lines of import log:"
Get-Content "$BuildOutputDir\import.log" -Tail 20 | ForEach-Object { Write-Host " $_" }
throw "Project import failed"
}
Write-Host " [OK] Project imported"
# Run prebuild script (modifies .cproject, needs to run after import)
Write-Host " --> Running prebuild script..."
$prebuildScript = "$ProjectRoot\scripts\prebuild.py"
if (Test-Path $prebuildScript) {
Push-Location $ProjectRoot
& python $prebuildScript
Pop-Location
Write-Host " [OK] Prebuild completed"
} else {
Write-Host " [WARNING] Prebuild script not found: $prebuildScript"
}
} else {
Write-Host " [OK] Project already imported"
}
# Step 3: Build
Write-Host "`n[3/3] Running build..."
$buildType = if ($Clean) { "-cleanBuild" } else { "-build" }
$buildTypeLabel = if ($Clean) { "Clean build" } else { "Incremental build" }
Write-Host " --> $buildTypeLabel starting...`n"
$buildArgs = @(
'-noSplash'
'-application', 'org.eclipse.cdt.managedbuilder.core.headlessbuild'
'-data', $WorkspaceDir
$buildType, 'dag_tactile_agg_fw/Debug_FLASH'
)
$buildStart = Get-Date
$buildLogPath = "$BuildOutputDir\build_output.log"
# Run build with real-time output
& .\s32dsc.exe $buildArgs 2>&1 | Tee-Object -FilePath $buildLogPath | ForEach-Object {
# Show build progress lines
if ($_ -match "^\[|Building|Compiling|Linking|Finished|error|warning") {
Write-Host $_
}
}
$buildDuration = (Get-Date) - $buildStart
# Check build result more accurately
$buildContent = Get-Content $buildLogPath -Raw
$buildFailed = $buildContent -match "Build Failed" -or $buildContent -match "\d+ error"
$errorCount = if ($buildContent -match "(\d+) error") { [int]$matches[1] } else { 0 }
Write-Host "`n============================================================"
if ($buildFailed -and $errorCount -gt 0) {
Write-Host " [ERROR] BUILD FAILED ($errorCount errors)"
Write-Host "============================================================"
Write-Host "`nError details:"
Get-Content $buildLogPath | Select-String -Pattern "error:" | Select-Object -First 10 | ForEach-Object {
Write-Host " $_"
}
Write-Host "`nFull build output: Debug_FLASH\build_output.log"
Write-Host "Duration: $([math]::Round($buildDuration.TotalSeconds, 1)) seconds`n"
exit 1
} else {
$elfPath = "$ProjectRoot\Debug_FLASH\dag_tactile_agg_fw.elf"
if (Test-Path $elfPath) {
$elfInfo = Get-Item $elfPath
Write-Host " [OK] BUILD SUCCESSFUL"
Write-Host "============================================================"
Write-Host "`nOutput:"
Write-Host " ELF file: $elfPath"
Write-Host " Size: $([math]::Round($elfInfo.Length/1KB, 2)) KB"
Write-Host " Modified: $($elfInfo.LastWriteTime)"
Write-Host " Duration: $([math]::Round($buildDuration.TotalSeconds, 1)) seconds`n"
exit 0
} else {
Write-Host " [WARNING] BUILD COMPLETED (status unclear)"
Write-Host "============================================================"
Write-Host "`nNo errors detected but ELF file not found."
Write-Host "Check Debug_FLASH\build_output.log for details.`n"
exit 0
}
}
}
catch {
Write-Host "`nScript failed: $_"
Write-Host $_.ScriptStackTrace
exit 1
}
finally {
Pop-Location
}