Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
45 changes: 39 additions & 6 deletions .vsts-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,35 @@ extends:
testRunnerAdditionalArguments: -class Microsoft.DotNet.Cli.New.IntegrationTests.DotnetNewTestTemplatesTests
publishXunitResults: true

### AOT (win-arm64 cross-build) ###
# dotnet-aot is built with NativeAOT, which can cross-compile win-x64 -> win-arm64 (the MSVC
# arm64 linker and the RID-specific ILCompiler package handle the cross-link; no sysroot is
# required). This leg therefore BUILDS on the existing win-x64 pool with /p:CrossBuild=true and
# produces the dotnet-aot .dll plus its mstat/dgml size-analysis artifacts (that step is gated
# on runAoTTests). It is build-only (runTests: false): there is no wired windows arm64 Helix
# queue yet, so running the *.AoT.Tests on arm64 hardware is a follow-up pending a
# windows.11.arm64 queue. Runs for internal PRs and test builds.
- ${{ if or(eq(parameters.runTestBuild, true), eq(variables['Build.Reason'], 'PullRequest')) }}:
- template: /eng/pipelines/templates/jobs/sdk-job-matrix.yml@self
parameters:
pool:
name: $(DncEngInternalBuildPool)
image: windows.vs2022.amd64
os: windows
helixTargetQueue: windows.amd64.vs2026.pre.scout
oneESCompat:
templateFolderName: templates-official
publishTaskPrefix: 1ES.
populateInternalRuntimeVariables: true
runtimeSourceProperties: /p:DotNetRuntimeSourceFeed=https://ci.dot.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64)
windowsJobParameterSets:
- categoryName: AoT
runAoTTests: true
targetArchitecture: arm64
runtimeIdentifier: win-arm64
osProperties: /p:CrossBuild=true
runTests: false

############### LINUX ###############
- template: /eng/pipelines/templates/jobs/sdk-job-matrix.yml@self
parameters:
Expand Down Expand Up @@ -314,17 +343,20 @@ extends:
publishArgument: $(_publishArgument)
officialBuildProperties: $(_officialBuildProperties)
runTests: false
### AOT (native arm64) ###
# The AoT leg builds dotnet-aot via NativeAOT, which cannot cross-compile, so it must
# run on native arm64 hardware (HostRid == TargetRid == osx-arm64) to produce the
# dotnet-aot .dylib and its mstat/dgml size-analysis output. Runs for internal PRs and
# test builds; official builds publish via the Official legs above and don't need it.
### AOT (osx-arm64 cross-build) ###
# dotnet-aot is built with NativeAOT, which can cross-compile osx-x64 -> osx-arm64 (clang/link
# on macOS are multi-target and need no extra sysroot). This leg therefore BUILDS on the x64
# macOS pool (the Official osx-arm64 leg already cross-builds on macOS-latest/x64) with
# /p:CrossBuild=true. Because AoT tests are dispatched to Helix (runTests passes
# -test /p:CustomHelixTargetQueue=...), the *.AoT.Tests still execute on the osx.15.arm64
# Helix queue, so there is no macOS AoT test-coverage loss. Runs for internal PRs and test
# builds; official builds publish via the Official legs above and don't need it.
- ${{ if or(eq(parameters.runTestBuild, true), eq(variables['Build.Reason'], 'PullRequest')) }}:
- template: /eng/pipelines/templates/jobs/sdk-job-matrix.yml@self
parameters:
pool:
name: Azure Pipelines
vmImage: macOS-15-arm64
vmImage: macOS-latest
Comment thread
baronfel marked this conversation as resolved.
Resolved
os: macOS
helixTargetQueue: osx.15.arm64
oneESCompat:
Expand All @@ -337,6 +369,7 @@ extends:
runAoTTests: true
targetArchitecture: arm64
runtimeIdentifier: osx-arm64
osProperties: /p:CrossBuild=true
### ARM64 TESTBUILD ###
- ${{ if and(or(eq(parameters.runTestBuild, true), eq(variables['Build.Reason'], 'PullRequest')), eq(parameters.enableArm64Job, true)) }}:
- template: /eng/pipelines/templates/jobs/sdk-job-matrix.yml@self
Expand Down
31 changes: 29 additions & 2 deletions .vsts-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,28 @@ stages:
os: windows
helixTargetQueue: windows.amd64.vs2026.pre.scout.open

### AoT (win-arm64 cross-build) ###
# dotnet-aot is built with NativeAOT, which can cross-compile win-x64 -> win-arm64 (the MSVC arm64
# linker and the RID-specific ILCompiler package handle the cross-link; no sysroot is required).
# This leg BUILDS on the win-x64 pool with /p:CrossBuild=true and produces the dotnet-aot .dll plus
# its mstat/dgml size-analysis artifacts (that step is gated on runAoTTests). It is build-only
# (runTests: false): there is no wired windows arm64 Helix queue yet, so running the *.AoT.Tests on
# arm64 hardware is a follow-up pending a windows.11.arm64 queue.
- template: /eng/pipelines/templates/jobs/sdk-job-matrix.yml@self
parameters:
pool:
name: $(DncEngPublicBuildPool)
demands: ImageOverride -equals windows.vs2022.amd64.open
os: windows
helixTargetQueue: windows.amd64.vs2026.pre.scout.open
windowsJobParameterSets:
- categoryName: AoT
runAoTTests: true
targetArchitecture: arm64
runtimeIdentifier: win-arm64
osProperties: /p:CrossBuild=true
runTests: false

############### LINUX ###############
- template: /eng/pipelines/templates/jobs/sdk-job-matrix.yml
parameters:
Expand Down Expand Up @@ -106,19 +128,24 @@ stages:
vmImage: macOS-latest
os: macOS
helixTargetQueue: osx.15.arm64.open
### AoT (native arm64) ###
### AoT (osx-arm64 cross-build) ###
# dotnet-aot is built with NativeAOT, which can cross-compile osx-x64 -> osx-arm64 (clang/link on
# macOS are multi-target and need no extra sysroot). This leg BUILDS on the x64 macOS pool with
# /p:CrossBuild=true; because AoT tests are dispatched to Helix, the *.AoT.Tests still run on the
# osx.15.arm64 Helix queue, so there is no macOS AoT test-coverage loss.
- template: /eng/pipelines/templates/jobs/sdk-job-matrix.yml
parameters:
pool:
name: Azure Pipelines
vmImage: macOS-15-arm64
vmImage: macOS-latest
os: macOS
helixTargetQueue: osx.15.arm64.open
macOSJobParameterSets:
- categoryName: AoT
runAoTTests: true
targetArchitecture: arm64
runtimeIdentifier: osx-arm64
osProperties: /p:CrossBuild=true
### x64 (CI only) ###
- ${{ if ne(variables['Build.Reason'], 'PullRequest') }}:
- template: /eng/pipelines/templates/jobs/sdk-job-matrix.yml
Expand Down
1 change: 1 addition & 0 deletions eng/pipelines/templates/jobs/sdk-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ jobs:
/p:EnableDefaultArtifacts=${{ parameters.enableDefaultArtifacts }}
/p:TargetArchitecture=${{ parameters.targetArchitecture }}
/p:PgoInstrument=${{ parameters.pgoInstrument }}
${{ parameters.osProperties }}
${{ parameters.runtimeSourceProperties }}
${{ parameters.officialBuildProperties }}
/p:DotNetSignType=$(_SignType) /p:TeamName=$(_TeamName)
Expand Down
52 changes: 38 additions & 14 deletions src/Layout/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,46 @@
in redist/targets/GenerateLayout.targets). This is shared by that target and by the
dotnet-aot.csproj ProjectReference in redist.csproj so the two stay in sync.

It is published for supported win/linux/osx RIDs in these cases:
* native builds, where the target RID matches the build host. On win/osx that is an exact
TargetRid == HostRid comparison. On Linux, HostRid is the distro-specific RID (e.g.
azurelinux.3-x64) while TargetRid is the portable RID (e.g. linux-x64), so an exact
comparison fails even for a native build. Following the VMR/arcade convention, a Linux
build is treated as native when it isn't a cross-build (TargetArchitecture ==
BuildArchitecture) and the build host OS is Linux.
* Linux cross-builds, where NativeAOT targets another architecture from an x64 Linux host.
NativeAOT can cross-compile as long as a cross toolchain and target sysroot are available
(CrossBuild=true, with ROOTFS_DIR provided by the azurelinux cross-prereq build
containers). Cross-compilation across operating systems is not supported.
NativeAOT can produce the dotnet-aot library for the build host's operating system, either
natively (targeting the host architecture) or cross-compiling to another architecture of the
*same* OS. Cross-compilation across operating systems is not supported. We therefore publish
for supported win/linux/osx RIDs whenever the target OS equals the build host OS:
* native builds, where the target architecture matches the build host architecture
(TargetArchitecture == BuildArchitecture). We do not compare TargetRid == HostRid
directly: on Linux HostRid is the distro-specific RID (e.g. azurelinux.3-x64) while
TargetRid is the portable RID (e.g. linux-x64), so an exact comparison fails even for a
native build. TargetArchitecture vs BuildArchitecture is the canonical native-vs-cross
signal across all platforms.
* same-OS cross-arch builds, where NativeAOT targets a different architecture from the build
host (TargetArchitecture != BuildArchitecture). This is supported on all three operating
systems: win-x64 -> win-arm64 and osx-x64 -> osx-arm64 (clang/link are multi-target and
need no extra sysroot), and Linux via the azurelinux cross-prereq containers, which
provide a cross toolchain and target sysroot (CrossBuild=true with ROOTFS_DIR). The cross
inputs (CrossBuild/TargetArchitecture/TargetRid) are forwarded to the child dotnet-aot
Publish in GenerateLayout.targets; ROOTFS_DIR flows via the environment on Linux.
-->
<_DotnetAotTargetRidSupported Condition="$(TargetRid.StartsWith('win')) or $(TargetRid.StartsWith('linux')) or $(TargetRid.StartsWith('osx'))">true</_DotnetAotTargetRidSupported>
<_DotnetAotIsLinuxNativeBuild Condition="'$(CrossBuild)' != 'true' and '$(DotNetBuildSourceOnly)' != 'true' and $(TargetRid.StartsWith('linux')) and !$(TargetRid.StartsWith('linux-musl')) and $([MSBuild]::IsOSPlatform('LINUX')) and '$(TargetArchitecture)' == '$(BuildArchitecture)'">true</_DotnetAotIsLinuxNativeBuild>
<_DotnetAotIsLinuxCrossBuild Condition="'$(CrossBuild)' == 'true' and '$(DotNetBuildSourceOnly)' != 'true' and $(TargetRid.StartsWith('linux'))">true</_DotnetAotIsLinuxCrossBuild>
<_ShouldPublishDotnetAot Condition="'$(_ShouldPublishDotnetAot)' == '' and '$(_DotnetAotTargetRidSupported)' == 'true' and ('$(TargetRid)' == '$(HostRid)' or '$(_DotnetAotIsLinuxNativeBuild)' == 'true' or '$(_DotnetAotIsLinuxCrossBuild)' == 'true')">true</_ShouldPublishDotnetAot>

<!-- The target OS (from the TargetRid prefix) equals the build host OS. NativeAOT can only
target the host OS, so this is a prerequisite for both native and cross-arch publishing. -->
<_DotnetAotIsSameOSBuild Condition="$([MSBuild]::IsOSPlatform('WINDOWS')) and $(TargetRid.StartsWith('win'))">true</_DotnetAotIsSameOSBuild>
<_DotnetAotIsSameOSBuild Condition="$([MSBuild]::IsOSPlatform('OSX')) and $(TargetRid.StartsWith('osx'))">true</_DotnetAotIsSameOSBuild>
<_DotnetAotIsSameOSBuild Condition="$([MSBuild]::IsOSPlatform('LINUX')) and $(TargetRid.StartsWith('linux'))">true</_DotnetAotIsSameOSBuild>

<!-- Native: same OS and same architecture as the build host (and not an explicit cross-build).
linux-musl is excluded because its NativeAOT toolchain is not wired up here. -->
<_DotnetAotIsNativeBuild Condition="'$(_DotnetAotIsSameOSBuild)' == 'true' and '$(TargetArchitecture)' == '$(BuildArchitecture)' and '$(CrossBuild)' != 'true' and '$(DotNetBuildSourceOnly)' != 'true' and !$(TargetRid.StartsWith('linux-musl'))">true</_DotnetAotIsNativeBuild>

<!-- Cross: same OS but a different architecture from the build host. On Windows/macOS the cross
toolchain (MSVC arm64 linker / clang) is multi-target, so an architecture mismatch alone is
sufficient. On Linux a cross toolchain and target sysroot are required, so we only treat it
as a cross build when CrossBuild=true - which is set by the leg that runs inside the
azurelinux cross-prereq container (providing clang + the sysroot via ROOTFS_DIR). Without
that guard the regular linux-arm64 legs (e.g. TestBuild), which build on the x64 pool with
no arm64 sysroot, would try to cross-link and fail. -->
<_DotnetAotIsCrossBuild Condition="'$(_DotnetAotIsSameOSBuild)' == 'true' and '$(TargetArchitecture)' != '$(BuildArchitecture)' and '$(DotNetBuildSourceOnly)' != 'true' and !$(TargetRid.StartsWith('linux-musl')) and !($(TargetRid.StartsWith('linux')) and '$(CrossBuild)' != 'true')">true</_DotnetAotIsCrossBuild>

<_ShouldPublishDotnetAot Condition="'$(_ShouldPublishDotnetAot)' == '' and '$(_DotnetAotTargetRidSupported)' == 'true' and ('$(_DotnetAotIsNativeBuild)' == 'true' or '$(_DotnetAotIsCrossBuild)' == 'true')">true</_ShouldPublishDotnetAot>
<_ShouldPublishDotnetAot Condition="'$(_ShouldPublishDotnetAot)' == ''">false</_ShouldPublishDotnetAot>
</PropertyGroup>

Expand Down
20 changes: 11 additions & 9 deletions src/Layout/redist/targets/GenerateLayout.targets
Original file line number Diff line number Diff line change
Expand Up @@ -532,10 +532,11 @@
them entirely in native code, falling back to the managed dotnet.dll for other commands.
The output is placed next to dotnet.dll so it's packaged with the SDK.

Runs for native builds (TargetRid == HostRid) on supported platforms, and for Linux
cross-builds (CrossBuild=true) where NativeAOT targets another architecture from an x64
Linux host using a cross toolchain and target sysroot (ROOTFS_DIR). See the
_ShouldPublishDotnetAot property in src/Layout/Directory.Build.props.
Runs for native builds (target OS/arch match the build host) on supported platforms, and for
same-OS cross-arch builds where NativeAOT targets a different architecture from the build host
(win-x64 -> win-arm64, osx-x64 -> osx-arm64, and Linux via the azurelinux cross containers that
provide a cross toolchain and target sysroot via ROOTFS_DIR). See the _ShouldPublishDotnetAot
property in src/Layout/Directory.Build.props.
-->
<Target Name="PublishDotnetAot"
Condition="'$(_ShouldPublishDotnetAot)' == 'true'">
Expand All @@ -549,13 +550,14 @@

<!--
Global properties for the dotnet-aot Publish below. _IsPublishing=true is always required
(see the note below). For Linux cross-builds we also forward the cross-compilation inputs:
the MSBuild task doesn't flow the outer build's global properties to the child project, so
CrossBuild and the target architecture/RID must be passed explicitly. The child then maps
SysRoot from the ROOTFS_DIR environment variable via LocateNativeCompiler.targets.
(see the note below). For same-OS cross-arch builds (win/osx/linux) we also forward the
cross-compilation inputs: the MSBuild task doesn't flow the outer build's global properties
to the child project, so CrossBuild and the target architecture/RID must be passed
explicitly. On Linux the child then maps SysRoot from the ROOTFS_DIR environment variable
via LocateNativeCompiler.targets; on Windows/macOS no sysroot is needed.
-->
<_DotnetAotPublishProperties>_IsPublishing=true</_DotnetAotPublishProperties>
<_DotnetAotPublishProperties Condition="'$(_DotnetAotIsLinuxCrossBuild)' == 'true'">$(_DotnetAotPublishProperties);CrossBuild=true;TargetArchitecture=$(TargetArchitecture);TargetRid=$(TargetRid)</_DotnetAotPublishProperties>
<_DotnetAotPublishProperties Condition="'$(_DotnetAotIsCrossBuild)' == 'true'">$(_DotnetAotPublishProperties);CrossBuild=true;TargetArchitecture=$(TargetArchitecture);TargetRid=$(TargetRid)</_DotnetAotPublishProperties>
</PropertyGroup>

<!--
Expand Down
Loading