Skip to content

[wasm] Build improvements based on feedback #59391

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Sep 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5f569e3
Refactor to allow fast-path
radical Sep 11, 2021
5b3b91f
MonoAOTCompiler: check for nothing-changed case
radical Sep 11, 2021
28fdcba
[wasm] Change optimization flag defaults for Debug config
radical Sep 17, 2021
6e52172
[wasm] EmccCompile: Fix incremental build, in case of only partial
radical Sep 21, 2021
08ae443
MonoAOTCompiler: Skip unmanaged assemblies, and emit a warning
radical Sep 22, 2021
7fe0e69
Apply suggestions from code review
radical Sep 22, 2021
1c0a340
MonoAOTCompiler: write the cache even when some files fail to compile
radical Sep 22, 2021
7230cd3
Don't set optimization defaults for Debug config, when publishing
radical Sep 22, 2021
c71f9c2
Wasm.Build.Tests: Disable net5.0 because they can't be tested right now
radical Sep 23, 2021
110ed85
[wasm] Error for undefined symbols only when publishing
radical Sep 24, 2021
d17bc64
[wasm] PInvokeTableGenerator: Add support for variadic functions
radical Sep 24, 2021
8ecfd1c
[wasm] Handle pinvokes with function pointers
radical Sep 24, 2021
f4cb745
[wasm] PInvokeTableGenerator: handle pinvokes with function pointers
radical Sep 25, 2021
aac1537
add missing variadic.{c,o}
radical Sep 25, 2021
f48d6b2
[wasm] Add test for issue dotnet#59255
radical Sep 25, 2021
9dd1976
Bump sdk for workload testing to 6.0.100-rc.2.21474.31
radical Sep 22, 2021
46ddc76
Merge remote-tracking branch 'origin/main' into wasm-improvements
radical Sep 27, 2021
712dbb3
MonoAOTCompiler: Check the hash for the file also, for "all up-to-dat…
radical Sep 27, 2021
b23e11e
Merge remote-tracking branch 'origin/main' into wasm-improvements
radical Sep 27, 2021
dc09bf6
Revert "MonoAOTCompiler: Check the hash for the file also, for "all u…
radical Sep 27, 2021
41c7476
PInvokeTableGenerator: don't generate any decl for variadic functions
radical Sep 27, 2021
dcbcc35
Add missing `using` for disposable objects.
radical Sep 29, 2021
1f57975
cleanup
radical Sep 29, 2021
4519646
Merge remote-tracking branch 'origin/main' into rf-wasm-improvements
radical Sep 29, 2021
20a67a1
address feedback from @lewing
radical Sep 29, 2021
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
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@
<SQLitePCLRawbundle_greenVersion>2.0.4</SQLitePCLRawbundle_greenVersion>
<MoqVersion>4.12.0</MoqVersion>
<FsCheckVersion>2.14.3</FsCheckVersion>
<SdkVersionForWorkloadTesting>6.0.100-rc.2.21463.12</SdkVersionForWorkloadTesting>
<SdkVersionForWorkloadTesting>6.0.100-rc.2.21474.31</SdkVersionForWorkloadTesting>
<!-- Docs -->
<MicrosoftPrivateIntellisenseVersion>6.0.0-preview-20210916.1</MicrosoftPrivateIntellisenseVersion>
<!-- ILLink -->
Expand Down
1 change: 1 addition & 0 deletions eng/testing/scenarios/BuildWasmAppsJobsList.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Wasm.Build.Tests.LocalEMSDKTests
Wasm.Build.Tests.MainWithArgsTests
Wasm.Build.Tests.NativeBuildTests
Wasm.Build.Tests.NativeLibraryTests
Wasm.Build.Tests.PInvokeTableGeneratorTests
Wasm.Build.Tests.RebuildTests
Wasm.Build.Tests.SatelliteAssembliesTests
Wasm.Build.Tests.WasmBuildAppTest
Expand Down
2 changes: 0 additions & 2 deletions src/libraries/workloads-testing.targets
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
</ItemGroup>

<Copy SourceFiles="@(_SourceFiles)" DestinationFolder="$(SdkWithWorkloadForTestingPath)\%(_SourceFiles.RecursiveDir)" />
<Copy SourceFiles="$(MonoProjectRoot)\wasm\BlazorOverwrite.targets" DestinationFiles="$(SdkWithWorkloadForTestingPath)\sdk\$(SdkVersionForWorkloadTesting)\Sdks\Microsoft.NET.Sdk.BlazorWebAssembly\targets\Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets" />

<WriteLinesToFile File="$(SdkWithWorkloadStampPath)" Lines="" Overwrite="true" />
</Target>
Expand All @@ -41,7 +40,6 @@
<Exec Condition="$([MSBuild]::IsOSPlatform('windows'))"
Command='powershell -ExecutionPolicy ByPass -NoProfile -command "&amp; $(_DotNetInstallScriptPath) -InstallDir $(SdkWithNoWorkloadForTestingPath) -Version $(SdkVersionForWorkloadTesting)"' />

<Copy SourceFiles="$(MonoProjectRoot)\wasm\BlazorOverwrite.targets" DestinationFiles="$(SdkWithNoWorkloadForTestingPath)\sdk\$(SdkVersionForWorkloadTesting)\Sdks\Microsoft.NET.Sdk.BlazorWebAssembly\targets\Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets" />
<WriteLinesToFile File="$(SdkWithNoWorkloadStampPath)" Lines="" Overwrite="true" />
</Target>

Expand Down
741 changes: 0 additions & 741 deletions src/mono/wasm/BlazorOverwrite.targets

This file was deleted.

13 changes: 9 additions & 4 deletions src/mono/wasm/build/WasmApp.Native.targets
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@
<PropertyGroup>
<_MonoAotCrossCompilerPath>@(MonoAotCrossCompiler->WithMetadataValue('RuntimeIdentifier','browser-wasm'))</_MonoAotCrossCompilerPath>
<_EmccDefaultFlagsRsp>$([MSBuild]::NormalizePath($(_WasmRuntimePackSrcDir), 'emcc-default.rsp'))</_EmccDefaultFlagsRsp>
<WasmNativeStrip Condition="'$(WasmNativeStrip)' == '' and '$(Configuration)' == 'Debug' and '$(WasmBuildingForNestedPublish)' != 'true'">false</WasmNativeStrip>
<WasmNativeStrip Condition="'$(WasmNativeStrip)' == ''">true</WasmNativeStrip>
<WasmNativeDebugSymbols Condition="'$(WasmNativeDebugSymbols)' == ''">true</WasmNativeDebugSymbols>
<WasmLinkIcalls Condition="'$(WasmLinkIcalls)' == ''">$(WasmBuildNative)</WasmLinkIcalls>
Expand All @@ -156,8 +157,7 @@

<_EmccAssertionLevelDefault>0</_EmccAssertionLevelDefault>
<_EmccOptimizationFlagDefault Condition="'$(_WasmDevel)' == 'true'">-O0 -s ASSERTIONS=$(_EmccAssertionLevelDefault)</_EmccOptimizationFlagDefault>
<_EmccOptimizationFlagDefault Condition="'$(_EmccOptimizationFlagDefault)' == '' and '$(OS)' != 'Windows_NT' and '$(Configuration)' == 'Debug'">-Os</_EmccOptimizationFlagDefault>
<_EmccOptimizationFlagDefault Condition="'$(_EmccOptimizationFlagDefault)' == '' and '$(Configuration)' != 'Debug'">-Oz</_EmccOptimizationFlagDefault>
<_EmccOptimizationFlagDefault Condition="'$(_EmccOptimizationFlagDefault)' == '' and '$(Configuration)' == 'Debug' and '$(WasmBuildingForNestedPublish)' != 'true'">-O1</_EmccOptimizationFlagDefault>
<_EmccOptimizationFlagDefault Condition="'$(_EmccOptimizationFlagDefault)' == ''">-Oz</_EmccOptimizationFlagDefault>

<EmccCompileOptimizationFlag Condition="'$(EmccCompileOptimizationFlag)' == ''">$(_EmccOptimizationFlagDefault)</EmccCompileOptimizationFlag>
Expand Down Expand Up @@ -206,6 +206,9 @@
<_EmccLDFlags Include="@(_EmccCommonFlags)" />
<_EmccLDFlags Include="-s TOTAL_MEMORY=$(EmccTotalMemory)" />

<!-- ILLinker should have removed unused imports, so error for Publish -->
<_EmccLDFlags Include="-s ERROR_ON_UNDEFINED_SYMBOLS=0" Condition="'$(WasmBuildingForNestedPublish)' != 'true'" />

<_DriverCDependencies Include="$(_WasmPInvokeHPath);$(_WasmICallTablePath)" />
<_DriverCDependencies Include="$(_DriverGenCPath)" Condition="'$(_DriverGenCNeeded)' == 'true'" />

Expand Down Expand Up @@ -297,7 +300,8 @@
Inputs="@(_BitcodeFile);$(_EmccDefaultFlagsRsp);$(_EmccCompileBitcodeRsp)"
Outputs="@(_BitcodeFile->'%(ObjectFile)')"
Condition="'$(_WasmShouldAOT)' == 'true' and @(_BitcodeFile->Count()) > 0"
DependsOnTargets="_WasmWriteRspForCompilingBitcode">
DependsOnTargets="_WasmWriteRspForCompilingBitcode"
Returns="@(FileWrites)">

<ItemGroup>
<_BitCodeFile Dependencies="%(_BitCodeFile.Dependencies);$(_EmccDefaultFlagsRsp);$(_EmccCompileBitcodeRsp)" />
Expand Down Expand Up @@ -363,7 +367,8 @@
<Target Name="_WasmLinkDotNet"
Inputs="@(_WasmLinkDependencies);$(_EmccDefaultFlagsRsp);$(_EmccLinkRsp)"
Outputs="$(_WasmIntermediateOutputPath)dotnet.js;$(_WasmIntermediateOutputPath)dotnet.wasm"
DependsOnTargets="_WasmSelectRuntimeComponentsForLinking;_WasmCompileAssemblyBitCodeFilesForAOT;_WasmWriteRspFilesForLinking">
DependsOnTargets="_WasmSelectRuntimeComponentsForLinking;_WasmCompileAssemblyBitCodeFilesForAOT;_WasmWriteRspFilesForLinking"
Returns="@(FileWrites)" >

<Message Text="Linking with emcc. This may take a while ..." Importance="High" />
<Message Text="Running emcc with @(_EmccLinkStepArgs->'%(Identity)', ' ')" Importance="Low" />
Expand Down
149 changes: 69 additions & 80 deletions src/tasks/AotCompilerTask/MonoAOTCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,13 @@ private bool ProcessAndValidateArguments()
throw new LogAsErrorException($"'{nameof(OutputType)}=Library' can not be used with '{nameof(UseStaticLinking)}=true'.");
}

foreach (var asmItem in Assemblies)
{
string? fullPath = asmItem.GetMetadata("FullPath");
if (!File.Exists(fullPath))
throw new LogAsErrorException($"Could not find {fullPath} to AOT");
}

return !Log.HasLoggedErrors;
}

Expand All @@ -339,6 +346,12 @@ public override bool Execute()
Log.LogError(laee.Message);
return false;
}
finally
{
if (_cache != null && _cache.Save(CacheFilePath!))
_fileWrites.Add(CacheFilePath!);
FileWrites = _fileWrites.ToArray();
}
}

private bool ExecuteInternal()
Expand All @@ -347,6 +360,7 @@ private bool ExecuteInternal()
return false;

_assembliesToCompile = EnsureAndGetAssembliesInTheSameDir(Assemblies);
_assembliesToCompile = FilterAssemblies(_assembliesToCompile);

if (!string.IsNullOrEmpty(AotModulesTablePath) && !GenerateAotModulesTable(_assembliesToCompile, Profilers, AotModulesTablePath))
return false;
Expand All @@ -372,42 +386,29 @@ private bool ExecuteInternal()
}
else
{
int allowedParallelism = Math.Min(_assembliesToCompile.Count, Environment.ProcessorCount);
int allowedParallelism = DisableParallelAot ? 1 : Math.Min(_assembliesToCompile.Count, Environment.ProcessorCount);
if (BuildEngine is IBuildEngine9 be9)
allowedParallelism = be9.RequestCores(allowedParallelism);

if (DisableParallelAot || allowedParallelism == 1)
ParallelLoopResult result = Parallel.ForEach(
argsList,
new ParallelOptions { MaxDegreeOfParallelism = allowedParallelism },
(args, state) => PrecompileLibraryParallel(args, state));

Log.LogMessage(MessageImportance.High, $"result: {result.IsCompleted}");
if (result.IsCompleted)
{
foreach (var args in argsList)
{
if (!PrecompileLibrarySerial(args))
return !Log.HasLoggedErrors;
}
int numUnchanged = _totalNumAssemblies - _numCompiled;
if (numUnchanged > 0 && numUnchanged != _totalNumAssemblies)
Log.LogMessage(MessageImportance.High, $"[{numUnchanged}/{_totalNumAssemblies}] skipped unchanged assemblies.");
}
else
else if (!Log.HasLoggedErrors)
{
ParallelLoopResult result = Parallel.ForEach(
argsList,
new ParallelOptions { MaxDegreeOfParallelism = allowedParallelism },
(args, state) => PrecompileLibraryParallel(args, state));

if (!result.IsCompleted)
{
return false;
}
Log.LogError($"Precompiling failed due to unknown reasons. Check log for more info");
}

int numUnchanged = _totalNumAssemblies - _numCompiled;
if (numUnchanged > 0 && numUnchanged != _totalNumAssemblies)
Log.LogMessage(MessageImportance.High, $"[{numUnchanged}/{_totalNumAssemblies}] skipped unchanged assemblies.");
}

CompiledAssemblies = ConvertAssembliesDictToOrderedList(compiledAssemblies, _assembliesToCompile).ToArray();

if (_cache.Save(CacheFilePath!))
_fileWrites.Add(CacheFilePath!);
FileWrites = _fileWrites.ToArray();

return !Log.HasLoggedErrors;
}

Expand All @@ -428,60 +429,68 @@ static bool IsNewerThanOutput(string inFile, string outFile)
(File.GetLastWriteTimeUtc(inFile) > File.GetLastWriteTimeUtc(outFile));
}

private IList<ITaskItem> EnsureAndGetAssembliesInTheSameDir(ITaskItem[] originalAssemblies)
private IList<ITaskItem> FilterAssemblies(IEnumerable<ITaskItem> assemblies)
{
List<ITaskItem> filteredAssemblies = new();
string firstAsmDir = Path.GetDirectoryName(originalAssemblies[0].GetMetadata("FullPath")) ?? string.Empty;
bool allInSameDir = true;

foreach (var origAsm in originalAssemblies)
foreach (var asmItem in assemblies)
{
if (allInSameDir && Path.GetDirectoryName(origAsm.GetMetadata("FullPath")) != firstAsmDir)
allInSameDir = false;

if (ShouldSkip(origAsm))
if (ShouldSkip(asmItem))
{
if (parsedAotMode == MonoAotMode.LLVMOnly)
throw new LogAsErrorException($"Building in AOTMode=LLVMonly is not compatible with excluding any assemblies for AOT. Excluded assembly: {origAsm.ItemSpec}");
throw new LogAsErrorException($"Building in AOTMode=LLVMonly is not compatible with excluding any assemblies for AOT. Excluded assembly: {asmItem.ItemSpec}");

Log.LogMessage(MessageImportance.Low, $"Skipping {origAsm.ItemSpec} because it has %(AOT_InternalForceToInterpret)=true");
Log.LogMessage(MessageImportance.Low, $"Skipping {asmItem.ItemSpec} because it has %(AOT_InternalForceToInterpret)=true");
continue;
}

filteredAssemblies.Add(origAsm);
string assemblyPath = asmItem.GetMetadata("FullPath");
using var assemblyFile = File.OpenRead(assemblyPath);
using PEReader reader = new(assemblyFile, PEStreamOptions.Default);
if (!reader.HasMetadata)
{
Log.LogWarning($"Skipping unmanaged {assemblyPath} for AOT");
continue;
}

filteredAssemblies.Add(asmItem);
}

return filteredAssemblies;

static bool ShouldSkip(ITaskItem asmItem)
=> bool.TryParse(asmItem.GetMetadata("AOT_InternalForceToInterpret"), out bool skip) && skip;
}

private IList<ITaskItem> EnsureAndGetAssembliesInTheSameDir(IList<ITaskItem> assemblies)
{
string firstAsmDir = Path.GetDirectoryName(assemblies.First().GetMetadata("FullPath")) ?? string.Empty;
bool allInSameDir = assemblies.All(asm => Path.GetDirectoryName(asm.GetMetadata("FullPath")) == firstAsmDir);
if (allInSameDir)
return filteredAssemblies;
return assemblies;

// Copy to aot-in

string aotInPath = Path.Combine(IntermediateOutputPath, "aot-in");
Directory.CreateDirectory(aotInPath);

List<ITaskItem> newAssemblies = new();
foreach (var origAsm in originalAssemblies)
foreach (var asmItem in assemblies)
{
string asmPath = origAsm.GetMetadata("FullPath");
string asmPath = asmItem.GetMetadata("FullPath");
string newPath = Path.Combine(aotInPath, Path.GetFileName(asmPath));

// FIXME: delete files not in originalAssemblies though
// FIXME: or .. just delete the whole dir?
if (Utils.CopyIfDifferent(asmPath, newPath, useHash: true))
Log.LogMessage(MessageImportance.Low, $"Copying {asmPath} to {newPath}");
_fileWrites.Add(newPath);

if (!ShouldSkip(origAsm))
{
ITaskItem newAsm = new TaskItem(newPath);
origAsm.CopyMetadataTo(newAsm);
newAssemblies.Add(newAsm);
}
ITaskItem newAsm = new TaskItem(newPath);
asmItem.CopyMetadataTo(newAsm);
newAssemblies.Add(newAsm);
}

return newAssemblies;

static bool ShouldSkip(ITaskItem asmItem)
=> bool.TryParse(asmItem.GetMetadata("AOT_InternalForceToInterpret"), out bool skip) && skip;
}

private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, string? monoPaths)
Expand Down Expand Up @@ -773,28 +782,6 @@ private bool PrecompileLibrary(PrecompileArguments args)
return true;
}

private bool PrecompileLibrarySerial(PrecompileArguments args)
{
try
{
if (PrecompileLibrary(args))
return true;
}
catch (LogAsErrorException laee)
{
Log.LogError($"Precompile failed for {args.AOTAssembly}: {laee.Message}");
}
catch (Exception ex)
{
if (Log.HasLoggedErrors)
Log.LogMessage(MessageImportance.Low, $"Precompile failed for {args.AOTAssembly}: {ex}");
else
Log.LogError($"Precompile failed for {args.AOTAssembly}: {ex}");
}

return false;
}

private void PrecompileLibraryParallel(PrecompileArguments args, ParallelLoopState state)
{
try
Expand All @@ -804,14 +791,14 @@ private void PrecompileLibraryParallel(PrecompileArguments args, ParallelLoopSta
}
catch (LogAsErrorException laee)
{
Log.LogError($"Precompile failed for {args.AOTAssembly}: {laee.Message}");
Log.LogError($"Precompiling failed for {args.AOTAssembly}: {laee.Message}");
}
catch (Exception ex)
{
if (Log.HasLoggedErrors)
Log.LogMessage(MessageImportance.Low, $"Precompile failed for {args.AOTAssembly}: {ex}");
else
Log.LogError($"Precompile failed for {args.AOTAssembly}: {ex}");
Log.LogError($"Precompiling failed for {args.AOTAssembly}: {ex}");
}

state.Break();
Expand Down Expand Up @@ -940,10 +927,8 @@ private static IList<ITaskItem> ConvertAssembliesDictToOrderedList(ConcurrentDic
List<ITaskItem> outItems = new(originalAssemblies.Count);
foreach (ITaskItem item in originalAssemblies)
{
if (!dict.TryGetValue(item.GetMetadata("FullPath"), out ITaskItem? dictItem))
throw new LogAsErrorException($"Bug: Could not find item in the dict with key {item.ItemSpec}");

outItems.Add(dictItem);
if (dict.TryGetValue(item.GetMetadata("FullPath"), out ITaskItem? dictItem))
outItems.Add(dictItem);
}
return outItems;
}
Expand Down Expand Up @@ -993,7 +978,7 @@ public FileCache(string? cacheFilePath, TaskLoggingHelper log)
}

_oldCache ??= new();
_newCache = new();
_newCache = new(_oldCache.FileHashes);
}

public bool ShouldCopy(ProxyFile proxyFile, [NotNullWhen(true)] out string? cause)
Expand Down Expand Up @@ -1110,6 +1095,10 @@ public enum MonoAotModulesTableLanguage

internal class CompilerCache
{
public CompilerCache() => FileHashes = new();
public CompilerCache(IDictionary<string, string> oldHashes)
=> FileHashes = new(oldHashes);

[JsonPropertyName("file_hashes")]
public ConcurrentDictionary<string, string> FileHashes { get; set; } = new();
public ConcurrentDictionary<string, string> FileHashes { get; set; }
}
Loading