private void RunPackager() { BuildReferencedAssembliesList(); var workAotPath = Path.Combine(IntermediateOutputPath, "workAot"); if (Directory.Exists(workAotPath)) { Directory.Delete(workAotPath, true); } Directory.CreateDirectory(workAotPath); var referencePathsParameter = string.Join(" ", _referencedAssemblies.Select(Path.GetDirectoryName).Distinct().Select(r => $"--search-path=\"{r}\"")); var debugOption = RuntimeDebuggerEnabled ? "--debug" : ""; string packagerBinPath = string.IsNullOrWhiteSpace(PackagerBinPath) ? Path.Combine(MonoWasmSDKPath, "packager.exe") : PackagerBinPath; // // Run the packager to create the original layout. The AOT will optionally run over this pass. // int packagerResults = RunProcess(packagerBinPath, $"{debugOption} {referencePathsParameter} \"{Path.GetFullPath(Assembly)}\"", _distPath); if (packagerResults != 0) { throw new Exception("Failed to generate wasm layout (More details are available in diagnostics mode or using the MSBuild /bl switch)"); } var runtimeExecutionMode = ParseRuntimeExecutionMode(); if (runtimeExecutionMode == RuntimeExecutionMode.FullAOT || runtimeExecutionMode == RuntimeExecutionMode.InterpreterAndAOT) { var emsdkPath = Environment.GetEnvironmentVariable("EMSDK"); if (string.IsNullOrEmpty(emsdkPath)) { throw new InvalidOperationException($"The EMSDK environment variable must be defined. See http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html#installation-instructions"); } var mixedModeExcluded = MixedModeExcludedAssembly ?.Select(a => a.ItemSpec) .ToArray() ?? Array.Empty <string>(); var mixedModeAotAssembliesParam = mixedModeExcluded.Any() ? "--skip-aot-assemblies=" + string.Join(",", mixedModeExcluded) : ""; var aotMode = runtimeExecutionMode == RuntimeExecutionMode.InterpreterAndAOT ? $"--aot-interp {mixedModeAotAssembliesParam}" : "--aot"; var aotOptions = $"{aotMode} --link-mode=all --emscripten-sdkdir=\"{emsdkPath}\" --builddir=\"{workAotPath}\""; var aotPackagerResult = RunProcess(packagerBinPath, $"{debugOption} {aotOptions} {referencePathsParameter} \"{Path.GetFullPath(Assembly)}\"", _distPath); if (aotPackagerResult != 0) { throw new Exception("Failed to generate wasm layout (More details are available in diagnostics mode or using the MSBuild /bl switch)"); } var ninjaResult = RunProcess("ninja", "", workAotPath); if (ninjaResult != 0) { throw new Exception("Failed to generate AOT layout (More details are available in diagnostics mode or using the MSBuild /bl switch)"); } } else { // // Run the IL Linker on the interpreter based output, as the packager does not yet do it. // if ( MonoILLinker && !string.IsNullOrEmpty(CustomLinkerPath) ) { string linkerInput = Path.Combine(IntermediateOutputPath, "linker-in"); if (Directory.Exists(linkerInput)) { Directory.Delete(linkerInput, true); } Directory.Move(_managedPath, linkerInput); Directory.CreateDirectory(_managedPath); var assemblyPath = Path.Combine(linkerInput, Path.GetFileName(Assembly)); var bindingsPath = Path.Combine(linkerInput, "WebAssembly.Bindings.dll"); var linkerPath = Path.Combine(Path.Combine(CustomLinkerPath, "linker"), "monolinker.exe"); int linkerResults = RunProcess( linkerPath, $"-out \"{_managedPath}\" --verbose -b true -l none --exclude-feature com --exclude-feature remoting -a \"{assemblyPath}\" -a \"{bindingsPath}\" -c link -p copy \"WebAssembly.Bindings\" -d \"{_managedPath}\"", _managedPath ); if (linkerResults != 0) { throw new Exception("Failed to execute the linker"); } // // The linker removes files after the mono-config.js file has been // generated by the packager. Synchronize the list with the actual list. // var deletedFiles = Directory .GetFiles(linkerInput) .Select(Path.GetFileName) .Except(Directory .GetFiles(_managedPath) .Select(Path.GetFileName) ); string monoConfigFilePath = Path.Combine(_distPath, "mono-config.js"); var monoConfig = File.ReadAllText(monoConfigFilePath); foreach (var deletedFile in deletedFiles) { Log.LogMessage($"Removing linker deleted file [{deletedFile}] from mono-config.js"); monoConfig = monoConfig .Replace($"\"{deletedFile}\",", "") .Replace($"\"{deletedFile}\"", ""); } File.WriteAllText(monoConfigFilePath, monoConfig); } } }
private void RunPackager() { BuildReferencedAssembliesList(); var workAotPath = Path.Combine(IntermediateOutputPath, "workAot"); if (Directory.Exists(workAotPath)) { Directory.Delete(workAotPath, true); } Directory.CreateDirectory(workAotPath); var referencePathsParameter = string.Join(" ", _referencedAssemblies.Select(Path.GetDirectoryName).Distinct().Select(r => $"--search-path=\"{r}\"")); var debugOption = RuntimeDebuggerEnabled ? "--debug" : ""; string packagerBinPath = string.IsNullOrWhiteSpace(PackagerBinPath) ? Path.Combine(MonoWasmSDKPath, "packager.exe") : PackagerBinPath; // // Run the packager to create the original layout. The AOT will optionally run over this pass. // int packagerResults = RunProcess(packagerBinPath, $"--runtime-config={RuntimeConfiguration} --zlib {debugOption} {referencePathsParameter} \"{Path.GetFullPath(Assembly)}\"", _distPath); if (packagerResults != 0) { throw new Exception("Failed to generate wasm layout (More details are available in diagnostics mode or using the MSBuild /bl switch)"); } if (IsRuntimeAOT()) { var emsdkPath = ValidateEmscripten(); var mixedModeExcluded = MixedModeExcludedAssembly ?.Select(a => a.ItemSpec) .ToArray() ?? Array.Empty <string>(); var mixedModeAotAssembliesParam = mixedModeExcluded.Any() ? "--skip-aot-assemblies=" + string.Join(",", mixedModeExcluded) : ""; var dynamicLibraries = GetDynamicLibrariesParams(); var dynamicLibraryParams = dynamicLibraries.Any() ? "--pinvoke-libs=" + string.Join(",", dynamicLibraries) : ""; var bitcodeFiles = GetBitcodeFilesParams(); var bitcodeFilesParams = dynamicLibraries.Any() ? string.Join(" ", bitcodeFiles.Select(f => $"\"--bc={f}\"")) : ""; var aotMode = _runtimeExecutionMode == RuntimeExecutionMode.InterpreterAndAOT ? $"--aot-interp {mixedModeAotAssembliesParam}" : "--aot"; var aotOptions = $"{aotMode} --link-mode=all {dynamicLibraryParams} {bitcodeFilesParams} --emscripten-sdkdir=\"{emsdkPath}\" --builddir=\"{workAotPath}\""; var aotPackagerResult = RunProcess(packagerBinPath, $"{debugOption} --zlib --runtime-config={RuntimeConfiguration} {aotOptions} {referencePathsParameter} \"{Path.GetFullPath(Assembly)}\"", _distPath); if (aotPackagerResult != 0) { throw new Exception("Failed to generate wasm layout (More details are available in diagnostics mode or using the MSBuild /bl switch)"); } var ninjaResult = RunProcess("ninja", "", workAotPath); if (ninjaResult != 0) { throw new Exception("Failed to generate AOT layout (More details are available in diagnostics mode or using the MSBuild /bl switch)"); } } else { // // Run the IL Linker on the interpreter based output, as the packager does not yet do it. // if ( MonoILLinker && !string.IsNullOrEmpty(CustomLinkerPath) ) { string linkerInput = Path.Combine(IntermediateOutputPath, "linker-in"); if (Directory.Exists(linkerInput)) { Directory.Delete(linkerInput, true); } Directory.Move(_managedPath, linkerInput); Directory.CreateDirectory(_managedPath); var assemblyPath = Path.Combine(linkerInput, Path.GetFileName(Assembly)); var frameworkBindings = new[] { "WebAssembly.Bindings.dll", "WebAssembly.Net.Http.dll", "WebAssembly.Net.WebSockets.dll", }; var bindingsPath = string.Join(" ", frameworkBindings.Select(a => $"-a \"{Path.Combine(linkerInput, a)}\"")); var linkerPath = Path.Combine(Path.Combine(CustomLinkerPath, "linker"), "monolinker.exe"); int linkerResults = RunProcess( linkerPath, $"-out \"{_managedPath}\" --verbose -b true -l none --exclude-feature com --exclude-feature remoting -a \"{assemblyPath}\" {bindingsPath} -c link -p copy \"WebAssembly.Bindings\" -d \"{_managedPath}\"", _managedPath ); if (linkerResults != 0) { throw new Exception("Failed to execute the linker"); } // // The linker removes files after the mono-config.js file has been // generated by the packager. Synchronize the list with the actual list. // var deletedFiles = Directory .GetFiles(linkerInput) .Select(Path.GetFileName) .Except(Directory .GetFiles(_managedPath) .Select(Path.GetFileName) ); string monoConfigFilePath = Path.Combine(_distPath, "mono-config.js"); var monoConfig = File.ReadAllText(monoConfigFilePath); foreach (var deletedFile in deletedFiles) { Log.LogMessage($"Removing linker deleted file [{deletedFile}] from mono-config.js"); monoConfig = monoConfig .Replace($"\"{deletedFile}\",", "") .Replace($"\"{deletedFile}\"", ""); } File.WriteAllText(monoConfigFilePath, monoConfig); } } }