Skip to content

Commit 531e161

Browse files
authored
Merge pull request #21359 from unoplatform/dev/jonpryor/jonp-add-android+nativeaot-skia-sample-stage
chore: build & run SamplesApp.Skia.netcoremobile with NativeAOT on Android
2 parents 024f677 + 92676ea commit 531e161

File tree

30 files changed

+483
-20
lines changed

30 files changed

+483
-20
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
parameters:
2+
vmLinuxPool: ''
3+
UNO_UWP_BUILD: ''
4+
XAML_FLAVOR_BUILD: ''
5+
6+
jobs:
7+
- job: Skia_Android_NativeAOT_Tests_Build
8+
displayName: 'Build Skia Android+NativeAOT Samples App'
9+
timeoutInMinutes: 60
10+
cancelTimeoutInMinutes: 1
11+
12+
pool: ${{ parameters.vmLinuxPool }}
13+
14+
variables:
15+
CombinedConfiguration: Release|Any CPU
16+
CI_Build: true
17+
18+
UNO_UWP_BUILD: ${{ parameters.UNO_UWP_BUILD }}
19+
XAML_FLAVOR_BUILD: ${{ parameters.XAML_FLAVOR_BUILD }}
20+
21+
steps:
22+
- checkout: self
23+
clean: true
24+
25+
- template: ../templates/gitversion.yml
26+
- template: ../templates/dotnet-mobile-install-linux.yml
27+
parameters:
28+
UnoCheckParameters: '--tfm net10.0-android'
29+
30+
- powershell: dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:ApplicationId=uno.platform.samplesapp.skia.nativeaot -p:SkiaPublishAot=true /bl:$(build.artifactstagingdirectory)/logs/build-skia-android-nativeaot.binlog
31+
displayName: Build Android+NativeAOT Skia Head
32+
33+
- script: >
34+
rm -Rf src/SamplesApp/SamplesApp.Skia.netcoremobile/obj
35+
workingDirectory: $(Build.SourcesDirectory)
36+
displayName: Delete obj folder to free up disk space
37+
38+
- task: CopyFiles@2
39+
displayName: 'Copy Generated Android APK'
40+
inputs:
41+
SourceFolder: $(build.sourcesdirectory)/src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/
42+
Contents: 'uno.platform.samplesapp.skia.nativeaot-Signed.apk'
43+
TargetFolder: $(build.artifactstagingdirectory)/android-nativeaot
44+
CleanTargetFolder: false
45+
OverWrite: false
46+
flattenFolders: false
47+
48+
- task: PublishPipelineArtifact@1
49+
displayName: 'Publish Android+NativeAOT Binaries'
50+
retryCountOnTaskFailure: 3
51+
inputs:
52+
targetPath: $(build.artifactstagingdirectory)/android-nativeaot
53+
ArtifactName: uitests-android-nativeaot-skia-build
54+
55+
- task: PublishBuildArtifacts@1
56+
retryCountOnTaskFailure: 3
57+
condition: always()
58+
inputs:
59+
PathtoPublish: $(build.artifactstagingdirectory)/logs
60+
ArtifactName: skia-samples-app-binlog
61+
ArtifactType: Container
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
parameters:
2+
vmLinuxPool: ''
3+
UNO_UWP_BUILD: ''
4+
XAML_FLAVOR_BUILD: ''
5+
6+
jobs:
7+
##
8+
## Android+NativeAOT Skia
9+
##
10+
11+
- job: Android_NativeAOT_Tests
12+
displayName: ' ' ## Name is concatenated with the matrix group name
13+
timeoutInMinutes: 45
14+
dependsOn: Skia_Android_NativeAOT_Tests_Build
15+
pool: ${{ parameters.vmLinuxPool }}
16+
17+
variables:
18+
CI_Build: true
19+
SourceLinkEnabled: false
20+
NUGET_PACKAGES: $(Agent.WorkFolder)/.nuget
21+
22+
strategy:
23+
matrix:
24+
25+
'Runtime Tests 0':
26+
ANDROID_SIMULATOR_APILEVEL: 34
27+
UITEST_TEST_MODE_NAME: RuntimeTests
28+
UNO_UITEST_BUCKET_ID: RuntimeTests
29+
UITEST_RUNTIME_TEST_GROUP: 0
30+
UITEST_RUNTIME_TEST_GROUP_COUNT: 5
31+
SAMPLEAPP_ARTIFACT_NAME: uitests-android-nativeaot-skia-build
32+
TARGETPLATFORM_NAME: net10
33+
UITEST_TEST_TIMEOUT: '2600s'
34+
35+
'Runtime Tests 1':
36+
ANDROID_SIMULATOR_APILEVEL: 34
37+
UITEST_TEST_MODE_NAME: RuntimeTests
38+
UNO_UITEST_BUCKET_ID: RuntimeTests
39+
UITEST_RUNTIME_TEST_GROUP: 1
40+
UITEST_RUNTIME_TEST_GROUP_COUNT: 5
41+
SAMPLEAPP_ARTIFACT_NAME: uitests-android-nativeaot-skia-build
42+
TARGETPLATFORM_NAME: net10
43+
UITEST_TEST_TIMEOUT: '2600s'
44+
45+
'Runtime Tests 2':
46+
ANDROID_SIMULATOR_APILEVEL: 34
47+
UITEST_TEST_MODE_NAME: RuntimeTests
48+
UNO_UITEST_BUCKET_ID: RuntimeTests
49+
UITEST_RUNTIME_TEST_GROUP: 2
50+
UITEST_RUNTIME_TEST_GROUP_COUNT: 5
51+
SAMPLEAPP_ARTIFACT_NAME: uitests-android-nativeaot-skia-build
52+
TARGETPLATFORM_NAME: net10
53+
UITEST_TEST_TIMEOUT: '2600s'
54+
55+
'Runtime Tests 3':
56+
ANDROID_SIMULATOR_APILEVEL: 34
57+
UITEST_TEST_MODE_NAME: RuntimeTests
58+
UNO_UITEST_BUCKET_ID: RuntimeTests
59+
UITEST_RUNTIME_TEST_GROUP: 3
60+
UITEST_RUNTIME_TEST_GROUP_COUNT: 5
61+
SAMPLEAPP_ARTIFACT_NAME: uitests-android-nativeaot-skia-build
62+
TARGETPLATFORM_NAME: net10
63+
UITEST_TEST_TIMEOUT: '2600s'
64+
65+
'Runtime Tests 4':
66+
ANDROID_SIMULATOR_APILEVEL: 34
67+
UITEST_TEST_MODE_NAME: RuntimeTests
68+
UNO_UITEST_BUCKET_ID: RuntimeTests
69+
UITEST_RUNTIME_TEST_GROUP: 4
70+
UITEST_RUNTIME_TEST_GROUP_COUNT: 5
71+
SAMPLEAPP_ARTIFACT_NAME: uitests-android-nativeaot-skia-build
72+
TARGETPLATFORM_NAME: net10
73+
UITEST_TEST_TIMEOUT: '2600s'
74+
75+
steps:
76+
- checkout: self
77+
clean: true
78+
79+
- bash: |
80+
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
81+
sudo udevadm control --reload-rules
82+
sudo udevadm trigger --name-match=kvm
83+
displayName: 'Enable KVM'
84+
85+
- task: DownloadPipelineArtifact@2
86+
displayName: Downloading $(SAMPLEAPP_ARTIFACT_NAME)
87+
inputs:
88+
artifact: $(SAMPLEAPP_ARTIFACT_NAME)
89+
path: '$(build.sourcesdirectory)/build/$(SAMPLEAPP_ARTIFACT_NAME)/android'
90+
91+
- task: DownloadBuildArtifacts@0
92+
condition: gt(variables['System.JobAttempt'], 1)
93+
continueOnError: true
94+
displayName: Download previous test runs failed tests
95+
inputs:
96+
artifactName: uitests-android-nativeaot-failure-results
97+
downloadPath: '$(build.sourcesdirectory)/build'
98+
99+
- template: ../templates/dotnet-install.yml
100+
101+
- bash: |
102+
chmod +x $(build.sourcesdirectory)/build/test-scripts/android-run-skia-runtime-tests.sh
103+
UNO_UITEST_APP_ID=uno.platform.samplesapp.skia.nativeaot \
104+
$(build.sourcesdirectory)/build/test-scripts/android-run-skia-runtime-tests.sh
105+
106+
displayName: Run Android+NativeAOT Skia Tests
107+
108+
- task: PublishTestResults@2
109+
condition: always()
110+
inputs:
111+
testRunTitle: 'Android+NativeAOT Skia Runtime Tests $(UITEST_RUNTIME_TEST_GROUP)'
112+
testResultsFormat: 'NUnit'
113+
testResultsFiles: '$(build.sourcesdirectory)/build/*TestResult*.xml'
114+
failTaskOnFailedTests: true
115+
116+
- task: PublishBuildArtifacts@1
117+
condition: always()
118+
retryCountOnTaskFailure: 3
119+
inputs:
120+
PathtoPublish: $(build.artifactstagingdirectory)
121+
ArtifactName: android-nativeaot-skia-results
122+
ArtifactType: Container
123+
124+
- task: PublishBuildArtifacts@1
125+
condition: always()
126+
displayName: Publish Failed Tests Results
127+
retryCountOnTaskFailure: 3
128+
inputs:
129+
PathtoPublish: $(build.sourcesdirectory)/build/uitests-failure-results
130+
ArtifactName: uitests-android-nativeaot-failure-results
131+
ArtifactType: Container

build/ci/tests/.azure-devops-tests-skia-stages.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,23 @@ stages:
7575
UNO_UWP_BUILD: '${{ parameters.UNO_UWP_BUILD }}'
7676
XAML_FLAVOR_BUILD: '${{ parameters.XAML_FLAVOR_BUILD }}'
7777

78+
- stage: runtime_tests_skia_android_nativeaot
79+
displayName: Tests - Android+NativeAOT Skia
80+
dependsOn:
81+
- Setup
82+
83+
jobs:
84+
- template: .azure-devops-tests-android-nativeaot-skia-build.yml
85+
parameters:
86+
vmLinuxPool: '${{ parameters.vmLinuxPool }}'
87+
UNO_UWP_BUILD: '${{ parameters.UNO_UWP_BUILD }}'
88+
XAML_FLAVOR_BUILD: '${{ parameters.XAML_FLAVOR_BUILD }}'
89+
- template: .azure-devops-tests-android-nativeaot-skia.yml
90+
parameters:
91+
vmLinuxPool: '${{ parameters.vmLinuxPool }}'
92+
UNO_UWP_BUILD: '${{ parameters.UNO_UWP_BUILD }}'
93+
XAML_FLAVOR_BUILD: '${{ parameters.XAML_FLAVOR_BUILD }}'
94+
7895
- stage: runtime_tests_skia_ios
7996
displayName: Tests - iOS Skia
8097
dependsOn:

build/test-scripts/android-run-skia-runtime-tests.sh

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,19 +157,21 @@ while [[ ! $($ANDROID_HOME/platform-tools/adb shell test -e "$UITEST_RUNTIME_AUT
157157
fi
158158
done
159159

160-
$ANDROID_HOME/platform-tools/adb pull $UITEST_RUNTIME_AUTOSTART_RESULT_DEVICE_PATH $UITEST_RUNTIME_AUTOSTART_RESULT_FILENAME
160+
$ANDROID_HOME/platform-tools/adb pull $UITEST_RUNTIME_AUTOSTART_RESULT_DEVICE_PATH $UITEST_RUNTIME_AUTOSTART_RESULT_FILENAME || echo "ERROR: could not adb pull $UITEST_RUNTIME_AUTOSTART_RESULT_DEVICE_PATH"
161+
162+
## Dump the emulator's system log
163+
$ANDROID_HOME/platform-tools/adb shell logcat -d > $LOGS_PATH/android-device-log-$UNO_UITEST_BUCKET_ID-$UITEST_RUNTIME_TEST_GROUP-$UITEST_TEST_MODE_NAME.txt
164+
165+
# create $BUILD_SOURCESDIRECTORY/build/uitests-failure-results before exiting, so that `PublishBuildArtifacts@1` doesn't error out just because the tests crashed.
166+
mkdir -p $(dirname ${UNO_TESTS_FAILED_LIST})
161167

162168
if [ ! -f "$UITEST_RUNTIME_AUTOSTART_RESULT_FILENAME" ]; then
163169
echo "ERROR: The test results file $UITEST_RUNTIME_AUTOSTART_RESULT_FILENAME does not exist (did nunit crash ?)"
164170
exit 1
165171
fi
166172

167-
## Dump the emulator's system log
168-
$ANDROID_HOME/platform-tools/adb shell logcat -d > $LOGS_PATH/android-device-log-$UNO_UITEST_BUCKET_ID-$UITEST_RUNTIME_TEST_GROUP-$UITEST_TEST_MODE_NAME.txt
169-
170173
## Export the failed tests list for reuse in a pipeline retry
171174
pushd $BUILD_SOURCESDIRECTORY/src/Uno.NUnitTransformTool
172-
mkdir -p $(dirname ${UNO_TESTS_FAILED_LIST})
173175

174176
echo "Running NUnitTransformTool"
175177

src/Directory.Build.props

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@
5555
<RestoreEnablePackagePruning>true</RestoreEnablePackagePruning>
5656

5757
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
58+
59+
<DefineConstants Condition=" '$(UseMonoRuntime)' == 'false' ">$(DefineConstants);RUNTIME_CORECLR</DefineConstants>
60+
<DefineConstants Condition=" '$(SkiaPublishAot)' == 'true' ">$(DefineConstants);RUNTIME_NATIVE_AOT</DefineConstants>
5861
</PropertyGroup>
5962

6063
<PropertyGroup>

src/SamplesApp/SamplesApp.Skia.netcoremobile/Android/Main.Android.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ public override void OnCreate()
116116
// TODO: remove once the Android+CoreCLR runtime properly inits crypto, possibly .NET 10 RC2?
117117
Java.Lang.JavaSystem.LoadLibrary("System.Security.Cryptography.Native.Android");
118118
#endif // RUNTIME_CORECLR
119+
#if RUNTIME_NATIVE_AOT
120+
// TODO: remove once the Android+NativeAOT runtime properly inits crypto
121+
// Likely once https://github.com/dotnet/android/pull/10461 is merged, possibly .NET 10 RC2?
122+
JniEnvironment.References.GetJavaVM(out var invocationPointer);
123+
NativeMethods.AndroidCryptoNative_InitLibraryOnLoad(javaVM: invocationPointer, reserved: IntPtr.Zero);
124+
#endif // RUNTIME_NATIVE_AOT
119125

120126
// Initialize Android-specific extensions.
121127
// These would be generally registered automatically by App.xaml generator,
@@ -126,4 +132,12 @@ public override void OnCreate()
126132
ApiExtensibility.Register(typeof(IApplicationViewSpanningRects), o => new FoldableApplicationViewSpanningRects(o));
127133
}
128134
}
135+
136+
#if RUNTIME_NATIVE_AOT
137+
internal static partial class NativeMethods
138+
{
139+
[DllImport("System.Security.Cryptography.Native.Android", CallingConvention = CallingConvention.Cdecl)]
140+
internal static extern void AndroidCryptoNative_InitLibraryOnLoad(IntPtr javaVM, IntPtr reserved);
141+
}
142+
#endif // RUNTIME_NATIVE_AOT
129143
}

src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
-->
3333
<NoWarn>$(NoWarn);NU1703;SYSLIB1045</NoWarn>
3434

35+
<!-- Ignore linker warnings for now -->
36+
<NoWarn>$(NoWarn);IL2026;IL2057;IL2062;IL2065;IL2067;IL2068;IL2070;IL2072;IL2075;IL2077;IL2080;IL2104;IL2111;IL2122;IL3000;IL3002;IL3050;IL3053</NoWarn>
37+
3538
<!--
3639
aab is the default packaging format in net6 API 31.
3740
We need an APK for deployment on simulators.
@@ -53,6 +56,8 @@
5356

5457
<!-- Required when not building inside VS to avoid dependency issues -->
5558
<PreBuildUnoUITasks Condition="'$(BuildingInsideVisualStudio)'==''">true</PreBuildUnoUITasks>
59+
60+
<PublishAot Condition=" '$(SkiaPublishAot)' != '' ">$(SkiaPublishAot)</PublishAot>
5661
</PropertyGroup>
5762

5863
<ItemGroup>
@@ -291,6 +296,7 @@
291296

292297
<ItemGroup>
293298
<TrimmerRootDescriptor Include="LinkerConfig.xml" />
299+
<TrimmerRootAssembly Include="SamplesApp.Skia" RootMode="All" />
294300
</ItemGroup>
295301

296302
<ItemGroup>

src/SamplesApp/SamplesApp.UITests/Windows_UI_Xaml_Input/Nested_Sequence_Tests.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ internal class Nested_Sequence_Tests : SampleControlUITestBase
3535
#if IS_RUNTIME_UI_TESTS
3636
[Uno.UI.RuntimeTests.RequiresFullWindow]
3737
#endif
38+
#if RUNTIME_NATIVE_AOT
39+
[Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: https://github.com/AwesomeAssertions/AwesomeAssertions/issues/290")]
40+
#endif // RUNTIME_NATIVE_AOT
3841
public async Task When_PressOnNestedAndReleaseOnContainer_Touch()
3942
{
4043
await RunAsync(_sample);
@@ -67,6 +70,9 @@ public async Task When_PressOnNestedAndReleaseOnContainer_Touch()
6770
[Ignore("Inputs simulated by selenium are directly appreaing at the start location and wrongly inserting an exit.")]
6871
//[ActivePlatforms(Platform.Browser)]
6972
#endif
73+
#if RUNTIME_NATIVE_AOT
74+
[Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: https://github.com/AwesomeAssertions/AwesomeAssertions/issues/290")]
75+
#endif // RUNTIME_NATIVE_AOT
7076
#if IS_RUNTIME_UI_TESTS
7177
[Uno.UI.RuntimeTests.RequiresFullWindow]
7278
#endif
@@ -101,6 +107,9 @@ public async Task When_PressOnNestedAndReleaseOnContainer_Mouse()
101107
#if !__SKIA__
102108
[Ignore("Does not work due to the 'implicit capture'")]
103109
#endif
110+
#if RUNTIME_NATIVE_AOT
111+
[Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: https://github.com/AwesomeAssertions/AwesomeAssertions/issues/290")]
112+
#endif // RUNTIME_NATIVE_AOT
104113
[InjectedPointer(PointerDeviceType.Touch)]
105114
public async Task When_PressOnContainerAndReleaseOnNested_Touch()
106115
{

0 commit comments

Comments
 (0)