diff --git a/BuildMetadataBin.cmd b/BuildMetadataBin.cmd deleted file mode 100644 index b2c327241..000000000 --- a/BuildMetadataBin.cmd +++ /dev/null @@ -1,3 +0,0 @@ -@echo OFF -powershell.exe -NoLogo -NoProfile -ExecutionPolicy ByPass -Command "& """%~dp0scripts\BuildMetadataBin.ps1""" %*" -exit /B %ERRORLEVEL% diff --git a/DoAll.ps1 b/DoAll.ps1 new file mode 100644 index 000000000..1b599a097 --- /dev/null +++ b/DoAll.ps1 @@ -0,0 +1,17 @@ +.\scripts\GenerateMetadataSource.ps1 +if ($LastExitCode -lt 0) +{ + exit $LastExitCode +} + +.\scripts\BuildMetadataBin.ps1 +if ($LastExitCode -lt 0) +{ + exit $LastExitCode +} + +.\scripts\TestWinmdBinary.ps1 +if ($LastExitCode -lt 0) +{ + exit $LastExitCode +} diff --git a/GenerateMetadataSource.cmd b/GenerateMetadataSource.cmd deleted file mode 100644 index 465aa0f41..000000000 --- a/GenerateMetadataSource.cmd +++ /dev/null @@ -1,3 +0,0 @@ -@echo OFF -pwsh.exe -NoLogo -NoProfile -ExecutionPolicy ByPass -Command "& """%~dp0scripts\GenerateMetadataSource.ps1""" %*" -exit /B %ERRORLEVEL% diff --git a/README.md b/README.md index b959e0f3c..87c43d8b2 100644 --- a/README.md +++ b/README.md @@ -151,9 +151,15 @@ The partitions are meant to break up headers into namespaces. However, some head # How to Generate the .winmd PowerShell Core is required to run the generation scripts. Open a PowerShell Core window and: -1) GenerateMetadataSource.cmd: This loops over the directories under generation\Partitions, running ClangSharp for each one. There are base settings for all partitions: name remaps are found in [generation/scraper/baseRemap.rsp](generation/scraper/baseRemap.rsp) and other settings are found in [generation/scraper/baseSettings.rsp](generation/scraper/baseSettings.rsp). Each partitions folder contains a main.cpp, remap.rsp, and settings.rsp. ClangSharp writes C# files to generation\emitter\manual\generated (these files are not checked in). -2) BuildMetadataBin.cmd: This builds the emitter and points it at the [generation/emitter](generation/emitter) directory. Again, the "generated" subdirectory contains the files that ClangSharp created in step 1. -3) Once the .winmd is built, run TestMetadataBin.cmd which checks for regressions. +1) [.\scripts\GenerateMetadataSource.ps1](.\scripts\GenerateMetadataSource.ps1): This loops over the directories under generation\Partitions, running ClangSharp for each one. There are base settings for all partitions: name remaps are found in [generation/scraper/baseRemap.rsp](generation/scraper/baseRemap.rsp) and other settings are found in [generation/scraper/baseSettings.rsp](generation/scraper/baseSettings.rsp). Each partitions folder contains a main.cpp, remap.rsp, and settings.rsp. ClangSharp writes C# files to generation\emitter\manual\generated (these files are not checked in). +2) [.\scripts\BuildMetadataBin.ps1](.\scripts\BuildMetadataBin.ps1): This builds the emitter and points it at the [generation/emitter](generation/emitter) directory. Again, the "generated" subdirectory contains the files that ClangSharp created in step 1. +3) Once the .winmd is built, run [.\scripts\TestMetadataBin.ps1](.\scripts\TestMetadataBin.ps1) which checks for regressions. + +...or if you can do it all in one shot in a PowerShell Core window: + +```winbatch +.\DoAll.ps1 +```   # Contributing diff --git a/TestMetadataBin.cmd b/TestMetadataBin.cmd deleted file mode 100644 index bcea06441..000000000 --- a/TestMetadataBin.cmd +++ /dev/null @@ -1,3 +0,0 @@ -@echo OFF -powershell.exe -NoLogo -NoProfile -ExecutionPolicy ByPass -Command "& """%~dp0scripts\CompareBinaryAgainstBaseline.ps1""" %*" -exit /B %ERRORLEVEL% diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 2f1787ddb..cd0c0359a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -72,9 +72,9 @@ steps: pwsh: true - task: PowerShell@2 - displayName: Test metadata binary against baseline + displayName: Test metadata binary inputs: - filePath: 'scripts\CompareBinaryAgainstBaseline.ps1' + filePath: 'scripts\TestWinmdBinary.ps1' arguments: '-assemblyVersion $(PrepOutput.NugetVersion)' pwsh: true diff --git a/scripts/BuildMetadataBin.ps1 b/scripts/BuildMetadataBin.ps1 index 743d44150..dc0337c2f 100644 --- a/scripts/BuildMetadataBin.ps1 +++ b/scripts/BuildMetadataBin.ps1 @@ -6,6 +6,8 @@ param . "$PSScriptRoot\CommonUtils.ps1" +Write-Output "`e[36m*** Building .winmd`e[0m" + if (!$assemblyVersion) { $assemblyVersion = $defaultWinSDKNugetVersion @@ -15,16 +17,28 @@ $constantsScraperPath = "$sourcesDir\ConstantsScraper" $constantsScraperProj = "$constantsScraperPath\ConstantsScraper.csproj" $constantsScraperPathBin = "$constantsScraperPath\bin\Release\netcoreapp3.1\ConstantsScraper.dll" & dotnet build $constantsScraperProj -c Release +if ($LastExitCode -ne 0) +{ + exit $LastExitCode +} $clangSharpSourceToWinmdPath = "$sourcesDir\ClangSharpSourceToWinmd" $clangSharpSourceToWinmdProj = "$clangSharpSourceToWinmdPath\ClangSharpSourceToWinmd.csproj" $clangSharpSourceToWinmdBin = "$clangSharpSourceToWinmdPath\bin\Release\netcoreapp3.1\ClangSharpSourceToWinmd.dll" & dotnet build $clangSharpSourceToWinmdProj -c Release +if ($LastExitCode -ne 0) +{ + exit $LastExitCode +} $metadataInteropPath = "$sourcesDir\Win32MetadataInterop" $metadataInteropProj = "$metadataInteropPath\Win32MetadataInterop.csproj" $metadataInteropBin = "$metadataInteropPath\bin\Release\netstandard2.1\Windows.Win32.Interop.dll" & dotnet build $metadataInteropProj -c Release +if ($LastExitCode -ne 0) +{ + exit $LastExitCode +} Copy-Item $metadataInteropBin $binDir @@ -42,9 +56,21 @@ Write-Output "Scraping constants and enums..." Write-Output "Calling: dotnet $constantsScraperPathBin --repoRoot rootDir --enumsJson $manualEnumsJson --enumsJson $enumsJson @$constantsScraperRsp @$requiredNamespacesForNames @$remapFileName" & dotnet $constantsScraperPathBin --repoRoot $rootDir --enumsJson $manualEnumsJson --enumsJson $enumsJson @$constantsScraperRsp @$requiredNamespacesForNames @$remapFileName +if ($LastExitCode -ne 0) +{ + Write-Error "Failed to scrape constants." + exit $LastExitCode +} Write-Output "`n" Write-Output "Creating $outputWinmdFileName..." Write-Output "Calling: dotnet $clangSharpSourceToWinmdBin --sourceDir $emitterDir --interopFileName $metadataInteropBin --outputFileName $outputWinmdFileName --version $assemblyVersion @$remapFileName @$requiredNamespacesForNames @$autoTypesFileName @$enumsRemapFileName" & dotnet $clangSharpSourceToWinmdBin --sourceDir $emitterDir --interopFileName $metadataInteropBin --outputFileName $outputWinmdFileName --version $assemblyVersion @$remapFileName @$requiredNamespacesForNames @$autoTypesFileName @$enumsRemapFileName +if ($LastExitCode -ne 0) +{ + Write-Error "Failed to build .winmd." + exit $LastExitCode +} + +Write-Output "`n`e[32mGenerating .winmd succeeded`e[0m" diff --git a/scripts/CleanOutputs.ps1 b/scripts/CleanOutputs.ps1 new file mode 100644 index 000000000..e0dab0df8 --- /dev/null +++ b/scripts/CleanOutputs.ps1 @@ -0,0 +1,6 @@ + +. "$PSScriptRoot\CommonUtils.ps1" + +Remove-Directory "$emitterDir\obj" +Remove-Directory "$scraperDir\obj" +Remove-Directory $defaultArtifactsDir diff --git a/scripts/CommonUtils.ps1 b/scripts/CommonUtils.ps1 index 1961a4926..c02b1a182 100644 --- a/scripts/CommonUtils.ps1 +++ b/scripts/CommonUtils.ps1 @@ -6,6 +6,14 @@ function Create-Directory([string[]] $Path) } } +function Remove-Directory([string[]] $Path) +{ + if ((Test-Path -Path $Path)) + { + Remove-Item $Path -Recurse + } +} + function Replace-Text { Param ([string] $path, [hashtable] $items) @@ -100,6 +108,7 @@ $emitterDir = "$generationDir\emitter" $partitionsDir = "$scraperDir\Partitions" $sdkApiPath = "$rootDir\ext\sdk-api" $sdkGeneratedSourceDir = "$emitterDir\generated" +$defaultArtifactsDir = "$rootDir\artifacts" if (Test-Path -Path $binDir -PathType leaf) { diff --git a/scripts/GenerateMetadataSource.ps1 b/scripts/GenerateMetadataSource.ps1 index 1ec5b2d69..23bf28a12 100644 --- a/scripts/GenerateMetadataSource.ps1 +++ b/scripts/GenerateMetadataSource.ps1 @@ -56,10 +56,13 @@ function Replace-Text if (!$artifactsDir) { - $artifactsDir = "$rootDir\artifacts" - Create-Directory $artifactsDir + $artifactsDir = $defaultArtifactsDir } +Create-Directory $artifactsDir + +Write-Output "`e[36m*** Generating source files`e[0m" + Write-Output "Making sure cpp NuGet packages are installed..." $nugetSrcPackagesDir = Join-Path -Path $artifactsDir "NuGetPackages" @@ -188,15 +191,39 @@ $stopwatch = [system.diagnostics.stopwatch]::StartNew() Write-Output "`nProcessing each partition...using $throttleCount parallel script(s)" +$errObj = new-object psobject +Add-Member -InputObject $errObj -MemberType NoteProperty -Name ErrorCode -Value 0 + $partitionNames | ForEach-Object -Parallel { + $localObj = $using:errObj + if ($localObj.ErrorCode -ne 0) + { + continue + } + $out1 = "`n$using:PSScriptRoot\GenerateMetadataSourceForPartition.ps1 -version $using:version -partitionName $_ -artifactsDir $using:artifactsDir..." $out2 = & $using:PSScriptRoot\GenerateMetadataSourceForPartition.ps1 -version $using:version -partitionName $_ -artifactsDir $using:artifactsDir -indent "`n " Write-Output "$out1$out2" + + if ($LastExitCode -lt 0) + { + Write-Error "Partition $_ failed." + $localObj.ErrorCode = $LastExitCode + } + } -ThrottleLimit $throttleCount +if ($errObj.ErrorCode -ne 0) +{ + Write-Error "Failed to scrape one or more partitions." + exit $errObj.ErrorCode +} + $stopwatch.Stop() $totalTime = $stopwatch.Elapsed.ToString("c") Write-Output "Total time taken for all partitions: $totalTime" +Write-Output "`n`e[32mGenerating source files succeeded`e[0m" + exit 0 diff --git a/scripts/GenerateMetadataSourceForPartition.ps1 b/scripts/GenerateMetadataSourceForPartition.ps1 index 7bba8ce3a..46703a3bd 100644 --- a/scripts/GenerateMetadataSourceForPartition.ps1 +++ b/scripts/GenerateMetadataSourceForPartition.ps1 @@ -71,6 +71,8 @@ if ($LASTEXITCODE -lt 0) Write-Error "$($indent)ClangSharpPInvokeGenerator.exe failed, full output at $generatorOutput`:" $errText = (Get-ChildItem $generatorOutput | select-string "Error: ") -join "`r`n" Write-Error $errText + + exit $LastExitCode } $possibleRemapsOutput = Join-Path -Path $generationOutArtifactsDir -ChildPath "$partitionName.possibleremaps.output.txt" diff --git a/scripts/CompareBinaryAgainstBaseline.ps1 b/scripts/TestWinmdBinary.ps1 similarity index 82% rename from scripts/CompareBinaryAgainstBaseline.ps1 rename to scripts/TestWinmdBinary.ps1 index c726f690c..ed3f0fa3a 100644 --- a/scripts/CompareBinaryAgainstBaseline.ps1 +++ b/scripts/TestWinmdBinary.ps1 @@ -9,6 +9,8 @@ param . "$PSScriptRoot\CommonUtils.ps1" +Write-Output "`e[36m*** Running tests on .winmd`e[0m" + if (!$assemblyVersion) { $assemblyVersion = $defaultWinSDKNugetVersion @@ -53,20 +55,49 @@ $winmdUtilsPath = "$sourcesDir\WinmdUtils" $winmdUtilsPathProj = "$winmdUtilsPath\WinmdUtils.csproj" $winmdUtilsPathBin = "$winmdUtilsPath\bin\Release\netcoreapp3.1\WinmdUtils.dll" & dotnet build $winmdUtilsPathProj -c Release +if ($LastExitCode -lt 0) +{ + exit $LastExitCode +} + +$failed = $false Write-Output "`n" Write-Output "Comparing $outputWinmdFileName against baseline $baselineWinmd..." Write-Output "Calling: dotnet $winmdUtilsPathBin showMissingImports --first $baselineWinmd --second $winmdPath" & dotnet $winmdUtilsPathBin showMissingImports --first $baselineWinmd --second $winmdPath +if (!$failed -and $LastExitCode -lt 0) +{ + $failed = $true +} Write-Output "`nLooking for duplicate imports in $outputWinmdFileName..." Write-Output "Calling: dotnet $winmdUtilsPathBin showDuplicateImports --winmd $winmdPath" & dotnet $winmdUtilsPathBin showDuplicateImports --winmd $winmdPath +if (!$failed -and $LastExitCode -lt 0) +{ + $failed = $true +} Write-Output "`nLooking for duplicate types in $outputWinmdFileName..." Write-Output "Calling: dotnet $winmdUtilsPathBin showDuplicateTypes --winmd $winmdPath" & dotnet $winmdUtilsPathBin showDuplicateTypes --winmd $winmdPath +if (!$failed -and $LastExitCode -lt 0) +{ + $failed = $true +} Write-Output "`nLooking for duplicate constants in $outputWinmdFileName..." Write-Output "Calling: dotnet $winmdUtilsPathBin showDuplicateConstants --winmd $winmdPath" & dotnet $winmdUtilsPathBin showDuplicateConstants --winmd $winmdPath +if (!$failed -and $LastExitCode -lt 0) +{ + $failed = $true +} + +if ($failed) +{ + exit -1 +} + +Write-Output "`n`e[32mTesting .winmd succeeded`e[0m"