Skip to content

Commit

Permalink
Add beginnings of WebAssembly build support for mono. (#33551)
Browse files Browse the repository at this point in the history
* Set emcc as the compiler for libraries build

* Add default subsets for webassembly build

* Fix various problems in the build

* Use WebAssembly Docker image

* Use Mono runtime for webassembly builds

Co-authored-by: Alexander Köplinger <[email protected]>
  • Loading branch information
vargaz and akoeplinger authored Apr 10, 2020
1 parent b5f5d71 commit fd4831f
Show file tree
Hide file tree
Showing 19 changed files with 104 additions and 48 deletions.
3 changes: 2 additions & 1 deletion eng/Subsets.props
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<PropertyGroup>
<DefaultSubsets>clr+mono+libs+installer</DefaultSubsets>
<DefaultSubsets Condition="'$(TargetOS)' == 'iOS' or '$(TargetOS)' == 'Android' or '$(TargetOS)' == 'tvOS'">mono+libs+installer</DefaultSubsets>
<DefaultSubsetCategories Condition="'$(TargetOS)' == 'WebAssembly'">mono+libs</DefaultSubsetCategories>
</PropertyGroup>

<PropertyGroup>
Expand Down Expand Up @@ -66,7 +67,7 @@
</PropertyGroup>

<PropertyGroup>
<RuntimeFlavor Condition="'$(TargetOS)' == 'tvOS' or '$(TargetOS)' == 'iOS' or '$(TargetOS)' == 'Android'">Mono</RuntimeFlavor>
<RuntimeFlavor Condition="'$(TargetOS)' == 'tvOS' or '$(TargetOS)' == 'iOS' or '$(TargetOS)' == 'Android' or '$(TargetOS)' == 'WebAssembly'">Mono</RuntimeFlavor>
<RuntimeFlavor Condition="'$(RuntimeFlavor)' == '' and $(_subset.Contains('+mono.runtime+')) and !$(_subset.Contains('+clr.runtime+'))">Mono</RuntimeFlavor>
<RuntimeFlavor Condition="'$(RuntimeFlavor)' == ''">CoreCLR</RuntimeFlavor>
</PropertyGroup>
Expand Down
9 changes: 7 additions & 2 deletions eng/native/build-commons.sh
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,13 @@ build_native()

popd
else
echo "Executing cmake --build \"$intermediatesDir\" --target install -j $__NumProc"
cmake --build "$intermediatesDir" --target install -j "$__NumProc"
cmake_command=cmake
if [[ "$build_arch" == "wasm" ]]; then
cmake_command="emcmake $cmake_command"
fi

echo "Executing $cmake_command --build \"$intermediatesDir\" --target install -j $__NumProc"
$cmake_command --build "$intermediatesDir" --target install -j "$__NumProc"
fi

local exit_code="$?"
Expand Down
20 changes: 17 additions & 3 deletions eng/native/configureplatform.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ if(CLR_CMAKE_HOST_OS STREQUAL Windows)
endif(CLR_CMAKE_HOST_OS STREQUAL Windows)

if(CLR_CMAKE_HOST_OS STREQUAL Emscripten)
set(CLR_CMAKE_HOST_ARCH_WASM 1)
#set(CLR_CMAKE_HOST_UNIX 1) # TODO: this should be reenabled but it activates a bunch of additional compiler flags in configurecompiler.cmake
set(CLR_CMAKE_HOST_UNIX_WASM 1)
endif(CLR_CMAKE_HOST_OS STREQUAL Emscripten)

#--------------------------------------------
Expand Down Expand Up @@ -196,6 +197,9 @@ elseif(CLR_CMAKE_HOST_UNIX_AMD64)
elseif(CLR_CMAKE_HOST_UNIX_X86)
set(CLR_CMAKE_HOST_ARCH_I386 1)
set(CLR_CMAKE_HOST_ARCH "x86")
elseif(CLR_CMAKE_HOST_UNIX_WASM)
set(CLR_CMAKE_HOST_ARCH_WASM 1)
set(CLR_CMAKE_HOST_ARCH "wasm")
elseif(WIN32)
# CLR_CMAKE_HOST_ARCH is passed in as param to cmake
if (CLR_CMAKE_HOST_ARCH STREQUAL x64)
Expand Down Expand Up @@ -237,6 +241,8 @@ if (CLR_CMAKE_TARGET_ARCH STREQUAL x64)
set(CLR_CMAKE_TARGET_ARCH_ARM 1)
set(CLR_CMAKE_TARGET_ARCH_ARMV7L 1)
set(ARM_SOFTFP 1)
elseif(CLR_CMAKE_TARGET_ARCH STREQUAL wasm)
set(CLR_CMAKE_TARGET_ARCH_WASM 1)
else()
clr_unknown_arch()
endif()
Expand Down Expand Up @@ -306,6 +312,12 @@ if(CLR_CMAKE_TARGET_OS STREQUAL SunOS)
set(CLR_CMAKE_TARGET_SUNOS 1)
endif(CLR_CMAKE_TARGET_OS STREQUAL SunOS)

if(CLR_CMAKE_TARGET_OS STREQUAL Emscripten)
set(CLR_CMAKE_TARGET_UNIX 1)
set(CLR_CMAKE_TARGET_LINUX 1)
set(CLR_CMAKE_TARGET_EMSCRIPTEN 1)
endif(CLR_CMAKE_TARGET_OS STREQUAL Emscripten)

if(CLR_CMAKE_TARGET_UNIX)
if(CLR_CMAKE_TARGET_ARCH STREQUAL x64)
set(CLR_CMAKE_TARGET_UNIX_AMD64 1)
Expand All @@ -317,6 +329,8 @@ if(CLR_CMAKE_TARGET_UNIX)
set(CLR_CMAKE_TARGET_UNIX_ARM64 1)
elseif(CLR_CMAKE_TARGET_ARCH STREQUAL x86)
set(CLR_CMAKE_TARGET_UNIX_X86 1)
elseif(CLR_CMAKE_TARGET_ARCH STREQUAL wasm)
set(CLR_CMAKE_TARGET_UNIX_WASM 1)
else()
clr_unknown_arch()
endif()
Expand All @@ -343,7 +357,7 @@ else()
endif()
endif()

if(NOT CLR_CMAKE_HOST_ARCH_WASM)
if(NOT CLR_CMAKE_TARGET_EMSCRIPTEN)
# Skip check_pie_supported call on Android as ld from llvm toolchain with NDK API level 21
# complains about missing linker flag `-no-pie` (while level 28's ld does support this flag,
# but since we know that PIE is supported, we can safely skip this redundant check).
Expand All @@ -363,7 +377,7 @@ if(NOT CLR_CMAKE_HOST_ARCH_WASM)
endif(NOT CLR_CMAKE_TARGET_ANDROID)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif(NOT CLR_CMAKE_HOST_ARCH_WASM)
endif(NOT CLR_CMAKE_TARGET_EMSCRIPTEN)

string(TOLOWER "${CMAKE_BUILD_TYPE}" LOWERCASE_CMAKE_BUILD_TYPE)
if(LOWERCASE_CMAKE_BUILD_TYPE STREQUAL debug)
Expand Down
2 changes: 1 addition & 1 deletion eng/native/configuretools.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ if (CMAKE_C_COMPILER MATCHES "-?[0-9]+(\.[0-9]+)?$")
set(CLR_CMAKE_COMPILER_FILE_NAME_VERSION "${CMAKE_MATCH_0}")
endif()

if(NOT WIN32)
if(NOT WIN32 AND NOT CLR_CMAKE_TARGET_ARCH_WASM)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(APPLE)
set(TOOLSET_PREFIX "")
Expand Down
4 changes: 4 additions & 0 deletions eng/native/gen-buildsys.sh
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ if [[ "$scan_build" == "ON" && -n "$SCAN_BUILD_COMMAND" ]]; then
cmake_command="$SCAN_BUILD_COMMAND $cmake_command"
fi

if [[ "$build_arch" == "wasm" ]]; then
cmake_command="emcmake $cmake_command"
fi

# Include CMAKE_USER_MAKE_RULES_OVERRIDE as uninitialized since it will hold its value in the CMake cache otherwise can cause issues when branch switching
$cmake_command \
-G "$generator" \
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/common/platform-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ jobs:
archType: wasm
platform: WebAssembly_wasm
container:
image: ubuntu-16.04-20200401182342-fe8b85d
image: ubuntu-18.04-webassembly-20200409132031-f70ea41
registry: mcr
jobParameters:
runtimeFlavor: ${{ parameters.runtimeFlavor }}
Expand Down
5 changes: 1 addition & 4 deletions eng/pipelines/libraries/base-job.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ jobs:
- ${{ if and(eq(parameters.osGroup, 'Linux'), eq(parameters.osSubGroup, ''), eq(parameters.archType, 'arm')) }}:
- _runtimeOSArg: /p:RuntimeOS=ubuntu.16.04

# force a value for OS when cross-building WebAssembly
- ${{ if eq(parameters.osGroup, 'WebAssembly') }}:
- _runtimeOSArg: -os ${{ parameters.osGroup }}

Expand Down Expand Up @@ -107,10 +108,6 @@ jobs:
- _runtimeArtifactsPathArg: ' /p:RuntimeArtifactsPath=$(_runtimeDownloadPath)'
- _testRunNamePrefixSuffix: $(runtimeFlavorName)_${{ parameters.liveRuntimeBuildConfig }}

# WebAssembly uses linux implementation detail
- ${{ if eq(parameters.osGroup, 'WebAssembly') }}:
- _runtimeArtifactName: 'CoreLib_Linux_x64_${{ parameters.liveRuntimeBuildConfig }}'

# Windows variables
- ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
- _runtimeOSArg: /p:RuntimeOS=win10
Expand Down
24 changes: 6 additions & 18 deletions eng/pipelines/libraries/build-job.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,18 @@ jobs:

${{ if ne(parameters.liveRuntimeBuildConfig, '') }}:
dependsOn:
- ${{ if ne(parameters.osGroup, 'WebAssembly') }}:
# Use corelib dependencies for coreclr and non test builds
- ${{ if and(eq(parameters.runtimeFlavor, 'coreclr'), eq(parameters.testScope, '')) }}:
- ${{ format('coreclr_corelib_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveRuntimeBuildConfig) }}
- ${{ if or(ne(parameters.runtimeFlavor, 'coreclr'), ne(parameters.testScope, '')) }}:
- ${{ format('{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeFlavor, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveRuntimeBuildConfig) }}
- ${{ if eq(parameters.osGroup, 'WebAssembly') }}:
- ${{ format('coreclr_corelib_build_{1}{2}_{3}_{4}', parameters.runtimeFlavor, 'linux', parameters.osSubgroup, 'x64', parameters.liveRuntimeBuildConfig) }}
# Use corelib dependencies for coreclr and non test builds
- ${{ if and(eq(parameters.runtimeFlavor, 'coreclr'), eq(parameters.testScope, '')) }}:
- ${{ format('coreclr_corelib_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveRuntimeBuildConfig) }}
- ${{ if or(ne(parameters.runtimeFlavor, 'coreclr'), ne(parameters.testScope, '')) }}:
- ${{ format('{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeFlavor, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveRuntimeBuildConfig) }}

variables:
- _subset: libs
- _addtionalBuildArguments: ''
- ${{ parameters.variables }}
- ${{ if eq(parameters.osGroup, 'WebAssembly') }}:
- EMSDK_PATH: $(Build.BinariesDirectory)/emsdk
- EMSDK_PATH: /usr/local/emscripten
- ${{ if eq(parameters.runTests, true) }}:
- _subset: libs+libs.tests
- _addtionalBuildArguments: /p:ArchiveTests=true
Expand All @@ -80,15 +77,6 @@ jobs:
ln -s /usr/local/opt/openssl/lib/pkgconfig/openssl.pc /usr/local/lib/pkgconfig/
displayName: Install Build Dependencies
- ${{ if eq(parameters.osGroup, 'WebAssembly') }}:
- script: |
EMSCRIPTEN_VERSION=1.38.47
git clone https://github.com/emscripten-core/emsdk.git $(EMSDK_PATH)
cd $(EMSDK_PATH)
./emsdk install ${EMSCRIPTEN_VERSION}-upstream
./emsdk activate --embedded ${EMSCRIPTEN_VERSION}-upstream
displayName: Install Emscripten
- ${{ if eq(parameters.isOfficialBuild, true) }}:
- template: /eng/pipelines/common/restore-internal-tools.yml
parameters:
Expand Down
7 changes: 7 additions & 0 deletions eng/pipelines/mono/templates/build-job.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ jobs:
- ${{ if eq(parameters.osGroup, 'Android') }}:
- name: osOverride
value: -os Android
- ${{ if eq(parameters.osGroup, 'WebAssembly') }}:
- name: EMSDK_PATH
value: /usr/local/emscripten
- name: archType
value: wasm
- name: osOverride
value: '-os WebAssembly'
- ${{ parameters.variables }}

steps:
Expand Down
5 changes: 4 additions & 1 deletion eng/pipelines/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ jobs:
- Linux_arm
- Linux_arm64
- Linux_musl_x64
- WebAssembly_wasm
# - Linux_musl_arm64
- Windows_NT_x64
# - Windows_NT_x86
Expand Down Expand Up @@ -302,6 +303,7 @@ jobs:
- Linux_arm
- Linux_arm64
- Linux_musl_x64
- WebAssembly_wasm
# - Linux_musl_arm64
- Windows_NT_x64
# - Windows_NT_x86
Expand Down Expand Up @@ -420,6 +422,7 @@ jobs:
# - iOS_arm # https://github.com/dotnet/runtime/issues/34465
- iOS_arm64
- iOS_x64
- WebAssembly_wasm
jobParameters:
liveRuntimeBuildConfig: release

Expand All @@ -438,6 +441,7 @@ jobs:
# - iOS_arm # https://github.com/dotnet/runtime/issues/34465
- iOS_arm64
- iOS_x64
- WebAssembly_wasm
jobParameters:
liveRuntimeBuildConfig: debug

Expand All @@ -449,7 +453,6 @@ jobs:
jobTemplate: /eng/pipelines/libraries/build-job.yml
buildConfig: ${{ variables.debugOnPrReleaseOnRolling }}
platforms:
- WebAssembly_wasm
- ${{ if eq(variables['isFullMatrix'], false) }}:
- Windows_NT_x86
jobParameters:
Expand Down
3 changes: 3 additions & 0 deletions src/libraries/Native/Unix/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ elseif (CLR_CMAKE_TARGET_ARCH_I386)
add_definitions(-DTARGET_32BIT=1)
add_definitions(-DTARGET_X86)
add_definitions(-D_FILE_OFFSET_BITS=64)
elseif (CLR_CMAKE_TARGET_ARCH_WASM)
add_definitions(-DTARGET_32BIT=1)
add_definitions(-DTARGET_WASM)
elseif (CLR_CMAKE_TARGET_ARCH_ARM64)
add_definitions(-DTARGET_64BIT=1)
add_definitions(-DTARGET_ARM64)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
project(System.IO.Compression.Native C)

if (CLR_CMAKE_TARGET_WASM)
if (CLR_CMAKE_TARGET_ARCH_WASM)
add_definitions(-s USE_ZLIB)
elseif (CLR_CMAKE_TARGET_ANDROID)
# need special case here since we want to link against libz.so but find_package() would resolve libz.a
Expand Down
2 changes: 1 addition & 1 deletion src/libraries/Native/Unix/System.Native/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ else ()
set(NATIVE_SOURCES ${NATIVE_SOURCES} pal_console.c)
endif ()

if (CLR_CMAKE_TARGET_LINUX)
if (CLR_CMAKE_TARGET_LINUX AND NOT CLR_CMAKE_TARGET_ARCH_WASM)
set(NATIVE_SOURCES ${NATIVE_SOURCES} pal_networkchange.c)

if (!HAVE_LINUX_RTNETLINK_H)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ int32_t SystemNative_GetOSArchitecture()
return ARCH_ARM64;
#elif defined(TARGET_AMD64)
return ARCH_X64;
#elif defined(TARGET_X86)
#elif defined(TARGET_X86) || defined(TARGET_WASM) // TODO: add arch for WASM
return ARCH_X86;
#else
#error Unidentified Architecture
Expand All @@ -71,7 +71,7 @@ int32_t SystemNative_GetProcessArchitecture()
return ARCH_ARM64;
#elif defined(TARGET_AMD64)
return ARCH_X64;
#elif defined(TARGET_X86)
#elif defined(TARGET_X86) || defined(TARGET_WASM) // TODO: add arch for WASM
return ARCH_X86;
#else
#error Unidentified Architecture
Expand Down
6 changes: 3 additions & 3 deletions src/libraries/Native/Unix/configure.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ include(CheckTypeSize)

if (CLR_CMAKE_TARGET_ANDROID)
set(PAL_UNIX_NAME \"ANDROID\")
elseif (CLR_CMAKE_TARGET_ARCH_WASM)
set(PAL_UNIX_NAME \"WEBASSEMBLY\")
elseif (CLR_CMAKE_TARGET_LINUX)
set(PAL_UNIX_NAME \"LINUX\")
elseif (CLR_CMAKE_TARGET_OSX)
Expand All @@ -28,8 +30,6 @@ elseif (CLR_CMAKE_TARGET_FREEBSD)
set(CMAKE_REQUIRED_INCLUDES ${CROSS_ROOTFS}/usr/local/include)
elseif (CLR_CMAKE_TARGET_NETBSD)
set(PAL_UNIX_NAME \"NETBSD\")
elseif (CLR_CMAKE_TARGET_ARCH_WASM)
set(PAL_UNIX_NAME \"WEBASSEMBLY\")
else ()
message(FATAL_ERROR "Unknown platform. Cannot define PAL_UNIX_NAME, used by RuntimeInformation.")
endif ()
Expand Down Expand Up @@ -839,7 +839,7 @@ set (CMAKE_REQUIRED_LIBRARIES ${PREVIOUS_CMAKE_REQUIRED_LIBRARIES})
set (HAVE_INOTIFY 0)
if (HAVE_INOTIFY_INIT AND HAVE_INOTIFY_ADD_WATCH AND HAVE_INOTIFY_RM_WATCH)
set (HAVE_INOTIFY 1)
elseif (CLR_CMAKE_TARGET_LINUX)
elseif (CLR_CMAKE_TARGET_LINUX AND NOT CLR_CMAKE_TARGET_ARCH_WASM)
message(FATAL_ERROR "Cannot find inotify functions on a Linux platform.")
endif()

Expand Down
5 changes: 4 additions & 1 deletion src/libraries/Native/build-native.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,13 @@ source "$__RepoRootDir"/eng/native/build-commons.sh

if [[ "$__BuildArch" == wasm ]]; then
if [[ -z "$EMSDK_PATH" ]]; then
echo "Error: Should set EMSDK_PATH environment variable pointing to emsdk root."
echo "Error: You need to set the EMSDK_PATH environment variable pointing to the emscripten SDK root."
exit 1
fi
source "$EMSDK_PATH"/emsdk_env.sh

export CLR_CC=$(which emcc)
export CLR_CXX=$(which em++)
elif [[ "$__TargetOS" == iOS ]]; then
# nothing to do here
true
Expand Down
3 changes: 2 additions & 1 deletion src/mono/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@
<TargetsiOSSimulator Condition="'$(TargetsiOS)' == 'true' and '$(Platform)' == 'x64'">true</TargetsiOSSimulator>
<TargetstvOSSimulator Condition="'$(TargetstvOS)' == 'true' and '$(Platform)' == 'x64'">true</TargetstvOSSimulator>
<TargetsAndroid Condition="'$(TargetOS)' == 'Android'">true</TargetsAndroid>
<TargetsWASM Condition="'$(TargetOS)' == 'WebAssembly'">true</TargetsWASM>
<TargetsWindows Condition="'$(TargetOS)' == 'Windows_NT'">true</TargetsWindows>
<TargetsUnix Condition="'$(TargetsFreeBSD)' == 'true' or '$(TargetsLinux)' == 'true' or '$(TargetsNetBSD)' == 'true' or '$(TargetsOSX)' == 'true' or '$(TargetstvOS)' == 'true' or '$(TargetsiOS)' == 'true' or '$(TargetsAndroid)' == 'true'">true</TargetsUnix>
<TargetsUnix Condition="'$(TargetsFreeBSD)' == 'true' or '$(TargetsLinux)' == 'true' or '$(TargetsNetBSD)' == 'true' or '$(TargetsOSX)' == 'true' or '$(TargetstvOS)' == 'true' or '$(TargetsiOS)' == 'true' or '$(TargetsAndroid)' == 'true' or '$(TargetsWASM)' == 'true'">true</TargetsUnix>
</PropertyGroup>

<PropertyGroup>
Expand Down
Loading

0 comments on commit fd4831f

Please sign in to comment.