Skip to content

Commit 816377b

Browse files
Perkseydotnet-bot
andauthored
[3.0] Streamline native builds (and build native libs for 3.0) (#2389)
* Initial work on native build workflow * Stop using YAML for GITHUB_OUTPUT * Add GH_TOKEN env var to stage2 * Use an action for comment writing instead * Fix permissions, try to fix expr issue * Same again * Fix PR comment location * Replace the comment rather than append to it * Start of native build job * Attempt to fix matrix * Add a job name, fix build script permissions issues * Add OSX build for SDL * Start of commit job * Add missing checkout * Use official action to checkout PR * Fix permissions issues * Update native binaries for bc82423 * Start of linux-x64 SDL build * Sudo for apt * apt-get update * Checkout submodule * Fix path error * Update native binaries for ece2459 * Add linux-arm and linux-arm64 * Use glibc 2.34 on linux-arm for Y2038 support * Update native binaries for 3e3df2c * Add win-arm, win-arm64, win-x64 * Fix dir structure * Attempt to keep win-arm support, may be on the chopping block though * Fix batch script error * Use curl instead of wget? * Fix winsdk install? * Remove 32-bit Windows on Arm support * Use a Microsoft Developer Command Prompt * Fix vcvarsall path * Use Ninja - libsdl-org/SDL##11487 * Update native binaries for 601bb66 * Fix artifact download path * Fix the fix * Update native binaries for 4630438 * Add iOS and tvOS for SDL * Fix file permissions * Update native binaries for 45f36d0 * Add Android build for SDL * Apparently sdkmanager is not in PATH * Install Python 3.11 * Install Ninja * Update native binaries for d7d3c69 * Try to ungitignore the Android jar * Update native binaries for f79ad90 * Add an easy update script * Include org.libsdl.app bindings with the aar, working package now * Update native binaries for 8cf95c2 * Some cleanup, and add docs * Fix build * Install workloads in test too * Update native binaries for 186f907 * Fix build (not ideally) * Update native binaries for 44b9933 * Dummy commit to run Test/Build again --------- Co-authored-by: The Silk.NET Automaton <9011267+dotnet-bot@users.noreply.github.com>
1 parent 3f39401 commit 816377b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1109
-17
lines changed

.gitattributes

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@
5353
*.7z binary
5454
*.ttf binary
5555
*.stout binary
56+
*.so binary
57+
*.dll binary
58+
*.dylib binary
59+
*.jar binary
5660

5761
# Verify
5862
*.verified.txt text eol=lf working-tree-encoding=UTF-8

.github/workflows/dotnet.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ jobs:
2727
with:
2828
dotnet-version: '9.0.x'
2929
dotnet-quality: 'preview'
30+
- name: Install Workloads
31+
run: dotnet workload restore
3032
- name: Pack
3133
# TODO decide whether we want experimental builds to use Debug or Release - using Release for now...
3234
run: >-
@@ -70,6 +72,8 @@ jobs:
7072
with:
7173
dotnet-version: '8.0.x'
7274
dotnet-quality: 'preview'
75+
- name: Install Workloads
76+
run: dotnet workload restore
7377
- name: Restore
7478
run: dotnet restore --runtime ${{ matrix.rid }}
7579
- name: Test

.github/workflows/native.yml

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
name: Native Builds
2+
on:
3+
pull_request:
4+
types: [opened, edited, synchronize]
5+
permissions:
6+
pull-requests: write
7+
contents: write
8+
env:
9+
# A space-separated list of paths to native libraries to build.
10+
NATIVE_LIBRARY_PATHS: "sources/SDL/Native"
11+
# A space-separated list of submodule paths for each native library path. Use _ if a submodule is not used - this must
12+
# match the number of spaces in NATIVE_LIBRARY_PATHS.
13+
NATIVE_LIBRARY_SUBMODULE_PATHS: "eng/submodules/sdl"
14+
# A space-separated list of shorthands to the native library paths that will build the native library for each native
15+
# library path. This must match the number of spaces in NATIVE_LIBRARY_PATHS. If a shorthand builds multiple native
16+
# binary paths, these will be deduplicated.
17+
NATIVE_LIBRARY_SHORTHANDS: "SDL"
18+
jobs:
19+
prerequisites:
20+
name: PR Check
21+
runs-on: ubuntu-latest
22+
steps:
23+
- uses: actions/checkout@v3
24+
- id: parse
25+
name: Determine which native libraries the user has asked to build, and where to look for changes.
26+
run: ./workflow-stage1.sh
27+
working-directory: eng/native/buildsystem
28+
env:
29+
PR_COMMENT: ${{ github.event.pull_request.body }}
30+
- uses: dorny/paths-filter@v3
31+
id: filter
32+
name: Determine which natives need to be rebuilt.
33+
with:
34+
filters: ${{ steps.parse.outputs.workflow_filters }}
35+
- name: Find a warning message from a previous run, if applicable.
36+
uses: peter-evans/find-comment@v3
37+
id: fc
38+
with:
39+
issue-number: ${{ github.event.number }}
40+
comment-author: "github-actions[bot]"
41+
body-includes: "Some of the native library builds modified in this PR were not referenced in the PR description."
42+
- id: strat
43+
name: Create the matrix strategy for the native builds.
44+
run: ./workflow-stage2.sh
45+
working-directory: eng/native/buildsystem
46+
env:
47+
NATIVE_LIBRARY_APPLICABLE_SHORTHANDS: ${{ join(fromJSON(steps.filter.outputs.changes), ' ') }}
48+
NATIVE_LIBRARY_USER_REFERENCED_SHORTHANDS: ${{ steps.parse.outputs.targets_referenced }}
49+
PR_EXISTING_NOTICE_ID: ${{ steps.fc.outputs.comment-id }}
50+
- name: Write a comment if needed.
51+
if: ${{ steps.strat.outputs.comment_to_write }}
52+
uses: peter-evans/create-or-update-comment@v4
53+
with:
54+
comment-id: ${{ steps.fc.outputs.comment-id }}
55+
issue-number: ${{ github.event.number }}
56+
body: ${{ steps.strat.outputs.comment_to_write }}
57+
edit-mode: replace
58+
outputs:
59+
matrix_strategy: ${{ steps.strat.outputs.matrix_strategy }}
60+
targets_referenced: ${{ steps.parse.outputs.targets_referenced }}
61+
build:
62+
needs: [prerequisites]
63+
strategy:
64+
matrix:
65+
flat: ${{ fromJSON(needs.prerequisites.outputs.matrix_strategy) }}
66+
runs-on: ${{ (startsWith(matrix.flat.runtime, 'osx') || startsWith(matrix.flat.runtime, 'ios') || startsWith(matrix.flat.runtime, 'tvos')) && 'macos-latest' || startsWith(matrix.flat.runtime, 'win') && 'windows-latest' || 'ubuntu-latest' }}
67+
name: ${{ matrix.flat.target }} / ${{ matrix.flat.runtime }}
68+
steps:
69+
- uses: actions/checkout@v3
70+
- run: |
71+
echo "https://github.com/actions/upload-artifact/issues/174" > .workaround-${{ matrix.flat.target }}-${{ matrix.flat.runtime }}.txt
72+
${{ format('.{0}{1}', startsWith(matrix.flat.runtime, 'win') && '\' || '/', matrix.flat.exec) }}
73+
working-directory: ${{ matrix.flat.dir }}
74+
- uses: actions/upload-artifact@v4
75+
with:
76+
name: natives-${{ matrix.flat.target }}-${{ matrix.flat.runtime }}
77+
path: |
78+
./.workaround-*.txt
79+
./${{ matrix.flat.dir }}/runtimes/${{ format('{0}{1}', matrix.flat.runtime, !contains(matrix.flat.runtime, '-') && '*' || '') }}/**/*
80+
./${{ matrix.flat.dir }}/lib/*${{ matrix.flat.runtime }}*/**/*
81+
./${{ matrix.flat.dir }}/*${{ matrix.flat.runtime }}*/**/*
82+
commit:
83+
name: Commit Binaries
84+
needs: [prerequisites, build]
85+
runs-on: ubuntu-latest
86+
if: ${{ needs.prerequisites.outputs.targets_referenced }}
87+
steps:
88+
- uses: actions/checkout@v4
89+
with:
90+
ref: ${{ github.head_ref }}
91+
- name: Download All Artifacts
92+
uses: actions/download-artifact@v4
93+
with:
94+
pattern: natives-*
95+
merge-multiple: true
96+
- name: Commit Artifacts
97+
run: |
98+
git config --local user.email "9011267+dotnet-bot@users.noreply.github.com"
99+
git config --local user.name "The Silk.NET Automaton"
100+
git add .
101+
git commit -m "Update native binaries for $(git rev-parse HEAD)"
102+
git push

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,3 +489,12 @@ src/Website/Silk.NET.Statiq/cache
489489

490490
# Verify
491491
*.received.*
492+
493+
# Native Binaries
494+
!**/runtimes/*/native/*.dylib
495+
!**/runtimes/*/native/*.so
496+
!**/runtimes/*/native/*.dll
497+
!**/lib/**/*.aar
498+
build/
499+
!eng/build/
500+
.workaround*

Directory.Build.props

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
3131
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
3232
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
33+
<ImplicitUsings>enable</ImplicitUsings>
3334
</PropertyGroup>
3435

3536
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
@@ -64,10 +65,12 @@
6465
<PublishRepositoryUrl>true</PublishRepositoryUrl>
6566
<VersionDependsOn>SilkShippingControl;$(VersionDependsOn)</VersionDependsOn>
6667
<PackageVersionDependsOn>SilkShippingControl;$(PackageVersionDependsOn)</PackageVersionDependsOn>
68+
<TargetsForTfmSpecificContentInPackage>SilkNativePackaging;$(TargetsForTfmSpecificContentInPackage)</TargetsForTfmSpecificContentInPackage>
69+
<GenerateNuspecDependsOn>SilkShippingControl;$(GenerateNuspecDependsOn)</GenerateNuspecDependsOn>
6770
</PropertyGroup>
6871

6972
<!-- SourceLink -->
70-
<PropertyGroup Condition="'$(SilkSourceLinkExempt)' == ''">
73+
<PropertyGroup Condition="'$(SilkSourceLinkExempt)' == '' and '$(SilkNativePackage)' != 'true' and '$(SilkMetapackage)' != 'true'">
7174
<DebugType>portable</DebugType>
7275
<EmbedAllSources>true</EmbedAllSources>
7376
<EmbedUntrackedSources>true</EmbedUntrackedSources>

Directory.Build.targets

Lines changed: 81 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,25 @@
139139
</UsingTask>
140140

141141
<Target Name="SilkShippingControl" BeforeTargets="BeforeBuild">
142+
<!-- Non-C# packages (i.e. metapackages, natives) -->
143+
<PropertyGroup Condition="'$(SilkNativePackage)' == 'true' or '$(SilkMetapackage)' == 'true'">
144+
<IncludeBuildOutput Condition="'$(SilkNativeHasAndroidJars)' != 'true'">false</IncludeBuildOutput>
145+
<IncludeBuildOutput Condition="'$(TargetFramework)' != ''">false</IncludeBuildOutput>
146+
<IncludeBuildOutput Condition="'$(SilkNativeHasAndroidJars)' == 'true' and $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">true</IncludeBuildOutput>
147+
<NoWarn>NU5128;1591;$(NoWarn)</NoWarn>
148+
<GenerateDocumentationFile>false</GenerateDocumentationFile>
149+
</PropertyGroup>
150+
142151
<!-- Public API -->
143152
<PropertyGroup Condition="'$(SilkTrackPublicAPI)' != 'true' or '$(TargetFramework)' == ''">
144153
<SilkTrackPublicAPI>false</SilkTrackPublicAPI>
145154
</PropertyGroup>
146155
<ItemGroup Condition="'$(SilkTrackPublicAPI)' == 'true'">
147156
<PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" PrivateAssets="All" />
148157
</ItemGroup>
149-
<ItemGroup Condition="'$(SilkSourceLinkExempt)' == ''">
158+
159+
<!-- SourceLink -->
160+
<ItemGroup Condition="'$(SilkSourceLinkExempt)' == '' and '$(SilkNativePackage)' != 'true' and '$(SilkMetapackage)' != 'true'">
150161
<PackageReference Include="DotNet.ReproducibleBuilds" PrivateAssets="All"/>
151162
<PackageReference Include="DotNet.ReproducibleBuilds.Isolated" PrivateAssets="All"/>
152163
</ItemGroup>
@@ -161,6 +172,7 @@
161172
<WriteLinesToFile File="PublicAPI/$(TargetFramework)/PublicAPI.Unshipped.txt"
162173
Lines="@(SilkNewPublicAPILines)"
163174
Condition="'$(SilkTrackPublicAPI)' == 'true' and !Exists('PublicAPI/$(TargetFramework)/PublicAPI.Unshipped.txt')" />
175+
164176
<!-- Versioning -->
165177
<PropertyGroup>
166178
<SilkChangelog>$([System.IO.File]::ReadAllText("$(MSBuildThisFileDirectory)docs/CHANGELOG.md"))</SilkChangelog>
@@ -171,19 +183,81 @@
171183
<Output PropertyName="SilkReleaseNotes" TaskParameter="SilkReleaseNotes" />
172184
</SilkGetVersionInfoTask>
173185
<PropertyGroup>
186+
<SilkOriginalVersionSuffix>$(VersionSuffix)</SilkOriginalVersionSuffix>
174187
<Version>$(SilkVersion)</Version>
175188
<VersionSuffix Condition="'$(VersionSuffix)' == ''">$(SilkVersionSuffix)</VersionSuffix>
176189
<PackageReleaseNotes>$(SilkReleaseNotes)</PackageReleaseNotes>
177190
<PackageVersion Condition="'$(VersionSuffix)' == ''">$(SilkVersion)</PackageVersion>
178191
<PackageVersion Condition="'$(VersionSuffix)' != ''">$(SilkVersion)-$(VersionSuffix)</PackageVersion>
179192
</PropertyGroup>
180-
<!-- Trimming -->
193+
194+
<!-- Native Packaging -->
181195
<PropertyGroup>
182-
<IsTrimmable Condition="'$(SilkTrimmingExempt)' == ''">true</IsTrimmable>
183-
<EnableTrimAnalyzer Condition="'$(SilkTrimmingExempt)' == ''">true</EnableTrimAnalyzer>
184-
<EnableAotAnalyzer Condition="'$(SilkTrimmingExempt)' == ''">true</EnableAotAnalyzer>
185-
<EnableSingleFileAnalyzer Condition="'$(SilkTrimmingExempt)' == ''">true</EnableSingleFileAnalyzer>
186-
<TrimMode Condition="'$(SilkTrimmingExempt)' == ''">full</TrimMode>
196+
<SilkVersionTxtPath>$(MSBuildProjectDirectory)/version.txt</SilkVersionTxtPath>
197+
<PackageVersion Condition="Exists('$(SilkVersionTxtPath)')">$([System.IO.File]::ReadAllText("$(SilkVersionTxtPath)").Trim())</PackageVersion>
198+
<PackageVersion Condition="'$(SilkOriginalVersionSuffix)' != '' and Exists('$(SilkVersionTxtPath)') and $(PackageVersion.Contains('-'))">$(PackageVersion)$(SilkOriginalVersionSuffix)</PackageVersion>
199+
<PackageVersion Condition="'$(SilkOriginalVersionSuffix)' != '' and Exists('$(SilkVersionTxtPath)') and !$(PackageVersion.Contains('-'))">$(PackageVersion)-$(SilkOriginalVersionSuffix)</PackageVersion>
187200
</PropertyGroup>
201+
<Error Text="Native packages should have a version.txt file! Read documentation/for-contributors/build-system.md for more info."
202+
Condition="'$(SilkNativePackage)' == 'true' and !Exists('$(SilkVersionTxtPath)')" />
203+
<ItemGroup Condition="'$(SilkNativePackage)' == 'true'">
204+
<None Include="$(MSBuildProjectDirectory)/runtimes/**/*" Pack="true" PackagePath="runtimes" />
205+
<!-- bundled in the aar instead -->
206+
<None Remove="$(MSBuildProjectDirectory)/runtimes/android*/**/*" Condition="'$(SilkNativeHasAndroidJars)' == 'true'" />
207+
</ItemGroup>
208+
<ItemGroup Condition="'$(SilkNativePackage)' == 'true' and $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
209+
<AndroidNativeLibrary Include="$(MSBuildProjectDirectory)/runtimes/android*/native/*.so" />
210+
<ProguardConfiguration Include="$(MSBuildProjectDirectory)/android/proguard.txt" Condition="Exists('$(MSBuildProjectDirectory)/android/proguard.txt')" />
211+
<AndroidLibrary Include="$(MSBuildProjectDirectory)/android/*.jar" Bind="true" Pack="true" />
212+
<TransformFile Include="$(MSBuildProjectDirectory)/android/*.xml" />
213+
</ItemGroup>
214+
215+
<!-- Trimming -->
216+
<PropertyGroup Condition="'$(SilkTrimmingExempt)' == ''">
217+
<IsTrimmable>true</IsTrimmable>
218+
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
219+
<EnableAotAnalyzer>true</EnableAotAnalyzer>
220+
<EnableSingleFileAnalyzer>true</EnableSingleFileAnalyzer>
221+
<TrimMode>full</TrimMode>
222+
</PropertyGroup>
223+
</Target>
224+
225+
226+
<!-- Closest things to documentation on what the hell this voodoo does:
227+
https://github.com/NuGet/Home/issues/10063#issuecomment-713083004
228+
https://github.com/xamarin/xamarin-android/pull/5242
229+
https://github.com/dotnet/sdk/issues/14042
230+
https://github.com/dotnet/sdk/blob/main/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets#L54
231+
https://github.com/xamarin/xamarin-android/issues/5957
232+
https://github.com/xamarin/xamarin-android/blob/main/Documentation/guides/OneDotNetEmbeddedResources.md
233+
234+
This is an adaptation of what we used in Silk.NET 2.X to add files to packages, which was originally focused on
235+
Android. For 3.0, we're trying to lean as much as possible on the built-in stuff for e.g. jars as this is in a
236+
much better state these days. However, some of the links above may only be relevant with that context. -->
237+
<Target Name="SilkNativePackaging" Condition="'$(SilkNativePackage)' == 'true'">
238+
<GetNuGetShortFolderName TargetFrameworkMoniker="$(TargetFrameworkMoniker)" TargetPlatformMoniker="$(TargetPlatformMoniker)">
239+
<Output TaskParameter="NuGetShortFolderName" PropertyName="SilkNuGetShortFolderName" />
240+
</GetNuGetShortFolderName>
241+
<ReadLinesFromFile File="$(MSBuildThisFileDirectory)eng/native/nuget/NativeNuGetPackage.targets">
242+
<Output TaskParameter="Lines" ItemName="SilkNativeNuGetPackageTargets" />
243+
</ReadLinesFromFile>
244+
<WriteLinesToFile File="$(IntermediateOutputPath)$(TargetFramework)/$(MSBuildProjectName).targets"
245+
Lines="@(SilkNativeNuGetPackageTargets->'%(Identity)'->Replace('TO_BE_REPLACED_MTOUCH_NATIVE_REFERENCE_LINKER_FLAGS', '$(SilkNativeiOSLinkerFlags)')->Replace('TO_BE_REPLACED_PROPERTY_PREFIX', '$(MSBuildProjectName.Replace('.', '_'))'))" />
246+
<WriteLinesToFile File="$(IntermediateOutputPath)$(TargetFramework)/_._" Lines="@(SilkDummyItem)" />
247+
<ItemGroup>
248+
<TfmSpecificPackageFile Include="$(IntermediateOutputPath)$(TargetFramework)/$(MSBuildProjectName).targets"
249+
Link="build/$(SilkNuGetShortFolderName)/$(MSBuildProjectName).targets"
250+
Pack="true"
251+
PackagePath="build/$(SilkNuGetShortFolderName)/$(MSBuildProjectName).targets" />
252+
<TfmSpecificPackageFile Include="$(IntermediateOutputPath)$(TargetFramework)/$(MSBuildProjectName).targets"
253+
Link="build/$(SilkNuGetShortFolderName)/$(MSBuildProjectName).targets"
254+
Pack="true"
255+
PackagePath="buildTransitive/$(SilkNuGetShortFolderName)/$(MSBuildProjectName).targets" />
256+
<TfmSpecificPackageFile Include="$(IntermediateOutputPath)$(TargetFramework)/_._"
257+
Link="lib/$(SilkNuGetShortFolderName)/_._"
258+
Pack="true"
259+
PackagePath="lib/$(SilkNuGetShortFolderName)/_._"
260+
Condition="'$(IncludeBuildOutput)' == 'false'" />
261+
</ItemGroup>
188262
</Target>
189263
</Project>

Silk.NET.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Silk.NET", "sources\Core\Si
9595
EndProject
9696
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Win32", "Win32", "{6E739132-EEAB-43A5-83C7-EB58C50D03A1}"
9797
EndProject
98+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Silk.NET.SDL.Native", "sources\SDL\Native\Silk.NET.SDL.Native.csproj", "{F16C0AB9-DE7E-4C09-9EE9-DAA8B8E935A6}"
99+
EndProject
98100
Global
99101
GlobalSection(SolutionConfigurationPlatforms) = preSolution
100102
Debug|Any CPU = Debug|Any CPU
@@ -153,6 +155,10 @@ Global
153155
{6FA628B8-9696-4847-89F9-E58F470AF4FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
154156
{6FA628B8-9696-4847-89F9-E58F470AF4FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
155157
{6FA628B8-9696-4847-89F9-E58F470AF4FB}.Release|Any CPU.Build.0 = Release|Any CPU
158+
{F16C0AB9-DE7E-4C09-9EE9-DAA8B8E935A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
159+
{F16C0AB9-DE7E-4C09-9EE9-DAA8B8E935A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
160+
{F16C0AB9-DE7E-4C09-9EE9-DAA8B8E935A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
161+
{F16C0AB9-DE7E-4C09-9EE9-DAA8B8E935A6}.Release|Any CPU.Build.0 = Release|Any CPU
156162
EndGlobalSection
157163
GlobalSection(SolutionProperties) = preSolution
158164
HideSolutionNode = FALSE
@@ -182,6 +188,7 @@ Global
182188
{3CADD95A-179F-4ECF-A49D-4B753832C63C} = {475AEF7B-0154-4989-AF82-97E3A95A96AF}
183189
{6FA628B8-9696-4847-89F9-E58F470AF4FB} = {5CD096DB-6C44-48F1-9093-AD4C84B6B7EC}
184190
{6E739132-EEAB-43A5-83C7-EB58C50D03A1} = {DD29EA8F-B1A6-45AA-8D2E-B38DA56D9EF6}
191+
{F16C0AB9-DE7E-4C09-9EE9-DAA8B8E935A6} = {EC4D7B06-D277-4411-BD7B-71A6D37683F0}
185192
EndGlobalSection
186193
GlobalSection(ExtensibilityGlobals) = postSolution
187194
SolutionGuid = {78D2CF6A-60A1-43E3-837B-00B73C9DA384}

0 commit comments

Comments
 (0)