<UsingTask TaskName="WasmLoadAssembliesAndReferences" AssemblyFile="$(WasmAppBuilderTasksAssemblyPath)" />
<UsingTask TaskName="PInvokeTableGenerator" AssemblyFile="$(WasmAppBuilderTasksAssemblyPath)" />
<UsingTask TaskName="IcallTableGenerator" AssemblyFile="$(WasmAppBuilderTasksAssemblyPath)" />
- <UsingTask TaskName="Microsoft.WebAssembly.Build.Tasks.RunWithEmSdkEnv" AssemblyFile="$(WasmAppBuilderTasksAssemblyPath)" />
<!--
Required public items/properties:
<Target Name="_WasmAotCompileApp" Condition="'$(RunAOTCompilation)' == 'true'">
<Error Condition="'@(_WasmAssembliesInternal)' == ''" Text="Item _WasmAssembliesInternal is empty" />
- <Error Condition="'$(EMSDK_PATH)' == ''" Text="%24(EMSDK_PATH) should be set to emscripten sdk" />
- <Error Condition="!Exists($(EMSDK_PATH))" Text="Cannot find EMSDK_PATH=$(EMSDK_PATH)" />
+ <Error Condition="'$(_IsEMSDKMissing)' == 'true'"
+ Text="$(_EMSDKMissingErrorMessage) Emscripten SDK is required for AOT'ing assemblies." />
<ItemGroup>
<MonoAOTCompilerDefaultAotArguments Include="no-opt" />
UseLLVM="true"
DisableParallelAot="true"
DedupAssembly="$(_WasmDedupAssembly)"
- LLVMPath="$(EMSDK_PATH)\upstream\bin">
+ LLVMPath="$(EmSdkUpstreamBinPath)">
<Output TaskParameter="CompiledAssemblies" ItemName="_WasmAssembliesInternal" />
<Output TaskParameter="FileWrites" ItemName="FileWrites" />
</MonoAOTCompiler>
</ItemGroup>
</Target>
- <Target Name="_BeforeWasmBuildApp" DependsOnTargets="_SetWasmBuildNativeDefaults">
+ <Target Name="_BeforeWasmBuildApp" DependsOnTargets="_SetupEmscripten;_SetWasmBuildNativeDefaults">
<Error Condition="'$(IntermediateOutputPath)' == ''" Text="%24(IntermediateOutputPath) property needs to be set" />
<Error Condition="!Exists('$(MicrosoftNetCoreAppRuntimePackRidDir)')" Text="MicrosoftNetCoreAppRuntimePackRidDir=$(MicrosoftNetCoreAppRuntimePackRidDir) doesn't exist" />
<Error Condition="@(WasmAssembliesToBundle->Count()) == 0" Text="WasmAssembliesToBundle item is empty. No assemblies to process" />
</ItemGroup>
</Target>
- <Target Name="_SetWasmBuildNativeDefaults">
+ <Target Name="_SetupEmscripten">
+ <!-- If $(Emscripten*ToolsPath) etc propeties are already set (by the workload pack),
+ then prefer that, and ignore $(EMSDK_PATH) -->
+
+ <!-- If $(Emscripten*ToolsPath) etc propeties are *not* set (by the workload pack),
+ then try to construct the same properties based on $(EMSDK_PATH) -->
+ <PropertyGroup Condition="'$(EmscriptenSdkToolsPath)' == '' and '$(EMSDK_PATH)' != ''">
+ <EmscriptenSdkToolsPath>$([MSBuild]::EnsureTrailingSlash($(EMSDK_PATH)))</EmscriptenSdkToolsPath>
+ <EmSdkUpstreamBinPath>$([MSBuild]::NormalizeDirectory($(EmscriptenSdkToolsPath), 'upstream', 'bin'))</EmSdkUpstreamBinPath>
+
+ <_NodeToolsBasePath>$(EmscriptenSdkToolsPath)node</_NodeToolsBasePath>
+
+ <!-- gets the path like emsdk/python/3.7.4-2_64bit -->
+ <_NodeToolsVersionedPath Condition="Exists($(_NodeToolsBasePath))">$([System.IO.Directory]::GetDirectories($(_NodeToolsBasePath)))</_NodeToolsVersionedPath>
+ <EmscriptenNodeToolsPath Condition="'$(_NodeToolsVersionedPath)' != ''">$(_NodeToolsVersionedPath)</EmscriptenNodeToolsPath>
+
+ <_UsingEMSDK_PATH>true</_UsingEMSDK_PATH>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <_EMSDKMissingPaths Condition="'$(_EMSDKMissingPaths)' == '' and ('$(EmscriptenSdkToolsPath)' == '' or !Exists('$(EmscriptenSdkToolsPath)'))">%24(EmscriptenSdkToolsPath)=$(EmscriptenSdkToolsPath) </_EMSDKMissingPaths>
+ <_EMSDKMissingPaths Condition="'$(_EMSDKMissingPaths)' == '' and ('$(EmscriptenNodeToolsPath)' == '' or !Exists('$(EmscriptenNodeToolsPath)'))">%24(EmscriptenNodeToolsPath)=$(EmscriptenNodeToolsPath) </_EMSDKMissingPaths>
+ <_EMSDKMissingPaths Condition="'$(_EMSDKMissingPaths)' == '' and ('$(EmSdkUpstreamBinPath)' == '' or !Exists('$(EmSdkUpstreamBinPath)'))">%24(EmSdkUpstreamBinPath)=$(EmSdkUpstreamBinPath) </_EMSDKMissingPaths>
+ </PropertyGroup>
+
+ <!-- Emscripten uses system python on Linux, so we don't need $(EmscriptenPythonToolsPath) -->
+ <PropertyGroup Condition="'$(_UsingEMSDK_PATH)' == 'true' and !$([MSBuild]::IsOSPlatform('linux'))">
+ <_PythonToolsBasePath>$(EmscriptenSdkToolsPath)python</_PythonToolsBasePath>
+ <_PythonToolsVersionedPath Condition="Exists($(_PythonToolsBasePath))">$([System.IO.Directory]::GetDirectories($(_PythonToolsBasePath)))</_PythonToolsVersionedPath>
+ <EmscriptenPythonToolsPath Condition="'$(_PythonToolsVersionedPath)' != ''">$(_PythonToolsVersionedPath)</EmscriptenPythonToolsPath>
+
+ <_EMSDKMissingPaths Condition="'$(_EMSDKMissingPaths)' == '' and ('$(EmscriptenPythonToolsPath)' == '' or !Exists('$(EmscriptenPythonToolsPath)'))">%24(EmscriptenPythonToolsPath)=$(EmscriptenPythonToolsPath) </_EMSDKMissingPaths>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <_EMSDKMissingErrorMessage Condition="'$(EMSDK_PATH)' == '' and '$(EmscriptenSdkToolsPath)' == ''">Could not find emscripten sdk. Either set %24(EMSDK_PATH), or use workloads to get the sdk.</_EMSDKMissingErrorMessage>
+
+ <_EMSDKMissingErrorMessage Condition="'$(_EMSDKMissingErrorMessage)' == '' and '$(_UsingEMSDK_PATH)' != 'true' and '$(_EMSDKMissingPaths)' != ''">Emscripten from the workload is missing some paths: $(_EMSDKMissingPaths).</_EMSDKMissingErrorMessage>
+ <_EMSDKMissingErrorMessage Condition="'$(_EMSDKMissingErrorMessage)' == '' and '$(_UsingEMSDK_PATH)' == 'true' and !Exists($(EMSDK_PATH))">Could not find Emscripten sdk at %24(EMSDK_PATH)=$(EMSDK_PATH) .</_EMSDKMissingErrorMessage>
+ <_EMSDKMissingErrorMessage Condition="'$(_EMSDKMissingErrorMessage)' == '' and '$(_UsingEMSDK_PATH)' == 'true' and '$(_EMSDKMissingPaths)' != ''">Specified Emscripten sdk at %24(EMSDK_PATH)=$(EMSDK_PATH) is missing some paths: $(_EMSDKMissingPaths).</_EMSDKMissingErrorMessage>
+
+ <_IsEMSDKMissing Condition="'$(_EMSDKMissingErrorMessage)' != ''">true</_IsEMSDKMissing>
+ </PropertyGroup>
+
<PropertyGroup>
- <_IsEMSDKMissing Condition="'$(EMSDK_PATH)' == '' or !Exists('$(EMSDK_PATH)')">true</_IsEMSDKMissing>
+ <EmscriptenSdkToolsPath Condition="'$(EmscriptenSdkToolsPath)' != ''" >$([MSBuild]::NormalizeDirectory($(EmscriptenSdkToolsPath)))</EmscriptenSdkToolsPath>
+ <EmscriptenNodeToolsPath Condition="'$(EmscriptenNodeToolsPath)' != ''" >$([MSBuild]::NormalizeDirectory($(EmscriptenNodeToolsPath)))</EmscriptenNodeToolsPath>
+ <EmscriptenPythonToolsPath Condition="'$(EmscriptenPythonToolsPath)' != ''">$([MSBuild]::NormalizeDirectory($(EmscriptenPythonToolsPath)))</EmscriptenPythonToolsPath>
+ <EmSdkUpstreamBinPath Condition="'$(EmSdkUpstreamBinPath)' != ''" >$([MSBuild]::NormalizeDirectory($(EmSdkUpstreamBinPath)))</EmSdkUpstreamBinPath>
</PropertyGroup>
+ <!-- Environment variables required for running emsdk commands like `emcc` -->
+ <ItemGroup Condition="'$(EmscriptenSdkToolsPath)' != ''">
+ <EmscriptenEnvVars Include="DOTNET_EMSCRIPTEN_LLVM_ROOT=$(EmscriptenSdkToolsPath)bin" />
+ <EmscriptenEnvVars Include="DOTNET_EMSCRIPTEN_BINARYEN_ROOT=$(EmscriptenSdkToolsPath)" />
+ <EmscriptenEnvVars Include="DOTNET_EMSCRIPTEN_NODE_JS=$([MSBuild]::NormalizePath($(EmscriptenNodeToolsPath), 'bin', 'node$(_ExeExt)'))" />
+ </ItemGroup>
+
+ <!-- Paths to be added to environment variable `PATH` -->
+ <ItemGroup Condition="'$(EmscriptenSdkToolsPath)' != '' and '$(_UsingEMSDK_PATH)' != 'true'">
+ <_EmscriptenAddPATH Condition="'$(EmscriptenPythonToolsPath)' != ''" Include="$(EmscriptenPythonToolsPath)bin" />
+ <_EmscriptenAddPATH Include="$(EmscriptenSdkToolsPath)emscripten" />
+ </ItemGroup>
+
+ <ItemGroup Condition="'$(EmscriptenSdkToolsPath)' != '' and '$(_UsingEMSDK_PATH)' == 'true'">
+ <_EmscriptenAddPATH Include="$(EmscriptenSdkToolsPath)" />
+ <_EmscriptenAddPATH Include="$(EmscriptenNodeToolsPath)bin" />
+ <_EmscriptenAddPATH Include="$([MSBuild]::NormalizeDirectory($(EmscriptenSdkToolsPath), 'upstream', 'emscripten'))" />
+ </ItemGroup>
+
+ <!-- paths with trailing slash, like:
+ c:\foo\bar\
+
+ .. will become PATH=c:\foo\bar\;c:\xyz
+
+ .. which would escape the semicolon path separator. So, change
+ that to c:\foo\bar\. so the setting will become:
+
+ PATH=c:\foo\bar\.;c:\xyz
+ -->
+ <ItemGroup>
+ <_EmscriptenAddPATHFixed Include="%(_EmscriptenAddPATH.Identity)."
+ Condition="$([MSBuild]::ValueOrDefault('%(_EmscriptenAddPATH.Identity)', '').EndsWith('\'))" />
+ <_EmscriptenAddPATHFixed Include="@(_EmscriptenAddPATH)"
+ Condition="!$([MSBuild]::ValueOrDefault('%(_EmscriptenAddPATH.Identity)', '').EndsWith('\'))" />
+ <_EmscriptenAddPATH Remove="@(_EmscriptenAddPATH)" />
+ <_EmscriptenAddPATH Include="@(_EmscriptenAddPATHFixed)" />
+ </ItemGroup>
+
+ <PropertyGroup>
+ <_EmscriptenAddPATHProperty Condition="'$(OS)' == 'Windows_NT'">@(_EmscriptenAddPATH -> '%(Identity)', '%3B')</_EmscriptenAddPATHProperty>
+ <_EmscriptenAddPATHProperty Condition="'$(OS)' != 'Windows_NT'">@(_EmscriptenAddPATH -> '%(Identity)', ':')</_EmscriptenAddPATHProperty>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <!-- semicolon is a msbuild property separator. It is also the path separator on windows.
+ So, we need to escape it here, so the paths don't get split up when converting
+ to string[] for passing to Exec task -->
+ <EmscriptenEnvVars Include="PATH=$(_EmscriptenAddPATHProperty)%3B$([MSBuild]::Escape($(PATH)))" Condition="'$(OS)' == 'Windows_NT'" />
+
+ <EmscriptenEnvVars Include="PATH=$(_EmscriptenAddPATHProperty):$(PATH)" Condition="'$(OS)' != 'Windows_NT'" />
+ </ItemGroup>
+ </Target>
+
+ <Target Name="_SetWasmBuildNativeDefaults">
<!-- if already set, maybe by a user projects, then a missing emsdk is an error -->
<Error Condition="'$(WasmBuildNative)' == 'true' and '$(_IsEMSDKMissing)' == 'true'"
- Text="Cannot find emscripten sdk, required for building native files. %24(EMSDK_PATH)=$(EMSDK_PATH)" />
+ Text="$(_EMSDKMissingErrorMessage) Emscripten SDK is required for building native files." />
<Error Condition="'$(RunAOTCompilation)' == 'true' and '$(_IsEMSDKMissing)' == 'true'"
- Text="Cannot find emscripten sdk, required for AOT'ing assemblies. %24(EMSDK_PATH)=$(EMSDK_PATH)" />
+ Text="$(_EMSDKMissingErrorMessage) Emscripten SDK is required for AOT'ing assemblies." />
<PropertyGroup>
<WasmBuildNative Condition="'$(RunAOTCompilation)' == 'true'">true</WasmBuildNative>
<!-- If we want to default to true, and sdk is missing, then just warn, and set it to false -->
<Warning Condition="'$(WasmBuildNative)' == 'true' and '$(_IsEMSDKMissing)' == 'true'"
- Text="Cannot find emscripten sdk, required for building native files. %24(EMSDK_PATH)=$(EMSDK_PATH). Skipping native relinking" />
+ Text="$(_EMSDKMissingErrorMessage) Emscripten SDK is required for building native files." />
<PropertyGroup>
<WasmBuildNative Condition="'$(WasmBuildNative)' == 'true' and '$(_IsEMSDKMissing)' == 'true'">false</WasmBuildNative>
</Target>
<Target Name="_WasmBuildNative" DependsOnTargets="_WasmAotCompileApp;_WasmStripAOTAssemblies;_GenerateDriverGenC;_CheckEmccIsExpectedVersion" Condition="'$(WasmBuildNative)' == 'true'">
- <Error Condition="'$(EMSDK_PATH)' == ''" Text="%24(EMSDK_PATH) should be set to emscripten sdk" />
+ <Error Condition="'$(EmscriptenSdkToolsPath)' == ''" Text="%24(EmscriptenSdkToolsPath) should be set to emscripten sdk" />
<PropertyGroup>
<EmccFlagsFile>$([MSBuild]::NormalizePath($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'src', 'emcc-flags.txt'))</EmccFlagsFile>
<EmccCFlags Condition="!$(_WasmIntermediateOutputPath.EndsWith('\'))">$(EmccCFlags) "-I$(_WasmIntermediateOutputPath)"</EmccCFlags>
<EmccLDFlags>$(EmccFlags) -s TOTAL_MEMORY=536870912</EmccLDFlags>
- <_WasmOptCommand>$([MSBuild]::NormalizePath('$(EMSDK_PATH)', 'upstream', 'bin', 'wasm-opt$(_ExeExt)'))</_WasmOptCommand>
+ <_WasmOptCommand>$([MSBuild]::NormalizePath('$(EmSdkUpstreamBinPath)', 'wasm-opt$(_ExeExt)'))</_WasmOptCommand>
</PropertyGroup>
<Message Text="Compiling native assets with emcc. This may take a while ..." Importance="High" />
- <RunWithEmSdkEnv Command='emcc $(EmccCFlags) "%(_WasmObjectsToBuild.SourcePath)" -c -o "%(_WasmObjectsToBuild.Identity)"' EmSdkPath="$(EMSDK_PATH)" />
- <RunWithEmSdkEnv Command="emcc $(EmccLDFlags) @(_DotnetJSSrcFile->'--js-library "%(Identity)"', ' ') @(_BitcodeFile->'"%(Identity)"', ' ') @(_WasmObjects->'"%(Identity)"', ' ') -o "$(_WasmIntermediateOutputPath)dotnet.js"" EmSdkPath="$(EMSDK_PATH)" />
- <RunWithEmSdkEnv Command='"$(_WasmOptCommand)" --strip-dwarf "$(_WasmIntermediateOutputPath)dotnet.wasm" -o "$(_WasmIntermediateOutputPath)dotnet.wasm"' Condition="'$(WasmNativeStrip)' == 'true'" IgnoreStandardErrorWarningFormat="true" EmSdkPath="$(EMSDK_PATH)" />
+ <Exec Command='emcc $(EmccCFlags) "%(_WasmObjectsToBuild.SourcePath)" -c -o "%(_WasmObjectsToBuild.Identity)"' EnvironmentVariables="@(EmscriptenEnvVars)" />
+ <Exec Command="emcc $(EmccLDFlags) @(_DotnetJSSrcFile->'--js-library "%(Identity)"', ' ') @(_BitcodeFile->'"%(Identity)"', ' ') @(_WasmObjects->'"%(Identity)"', ' ') -o "$(_WasmIntermediateOutputPath)dotnet.js"" EnvironmentVariables="@(EmscriptenEnvVars)" />
+ <Exec Command='"$(_WasmOptCommand)" --strip-dwarf "$(_WasmIntermediateOutputPath)dotnet.wasm" -o "$(_WasmIntermediateOutputPath)dotnet.wasm"' Condition="'$(WasmNativeStrip)' == 'true'" IgnoreStandardErrorWarningFormat="true" EnvironmentVariables="@(EmscriptenEnvVars)" />
<ItemGroup>
<WasmNativeAsset Include="$(_WasmIntermediateOutputPath)dotnet.wasm" />
<Output TaskParameter="Lines" PropertyName="RuntimeEmccVersion" />
</ReadLinesFromFile>
- <RunWithEmSdkEnv Command="emcc --version" WorkingDirectory="$(_WasmIntermediateOutputPath)" EmSdkPath="$(EMSDK_PATH)" ConsoleToMsBuild="true">
+ <Exec Command="emcc --version" WorkingDirectory="$(_WasmIntermediateOutputPath)" EnvironmentVariables="@(EmscriptenEnvVars)" ConsoleToMsBuild="true" StandardOutputImportance="Low">
<Output TaskParameter="ConsoleOutput" ItemName="_VersionLines" />
- </RunWithEmSdkEnv>
+ </Exec>
<!-- we want to get the first line from the output, which has the version.
Rest of the lines are the license -->