Skip to content
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

[NativeAOT-LLVM] Build on Linux #2574

Merged
merged 22 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from 21 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
2 changes: 1 addition & 1 deletion docs/using-nativeaot/prerequisites.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ The following pre-requisites need to be installed for building .NET projects wit
## Emscripten SDK

* Install and activate Emscripten. See [Install Emscripten](https://emscripten.org/docs/getting_started/downloads.html#installation-instructions-using-the-emsdk-recommended).
* We strongly recommend using the same version that we test against. Look for it here: [install-emscripten.cmd](https://github.com/dotnet/runtimelab/blob/feature/NativeAOT-LLVM/eng/pipelines/runtimelab/install-emscripten.cmd).
* We strongly recommend using the same version that we test against. Look for it here: [install-emscripten.ps1](https://github.com/dotnet/runtimelab/blob/feature/NativeAOT-LLVM/eng/pipelines/runtimelab/install-emscripten.ps1).
```
./emsdk install <version>
./emsdk activate <version>
Expand Down
2 changes: 1 addition & 1 deletion docs/workflow/building/coreclr/nativeaot.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The Native AOT toolchain can be currently built for Linux (x64/arm64), macOS (x6
There are two kinds of binary artifacts produced by the build and needed for development: the runtime libraries and the cross-targeting compilers, ILC and RyuJit. They are built differently and separately.

For the runtime libraries:
- Clone the [emsdk](https://github.com/emscripten-core/emsdk) repository and use the `emsdk.bat` script it comes with to [install](https://emscripten.org/docs/getting_started/downloads.html) (and optionally "activate", i. e. set the relevant environment variables permanently) the Emscripten SDK, which will be used by the native build as a sort of "virtualized" build environment. It is recommended to use the same Emscripten version that [the CI](https://github.com/dotnet/runtimelab/blob/feature/NativeAOT-LLVM/eng/pipelines/runtimelab/install-emscripten.cmd#L14-L18) uses.
- Clone the [emsdk](https://github.com/emscripten-core/emsdk) repository and use the `emsdk.bat` script it comes with to [install](https://emscripten.org/docs/getting_started/downloads.html) (and optionally "activate", i. e. set the relevant environment variables permanently) the Emscripten SDK, which will be used by the native build as a sort of "virtualized" build environment. It is recommended to use the same Emscripten version that [the CI](https://github.com/dotnet/runtimelab/blob/feature/NativeAOT-LLVM/eng/pipelines/runtimelab/install-emscripten.ps1#L16-L20) uses.
```
git clone https://github.com/emscripten-core/emsdk
cd emsdk
Expand Down
24 changes: 17 additions & 7 deletions eng/pipelines/common/global-build-job.yml
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,13 @@ jobs:

# Install Wasm dependencies: emscripten, LLVM, NodeJS
- ${{ if and(eq(parameters.runtimeFlavor, 'coreclr'), eq(parameters.archType, 'wasm')) }}:
- script: call $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-emscripten.cmd $(Build.SourcesDirectory)\wasm-tools
- script: pwsh $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-emscripten.ps1 $(Build.SourcesDirectory)/wasm-tools
displayName: Install/activate emscripten
- script: call $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-llvm.cmd $(Build.SourcesDirectory)\wasm-tools $(Build.SourcesDirectory) ${{ parameters.buildConfig }}
- script: call $(Build.SourcesDirectory)/eng/pipelines/runtimelab/set-cmake-path.cmd

Choose a reason for hiding this comment

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

I suspect this will need to be put under if eq(parameters.hostedOs, 'windows'), but let's leave that for the next change.

displayName: Set CMake path
- script: pwsh $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-llvm.ps1 -CI -InstallDir $(Build.SourcesDirectory)\wasm-tools -Configs ${{ parameters.buildConfig }}
displayName: Install/build LLVM
- script: call $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-nodejs.cmd $(Build.SourcesDirectory)\wasm-tools
- script: pwsh $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-nodejs.ps1 $(Build.SourcesDirectory)\wasm-tools
displayName: Install NodeJS

- ${{ if and(eq(parameters.runtimeFlavor, 'coreclr'), eq(parameters.platform, 'wasi_wasm_win')) }}:
Expand All @@ -222,10 +224,18 @@ jobs:
- script: call $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-wasmer.cmd $(Build.SourcesDirectory)\wasm-tools
displayName: Install wasmer

- ${{ if and(eq(parameters.osGroup, 'windows'), eq(parameters.archType, 'x64')) }}:
# Install LLVM for the win-x64 build as it will build the clrjit for browser_wasm cross compilation
- script: call $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-llvm.cmd $(Build.SourcesDirectory)\wasm-tools $(Build.SourcesDirectory) ${{ parameters.buildConfig }}
displayName: Install/build LLVM
- ${{ if eq(parameters.archType, 'x64') }}:
- ${{ if eq(parameters.osGroup, 'windows') }}:
- script: call $(Build.SourcesDirectory)/eng/pipelines/runtimelab/set-cmake-path.cmd
displayName: Set CMake path
- script: pwsh $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-llvm.ps1 -CI -InstallDir $(Build.SourcesDirectory)/wasm-tools -Configs ${{ parameters.buildConfig }}
displayName: Install/build LLVM
- ${{ if eq(parameters.osGroup, 'linux') }}:
- script: $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-pwsh.sh $(Build.SourcesDirectory)/wasm-tools
displayName: Install Powershell 7
# Install LLVM for the win-x64 and linux-x64 build as it will build the clrjit for browser_wasm cross compilation
- script: $(Build.SourcesDirectory)/wasm-tools/powershell7/pwsh $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-llvm.ps1 -CI -InstallDir $(Build.SourcesDirectory)/wasm-tools -Configs ${{ parameters.buildConfig }}

Choose a reason for hiding this comment

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

install-pwsh.sh sets PATH. Does a plain pwsh $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-llvm.ps1 ... not work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that will work, yes. Its not actually exercised with this PR but should be fine.

displayName: Install/build LLVM

Choose a reason for hiding this comment

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

This will install tools for host configurations (windows_x64, linux_x64) that do not actually target WASM. I think the LLVM stuff should be deleted for windows_x64 and Install Powershell 7 folded into the above block (under {{ if and(eq(parameters.runtimeFlavor, 'coreclr'), eq(parameters.archType, 'wasm')) }}:) under if ne(parameters.hostedOs, 'windows') (this way it will, hopefully, also work for macOS if/when that comes).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, done. The Linux build isn't pulling in these tools with this change but that's fine, they will be with #2569


- ${{ if or(eq(parameters.platform, 'browser_wasm_win'), and(eq(parameters.platform, 'wasi_wasm_win'), not(eq(parameters.runtimeFlavor, 'coreclr')))) }}:
# Update machine certs
Expand Down
4 changes: 1 addition & 3 deletions eng/pipelines/runtimelab.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ extends:
helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml
buildConfig: debug
platforms:
# - linux_x64
- osx_x64
- windows_x64
- Browser_wasm_win
Expand All @@ -81,7 +80,6 @@ extends:
helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml
buildConfig: checked
platforms:
# - linux_x64
- windows_x64
jobParameters:
timeoutInMinutes: 300
Expand All @@ -101,7 +99,7 @@ extends:
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
buildConfig: release
platforms:
# - linux_x64
- linux_x64
- osx_x64
- windows_x64
- Browser_wasm_win
Expand Down
25 changes: 0 additions & 25 deletions eng/pipelines/runtimelab/install-emscripten.cmd

This file was deleted.

23 changes: 23 additions & 0 deletions eng/pipelines/runtimelab/install-emscripten.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
param(
$InstallDir
)

$ErrorActionPreference="Stop"

New-Item -ItemType Directory -Force -Path $InstallDir

Set-Location -Path $InstallDir

git clone https://github.com/emscripten-core/emsdk.git

Set-Location -Path emsdk

# Checkout a specific commit to avoid unexpected issues
git checkout 37b85e9

./emsdk install 3.1.47

./emsdk activate 3.1.47

# Set a variable for later use (used in common/build.ps1)
Write-Host "##vso[task.setvariable variable=NATIVEAOT_CI_WASM_BUILD_EMSDK_PATH]$PWD"
22 changes: 0 additions & 22 deletions eng/pipelines/runtimelab/install-llvm.cmd

This file was deleted.

39 changes: 33 additions & 6 deletions eng/pipelines/runtimelab/install-llvm.ps1
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
[CmdletBinding(PositionalBinding=$false)]
param(
[ValidateSet("Debug","Release")][string[]]$Configs = @("Debug","Release"),
$InstallDir,
[ValidateSet("Debug","Release","Checked")][string[]]$Configs = @("Debug","Release"),
[switch]$CI,
[switch]$NoClone,
[switch]$NoBuild
)


$ErrorActionPreference="Stop"

New-Item -ItemType Directory -Path $InstallDir -Force
Set-Location -Path $InstallDir

# Set IsWindows if the version of Powershell does not already have it.
if (!(Test-Path variable:global:IsWindows))
{
$IsWindows = [Environment]::OSVersion.Platform -eq [PlatformID]::Win32NT
}

if (!(gcm git -ErrorAction SilentlyContinue))
{
Write-Error "Unable to find 'git' in PATH"
Expand All @@ -31,27 +42,43 @@ elseif (!(Test-Path llvm-project))
exit 1
}

foreach ($Config in $Configs)
# There is no [C/c]hecked LLVM config, so change to Debug
foreach ($Config in $Configs | % { if ($_ -eq "Checked") { "Debug" } else { $_ } } | Select-Object -Unique)
{
pushd llvm-project
$BuildDirName = "build-$($Config.ToLower())"
mkdir $BuildDirName -Force
New-Item -ItemType Directory $BuildDirName -Force

$BuildDirPath = "$pwd/$BuildDirName"
$SourceDirName = "$pwd/llvm"
popd

$CmakeConfigureCommandLine = "-G", "Visual Studio 17 2022", "-DLLVM_INCLUDE_BENCHMARKS=OFF", "-Thost=x64"
if ($IsWindows)
{
$CmakeGenerator = "Visual Studio 17 2022"
}
else
{
$CmakeGenerator = "Unix Makefiles"
}

$CmakeConfigureCommandLine = "-G", "$CmakeGenerator", "-DLLVM_INCLUDE_BENCHMARKS=OFF"
$CmakeConfigureCommandLine += "-S", $SourceDirName, "-B", $BuildDirPath
if ($Config -eq "Release")
{
$LlvmConfig = "Release"
$CmakeConfigureCommandLine += "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded"
if ($IsWindows)
{
$CmakeConfigureCommandLine += "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded", "-Thost=x64"
}
}
else
{
$LlvmConfig = "Debug"
$CmakeConfigureCommandLine += "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebug"
if ($IsWindows)
{
$CmakeConfigureCommandLine += "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebug", "-Thost=x64"
}
}
$CmakeConfigureCommandLine += "-DCMAKE_BUILD_TYPE=$LlvmConfig"

Expand Down
9 changes: 0 additions & 9 deletions eng/pipelines/runtimelab/install-nodejs.cmd

This file was deleted.

30 changes: 26 additions & 4 deletions eng/pipelines/runtimelab/install-nodejs.ps1
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
$InstallPath = $Args[0]
$NodeJSVersion = "v20.2.0"
$NodeJSInstallName = "node-$NodeJSVersion-win-x64"
$NodeJSZipName = "$NodeJSInstallName.zip"

if (!(Test-Path variable:global:IsWindows))
{
$IsWindows = [Environment]::OSVersion.Platform -eq [PlatformID]::Win32NT
}

if ($IsWIndows)
{
$NodeJSInstallName = "node-$NodeJSVersion-win-x64"
$NodeJSZipName = "$NodeJSInstallName.zip"
}
else
{
$NodeJSInstallName = "node-$NodeJSVersion-linux-x64"
$NodeJSZipName = "$NodeJSInstallName.tar.xz"
}

if (!(Test-Path $InstallPath))
{
Expand Down Expand Up @@ -33,9 +47,17 @@ if ($RetryCount -le 0)
exit 1
}

Expand-Archive -LiteralPath "$InstallPath\$NodeJSInstallName.zip" -DestinationPath $InstallPath -Force
if ($IsWindows)
{
Expand-Archive -LiteralPath "$InstallPath\$NodeJSZipName" -DestinationPath $InstallPath -Force
$NodeJSExePath = "$InstallPath\$NodeJSInstallName\node.exe"
Comment on lines +52 to +53

Choose a reason for hiding this comment

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

Does Expand-Archive not work on Linux (it's a bit surprising)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It does, but doesn't support gz which is gzip, or xz which is some LZMA I think.

Copy link
Contributor Author

@yowl yowl May 10, 2024

Choose a reason for hiding this comment

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

And those are our options for linux https://nodejs.org/dist/v9.9.0/

}
else
{
tar xJf $InstallPath/$NodeJSZipName -C $InstallPath
$NodeJSExePath = "$InstallPath/$NodeJSInstallName/bin/node"
}

$NodeJSExePath = "$InstallPath\$NodeJSInstallName\node.exe"
if (!(Test-Path $NodeJSExePath))
{
Write-Error "Did not find NodeJS at: '$NodeJSExePath'"
Expand Down
19 changes: 19 additions & 0 deletions eng/pipelines/runtimelab/install-pwsh.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env bash

mkdir -p $1

cd $1

curl -L -o powershell.tar.gz https://github.com/PowerShell/PowerShell/releases/download/v7.3.12/powershell-7.3.12-linux-x64.tar.gz

# Create the target folder where powershell will be placed
mkdir powershell7

# Expand powershell to the target folder
tar zxf powershell.tar.gz -C powershell7

# Set execute permissions
chmod +x powershell7/pwsh

echo setting PATH
echo ##vso[task.setvariable variable=PATH]$PATH:$1/powershell7
10 changes: 10 additions & 0 deletions eng/pipelines/runtimelab/set-cmake-path.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Save the current PATH because init-vs-env.cmd will add enough to the PATH that calling it twice
# will exceed the command length limit.
set OLD_PATH=%PATH%
call "%RepoRoot%eng\native\init-vs-env.cmd" wasm || exit /b 1

call set CMakeDir=%%CMakePath:\cmake.exe=%%

echo CMakeDir is %CMakeDir%
echo Setting PATH to %OLD_PATH%;%CMakeDir%
echo ##vso[task.setvariable variable=PATH]%OLD_PATH%;%CMakeDir%
20 changes: 20 additions & 0 deletions src/coreclr/build-runtime.sh
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,26 @@ if [[ -n "$__RequestedBuildComponents" ]]; then
__CMakeTarget=" $__RequestedBuildComponents "
__CMakeTarget="${__CMakeTarget// paltests / paltests_install }"
fi

if [[ "$__CMakeTarget" == *"wasmjit"* ]]; then
__CMakeArgs="$__CMakeArgs -DCLR_CMAKE_BUILD_LLVM_JIT=1"

if [[ "$__BuildType" == "Release" ]]; then
if [[ -n $LLVM_CMAKE_CONFIG_RELEASE ]]; then
LLVM_CMAKE_CONFIG="$LLVM_CMAKE_CONFIG_RELEASE"
fi
else
if [[ -n $LLVM_CMAKE_CONFIG_DEBUG ]]; then
LLVM_CMAKE_CONFIG="$LLVM_CMAKE_CONFIG_DEBUG"
fi
fi

if [[ -z "$LLVM_CMAKE_CONFIG" ]]; then
echo The LLVM_CMAKE_CONFIG environment variable pointing to llvm-build-dir/lib/cmake/llvm must be set. 1>&2
exit 1
fi
fi

if [[ -z "$__CMakeTarget" ]]; then
__CMakeTarget="install"
fi
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/jit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ function(create_standalone_jit)
# We'll be linking against LLVM built without /guard:ehcont, so disable it.
set_target_properties(${TARGETDETAILS_TARGET} PROPERTIES CLR_EH_CONTINUATION OFF)

find_package(LLVM REQUIRED CONFIG PATHS $ENV{LLVM_CMAKE_CONFIG})
# Only look at "our" LLVM with LLVM_CMAKE_CONFIG.
find_package(LLVM REQUIRED CONFIG PATHS $ENV{LLVM_CMAKE_CONFIG} NO_DEFAULT_PATH)
target_include_directories(${TARGETDETAILS_TARGET} PRIVATE ${LLVM_INCLUDE_DIRS})
separate_arguments(LLVM_DEFINITIONS)
target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE ${LLVM_DEFINITIONS})
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/nativeaot/Runtime/unix/UnixContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
// WASM has no thread state contexts.
#ifndef HOST_WASM

#include <ucontext.h>

// Convert Unix native context to PAL_LIMITED_CONTEXT
void NativeContextToPalContext(const void* context, PAL_LIMITED_CONTEXT* palContext);
// Redirect Unix native context to the PAL_LIMITED_CONTEXT and also set the first two argument registers
Expand Down
1 change: 1 addition & 0 deletions src/native/libs/build-native.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ __usePThreads=0
source "$__RepoRootDir"/eng/native/build-commons.sh

# Set cross build
EMSDK_PATH=$EMSDK
if [[ "$__TargetOS" == browser ]]; then
if [[ -z "$EMSDK_PATH" ]]; then
if [[ -d "$__RepoRootDir"/src/mono/browser/emsdk/ ]]; then
Expand Down