Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,6 @@
<PropertyGroup>
<_WasmBuildWebCilPath>$([MSBuild]::NormalizeDirectory($(IntermediateOutputPath), 'webcil'))</_WasmBuildWebCilPath>
<_WasmBuildTmpWebCilPath>$([MSBuild]::NormalizeDirectory($(IntermediateOutputPath), 'tmp-webcil'))</_WasmBuildTmpWebCilPath>
<_WasmBuildOuputPath>$([MSBuild]::NormalizeDirectory('$(OutputPath)', 'wwwroot'))</_WasmBuildOuputPath>
</PropertyGroup>

<ConvertDllsToWebCil Candidates="@(_BuildAssetsCandidates)" IntermediateOutputPath="$(_WasmBuildTmpWebCilPath)" OutputPath="$(_WasmBuildWebCilPath)" IsEnabled="$(_WasmEnableWebcil)">
Expand All @@ -358,6 +357,8 @@
</ConvertDllsToWebCil>

<ItemGroup>
<!-- Set per-item ContentRoot so each asset's Identity matches its actual file on disk -->
<_WebCilAssetsCandidates Update="@(_WebCilAssetsCandidates)" ContentRoot="%(RootDir)%(Directory)" />
<_WasmFingerprintPatterns Include="WasmFiles" Pattern="*.wasm" Expression="#[.{fingerprint}]!" />
<_WasmFingerprintPatterns Include="DllFiles" Pattern="*.dll" Expression="#[.{fingerprint}]!" />
<_WasmFingerprintPatterns Include="DatFiles" Pattern="*.dat" Expression="#[.{fingerprint}]!" />
Expand All @@ -372,7 +373,6 @@
AssetRole="Primary"
CopyToOutputDirectory="PreserveNewest"
CopyToPublishDirectory="Never"
ContentRoot="$(_WasmBuildOuputPath)"
FingerprintCandidates="$(_WasmFingerprintAssets)"
FingerprintPatterns="@(FingerprintPatterns);@(_WasmFingerprintPatterns)"
BasePath="$(StaticWebAssetBasePath)"
Expand Down Expand Up @@ -457,7 +457,7 @@
<Output TaskParameter="ResolvedEndpoints" ItemName="_WasmResolvedEndpoints" />
</ResolveFingerprintedStaticWebAssetEndpointsForAssets>

<GenerateWasmBootJson

Check failure on line 460 in src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release LibraryTestsCoreCLR)

src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets#L460

src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets(460,5): error : (NETCORE_ENGINEERING_TELEMETRY=Build) System.ArgumentException: An item with the same key has already been added. Key: /__w/1/s/artifacts/bin/System.Reflection.TestModule/Release/netstandard2.0/System.Reflection.TestModule.dll at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) at System.Linq.Enumerable.SpanToDictionary[TSource,TKey](ReadOnlySpan`1 source, Func`2 keySelector, IEqualityComparer`1 comparer) at System.Linq.Enumerable.ToDictionary[TSource,TKey](IEnumerable`1 source, Func`2 keySelector, IEqualityComparer`1 comparer) at Microsoft.NET.Sdk.WebAssembly.GenerateWasmBootJson.WriteBootConfig(String entryAssemblyName) in /_/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs:line 203 at Microsoft.NET.Sdk.WebAssembly.GenerateWasmBootJson.Execute() in /_/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs:line 110
AssemblyPath="@(IntermediateAssembly)"
ApplicationEnvironment="$(_WasmBuildApplicationEnvironmentName)"
Resources="@(WasmStaticWebAsset);@(_WasmJsModuleCandidatesForBuild);@(_WasmFilesToIncludeInFileSystemStaticWebAsset)"
Expand Down Expand Up @@ -518,7 +518,7 @@
AssetTraitValue="manifest"
CopyToOutputDirectory="PreserveNewest"
CopyToPublishDirectory="Never"
ContentRoot="$(OutDir)wwwroot"
ContentRoot="$(IntermediateOutputPath)"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this needs to happen in other places like the definition of the .wasm files as assets (after webcil conversion).

I believe the important bit here is that ContentRoot + RelativePath must exist for all assets

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Added a commit that sets per-item ContentRoot metadata on each _WebCilAssetsCandidates item to %(RootDir)%(Directory) (its own directory). This ensures candidateFullPath.StartsWith(normalizedContentRoot) is always true in DefineStaticWebAssets.ComputeCandidateIdentity, so Identity equals the physical file path for all candidates — webcil-converted files in obj/webcil/, runtime pack files in packs/, PDBs from obj/, etc.

The task-level ContentRoot parameter is kept as a fallback but the per-item metadata takes precedence via ComputePropertyValue.

BasePath="$(StaticWebAssetBasePath)"
>
<Output TaskParameter="Assets" ItemName="_WasmBuildBootConfigStaticWebAsset" />
Expand Down Expand Up @@ -584,18 +584,10 @@
</Target>

<Target Name="_AddWasmPreloadBuildProperties" DependsOnTargets="_WasmConfigurePreload;_AddWasmStaticWebAssets" BeforeTargets="GenerateStaticWebAssetsManifest" Condition="'$(_WasmPreloadAssets)' == 'true'">
<PropertyGroup>
<_WasmBootConfigFileNameWithoutExtension>$([System.IO.Path]::GetFileNameWithoutExtension('$(_WasmBootConfigFileName)'))</_WasmBootConfigFileNameWithoutExtension>
<_WasmBootConfigFileExtension>$([System.IO.Path]::GetExtension('$(_WasmBootConfigFileName)'))</_WasmBootConfigFileExtension>
</PropertyGroup>
<ItemGroup>
<_WasmPreloadBuildScriptAsset Include="@(StaticWebAsset)" Condition="'$(_WasmFingerprintAssets)' == 'true' and '$(_WasmFingerprintBootConfig)' == 'true' and '%(AssetKind)' != 'Publish' and '%(FileName)%(Extension)' == '$(_WasmBootConfigFileNameWithoutExtension).%(Fingerprint)$(_WasmBootConfigFileExtension)'" />
<_WasmPreloadBuildScriptAsset Include="@(StaticWebAsset)" Condition="('$(_WasmFingerprintAssets)' != 'true' or '$(_WasmFingerprintBootConfig)' != 'true') and '%(AssetKind)' != 'Publish' and '%(FileName)%(Extension)' == '$(_WasmBootConfigFileName)'" />
</ItemGroup>

<FilterStaticWebAssetEndpoints
Endpoints="@(StaticWebAssetEndpoint)"
Assets="@(_WasmPreloadBuildScriptAsset)"
Assets="@(_WasmBuildBootConfigStaticWebAsset)"
Filters="@(_WasmPreloadEndpointFilter)"
>
<Output TaskParameter="FilteredEndpoints" ItemName="_WasmPreloadBuildScriptAssetEndpoint" />
Expand All @@ -614,13 +606,10 @@
</ItemGroup>
</Target>
<Target Name="_AddWasmPreloadPublishProperties" DependsOnTargets="_WasmConfigurePreload;_AddPublishWasmBootJsonToStaticWebAssets" BeforeTargets="GenerateStaticWebAssetsPublishManifest" Condition="'$(_WasmPreloadAssets)' == 'true'">
<ItemGroup>
<_WasmPreloadPublishScriptAsset Include="@(StaticWebAsset)" Condition="'%(AssetKind)' != 'Build' and '%(FileName)%(Extension)' == '$(_WasmPublishBootConfigFileName)'" />
</ItemGroup>

<FilterStaticWebAssetEndpoints
Endpoints="@(StaticWebAssetEndpoint)"
Assets="@(_WasmPreloadPublishScriptAsset)"
Assets="@(_WasmPublishBootConfigStaticWebAsset)"
Filters="@(_WasmPreloadEndpointFilter)"
>
<Output TaskParameter="FilteredEndpoints" ItemName="_WasmPreloadPublishScriptAssetEndpoint" />
Expand Down Expand Up @@ -729,6 +718,18 @@
<_NewWebCilPublishStaticWebAssetsCandidatesNoMetadata
Include="@(_NewWebCilPublishStaticWebAssetsCandidates)"
RemoveMetadata="Integrity;Fingerprint" />
<!-- Set per-item ContentRoot so each asset's Identity matches its actual file on disk.
Clear stale Fingerprint/Integrity so DefineStaticWebAssets recomputes from the actual file. -->
<_NewWebCilPublishStaticWebAssetsCandidatesNoMetadata Update="@(_NewWebCilPublishStaticWebAssetsCandidatesNoMetadata)" ContentRoot="%(RootDir)%(Directory)" />
<_PromotedWasmPublishStaticWebAssets Update="@(_PromotedWasmPublishStaticWebAssets)" ContentRoot="%(RootDir)%(Directory)" Fingerprint="" Integrity="" />
<!-- Satellite (Culture) promoted assets are Related assets whose RelatedAsset points to a build-time path
that doesn't match any publish-time candidate. Promote them to Primary so DefineStaticWebAssets
processes them as standalone assets instead of trying to match a parent. -->
<_PromotedWasmPublishStaticWebAssets
Update="@(_PromotedWasmPublishStaticWebAssets)"
Condition="'%(_PromotedWasmPublishStaticWebAssets.AssetTraitName)' == 'Culture'"
AssetRole="Primary"
RelatedAsset="" />
</ItemGroup>

<DefineStaticWebAssets CandidateAssets="@(_NewWebCilPublishStaticWebAssetsCandidatesNoMetadata);@(_PromotedWasmPublishStaticWebAssets)">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,23 +332,11 @@ static bool IsDotNetWasm(string key)

private TaskItem CreatePromotedAsset(ITaskItem asset)
{
string newAssetItemSpec = asset.ItemSpec;
string newAssetRelativePath = asset.GetMetadata("RelativePath");

if (FingerprintAssets)
{
string assetDirectory = Path.GetDirectoryName(asset.ItemSpec);
string assetFileNameToFingerprint = Path.GetFileName(newAssetRelativePath);
string fingerprint = asset.GetMetadata("Fingerprint");
string newAssetFingerprintedFileName = assetFileNameToFingerprint.Replace("#[.{fingerprint}]!", $".{fingerprint}");
if (newAssetFingerprintedFileName != assetFileNameToFingerprint)
{
newAssetItemSpec = $"{assetDirectory}/{newAssetFingerprintedFileName}";
}
}

var newAsset = new TaskItem(newAssetItemSpec, asset.CloneCustomMetadata());
newAsset.SetMetadata("RelativePath", newAssetRelativePath);
// Keep ItemSpec pointing to the actual file on disk.
// DefineStaticWebAssets will resolve fingerprint placeholders in RelativePath
// and compute Fingerprint/Integrity from the real file.
var newAsset = new TaskItem(asset.ItemSpec, asset.CloneCustomMetadata());
newAsset.SetMetadata("RelativePath", asset.GetMetadata("RelativePath"));

ApplyPublishProperties(newAsset);
return newAsset;
Expand Down