Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion eng/Signing.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
<FileExtensionSignInfo Include=".pyd" CertificateName="MicrosoftDotNet500" />
<FileExtensionSignInfo Include=".cat" CertificateName="MicrosoftDotNet500" />

<!-- We don't need to code sign .js files because they are not used in Windows Script Host. -->
<!-- JS files are customer-modifiable Emscripten toolchain files. They cannot be
Authenticode-signed because modifying a signed file breaks the signature.
Instead, a catalog file (emscripten-js.cat) is generated and signed to provide
integrity verification. See the GenerateCatalogFiles target in eng/emsdk.proj. -->
<FileExtensionSignInfo Update=".js" CertificateName="None" />

<!--
Expand Down
18 changes: 18 additions & 0 deletions eng/emsdk.proj
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,24 @@
<Delete Files="@(DeleteCacheFiles)" />
</Target>

<!--
Generate a catalog (.cat) file covering all .js files in the SDK package.
The .js files are customer-modifiable Emscripten toolchain files that cannot be
directly Authenticode-signed. The .cat provides integrity verification without
preventing modification. Only runs on Windows (makecat.exe is a Windows SDK tool)
and only the Windows packs are inserted into VS.
-->
<Target Name="GenerateCatalogFiles" AfterTargets="ReallyBuild" Condition="$([MSBuild]::IsOSPlatform('Windows'))">
<PropertyGroup>
<_CatOutputPath>$(ArtifactsObjDir)upstream\emscripten\emscripten-js.cat</_CatOutputPath>
<_ErrorIfMakecatNotFound Condition="'$(ContinuousIntegrationBuild)' == 'true' or '$(OfficialBuild)' == 'true'">-ErrorIfMakecatNotFound</_ErrorIfMakecatNotFound>
</PropertyGroup>

<Exec Command="powershell.exe -NoProfile -ExecutionPolicy Bypass -Command &quot;&amp; '$(MSBuildThisFileDirectory)generate-catalog.ps1' -RootPath '$(ArtifactsObjDir)upstream' -CatOutputPath '$(_CatOutputPath)' -WindowsSdkDir '$(WindowsSdkDir)' $(_ErrorIfMakecatNotFound)&quot;" StandardOutputImportance="High" />

<Message Condition="Exists('$(_CatOutputPath)')" Importance="High" Text="Generated catalog file: $(_CatOutputPath)" />
</Target>

<Target Name="ReallyPack" DependsOnTargets="Build" BeforeTargets="Pack">
<Message Importance="High" Text="Creating nuget packages..." />
<MSBuild Projects="$(MSBuildThisFileDirectory)nuget\Microsoft.NET.Runtime.Emscripten.Node\Microsoft.NET.Runtime.Emscripten.Node.pkgproj" Targets="Build" />
Expand Down
95 changes: 95 additions & 0 deletions eng/generate-catalog.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<#
.SYNOPSIS
Generates a catalog definition file (.cdf) and catalog file (.cat) for all .js files
in the specified root directory. Used for VS signing compliance - the .js files are
customer-modifiable and cannot be directly Authenticode-signed.

.PARAMETER RootPath
Root directory to search for .js files recursively.

.PARAMETER CatOutputPath
Full path for the output .cat file.
#>
param(
[Parameter(Mandatory)][string]$RootPath,
[Parameter(Mandatory)][string]$CatOutputPath,
[string]$WindowsSdkDir = '',
[switch]$ErrorIfMakecatNotFound
)

$ErrorActionPreference = 'Stop'

$cdfPath = [System.IO.Path]::ChangeExtension($CatOutputPath, '.cdf')

$files = Get-ChildItem -Path $RootPath -Recurse -Filter '*.js' -File
if ($files.Count -eq 0) {
Write-Warning "No .js files found under $RootPath - skipping catalog generation."
exit 0
}

$cdf = @()
$cdf += '[CatalogHeader]'
$cdf += "Name=$CatOutputPath"
$cdf += 'CatalogVersion=2'
$cdf += 'HashAlgorithms=SHA256'
$cdf += ''
$cdf += '[CatalogFiles]'

$i = 0
foreach ($f in $files) {
$label = "js_${i}_" + ($f.Name -replace '[^\w\.-]', '_')
$cdf += "<hash>$label=$($f.FullName)"
$i++
}

$cdf | Set-Content -Path $cdfPath -Encoding ASCII
Write-Host "Generated CDF with $($files.Count) .js files at $cdfPath"

$catDir = [System.IO.Path]::GetDirectoryName($CatOutputPath)
if (-not (Test-Path $catDir)) {
New-Item -ItemType Directory -Path $catDir -Force | Out-Null
}

# Find makecat.exe - it ships with the Windows SDK and may not be on PATH.
# Prefer WindowsSdkDir if passed from MSBuild (not available in this repo's build
# context since it uses Microsoft.Build.Traversal, but may be set in other builds).
$makecat = $null
if ($WindowsSdkDir -and (Test-Path $WindowsSdkDir)) {
$makecat = Get-ChildItem -Path (Join-Path $WindowsSdkDir 'bin') -Recurse -Filter 'makecat.exe' -File |
Where-Object { $_.DirectoryName -match 'x64' } |
Sort-Object DirectoryName -Descending |
Select-Object -First 1
}

if (-not $makecat) {
$makecat = Get-Command makecat.exe -ErrorAction SilentlyContinue
}

if (-not $makecat) {
# Fallback: search common Windows SDK locations
$sdkRoot = "${env:ProgramFiles(x86)}\Windows Kits\10\bin"
if (Test-Path $sdkRoot) {
$makecat = Get-ChildItem -Path $sdkRoot -Recurse -Filter 'makecat.exe' -File |
Where-Object { $_.DirectoryName -match 'x64' } |
Sort-Object DirectoryName -Descending |
Select-Object -First 1
}
}

if (-not $makecat) {
if ($ErrorIfMakecatNotFound) {
throw "makecat.exe not found. Catalog signing requires the Windows SDK which must be available in CI builds."
}
Write-Warning "makecat.exe not found - skipping catalog generation. Catalog signing requires the Windows SDK."
exit 0
}

$makecatPath = if ($makecat -is [System.Management.Automation.CommandInfo]) { $makecat.Source } else { $makecat.FullName }
Write-Host "Using makecat.exe at: $makecatPath"

& $makecatPath $cdfPath
if ($LASTEXITCODE -ne 0) {
throw "makecat.exe failed with exit code $LASTEXITCODE"
}

Write-Host "Generated catalog file: $CatOutputPath"