diff --git a/.gitignore b/.gitignore index 88dd960af910..a429b6f8535c 100644 --- a/.gitignore +++ b/.gitignore @@ -202,6 +202,5 @@ launchSettings.json # Testing artifacts testing/ -src/samples/**/Unsafe*.cs -src/samples/**/Swift.*.cs -src/samples/**/Library/*.cs +src/samples/ +GeneratedBindings/ \ No newline at end of file diff --git a/SwiftBindings.sln b/SwiftBindings.sln index 9337598d278c..92b26fef6e45 100644 --- a/SwiftBindings.sln +++ b/SwiftBindings.sln @@ -13,8 +13,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Swift.Runtime.Tests", "src\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Swift.Bindings.Integration.Tests", "src\Swift.Bindings\tests\IntegrationTests\Swift.Bindings.Integration.Tests.csproj", "{CF9035B8-57F0-49A2-B985-94B1F6389339}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Swift.Bindings.Framework.Tests", "src\Swift.Bindings\tests\FrameworkTests\Swift.Bindings.Framework.Tests.csproj", "{BCC05AA9-F43C-478F-B417-D7E4EFD29362}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -88,17 +86,5 @@ Global {CF9035B8-57F0-49A2-B985-94B1F6389339}.Release|x64.Build.0 = Release|Any CPU {CF9035B8-57F0-49A2-B985-94B1F6389339}.Release|x86.ActiveCfg = Release|Any CPU {CF9035B8-57F0-49A2-B985-94B1F6389339}.Release|x86.Build.0 = Release|Any CPU - {BCC05AA9-F43C-478F-B417-D7E4EFD29362}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BCC05AA9-F43C-478F-B417-D7E4EFD29362}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BCC05AA9-F43C-478F-B417-D7E4EFD29362}.Debug|x64.ActiveCfg = Debug|Any CPU - {BCC05AA9-F43C-478F-B417-D7E4EFD29362}.Debug|x64.Build.0 = Debug|Any CPU - {BCC05AA9-F43C-478F-B417-D7E4EFD29362}.Debug|x86.ActiveCfg = Debug|Any CPU - {BCC05AA9-F43C-478F-B417-D7E4EFD29362}.Debug|x86.Build.0 = Debug|Any CPU - {BCC05AA9-F43C-478F-B417-D7E4EFD29362}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BCC05AA9-F43C-478F-B417-D7E4EFD29362}.Release|Any CPU.Build.0 = Release|Any CPU - {BCC05AA9-F43C-478F-B417-D7E4EFD29362}.Release|x64.ActiveCfg = Release|Any CPU - {BCC05AA9-F43C-478F-B417-D7E4EFD29362}.Release|x64.Build.0 = Release|Any CPU - {BCC05AA9-F43C-478F-B417-D7E4EFD29362}.Release|x86.ActiveCfg = Release|Any CPU - {BCC05AA9-F43C-478F-B417-D7E4EFD29362}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/eng/pipelines/common/templates/build-job.yml b/eng/pipelines/common/templates/build-job.yml index 6cd00fb677f1..1ae4b1faeef2 100644 --- a/eng/pipelines/common/templates/build-job.yml +++ b/eng/pipelines/common/templates/build-job.yml @@ -6,6 +6,9 @@ parameters: pool: {} isOfficialBuild: false runTests: true + bindings: + isBindingsBuild: false + scriptArgs: '' jobs: @@ -51,6 +54,10 @@ jobs: /p:TargetPlatform=${{ parameters.archType }} displayName: Build and Test + - ${{ if and(eq(parameters.bindings.isBindingsBuild, true), ne(parameters.osGroup, 'Windows_NT')) }}: + - script: ./generate.sh ${{ parameters.bindings.scriptArgs }} + displayName: Generate Bindings + - ${{ if eq(parameters.isOfficialBuild, true) }}: - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml parameters: diff --git a/eng/pipelines/runtimelab-official.yml b/eng/pipelines/runtimelab-official.yml index 6a7131a6fb13..950bfad57479 100644 --- a/eng/pipelines/runtimelab-official.yml +++ b/eng/pipelines/runtimelab-official.yml @@ -47,6 +47,9 @@ extends: name: Azure Pipelines image: macos-latest os: macOS + bindings: + isBindingsBuild: true + scriptArgs: '--platform MacOSX --arch arm64e-apple-macos --framework StoreKit --framework SwiftUI --experimental' - ${{ if eq(variables.isOfficialBuild, true) }}: - template: /eng/pipelines/common/templates/publish.yml diff --git a/generate.sh b/generate.sh new file mode 100755 index 000000000000..2f8dd9d1399b --- /dev/null +++ b/generate.sh @@ -0,0 +1,138 @@ +#!/usr/bin/env bash + +usage() +{ + echo "Common settings:" + echo " --platform Platform: MacOSX, iPhoneOS, iPhoneSimulator, AppleTVOS, AppleTVSimulator" + echo " --arch Architecture: arm64e-apple-macos, x86_64-apple-macos" + echo " --framework Framework to generate bindings for" + echo " --help Print help and exit (short: -h)" + echo "" + + echo "Actions:" + echo " --experimental Generates only Runtime.Swift namespace when bindings for frameworks are not complete" +} + +source="${BASH_SOURCE[0]}" + +# resolve $SOURCE until the file is no longer a symlink +while [[ -h $source ]]; do + scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" + source="$(readlink "$source")" + + # if $source was a relative symlink, we need to resolve it relative to the path where the + # symlink file was located + [[ $source != /* ]] && source="$scriptroot/$source" +done + +scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" + +platform='' +arch='' +frameworks=() +experimental=false + +output_dir="./GeneratedBindings" + +while [[ $# > 0 ]]; do + opt="$(echo "${1/#--/-}" | tr "[:upper:]" "[:lower:]")" + case "$opt" in + -help|-h) + usage + exit 0 + ;; + -experimental) + experimental=true + ;; + -platform) + platform=$2 + shift + ;; + -arch) + arch=$2 + shift + ;; + -framework) + frameworks+=("$2") + shift + ;; + esac + + shift +done + +# Output directory for generated bindings +rm -rf "$output_dir" +mkdir -p "$output_dir" + +cd "$output_dir" + +# Function to extract ABI file +function ExtractABI { + local framework=$1 + + echo "Generating ABI for framework '$framework', platform '$platform', architecture '$arch'" + + local sdk_path=$(xcrun -sdk $(echo "$platform" | tr '[:upper:]' '[:lower:]') --show-sdk-path) + local swift_interface_path="/Applications/Xcode.app/Contents/Developer/Platforms/${platform}.platform/Developer/SDKs/${platform}.sdk/System/Library/Frameworks/${framework}.framework/Versions/Current/Modules/${framework}.swiftmodule/${arch}.swiftinterface" + + if [ ! -f "$swift_interface_path" ]; then + echo "Error: Swift interface file not found for framework '$framework'." + return 1 + fi + + xcrun swift-frontend -compile-module-from-interface "$swift_interface_path" \ + -module-name "$framework" \ + -sdk "$sdk_path" \ + -emit-abi-descriptor-path "./${framework}.abi.json" +} + +# Function to generate bindings +function InvokeProjectionTooling { + local framework=$1 + + $scriptroot/.dotnet/dotnet $scriptroot/artifacts/bin/Swift.Bindings/Release/net9.0/Swift.Bindings.dll -a "$framework" -o "./" + + if $experimental; then + rm -rf "./Swift.$framework.cs" + fi +} + +# Function to generate NuGet package +function PackNuGet { + local project_file="./Swift.Bindings.${platform}.Experimental.csproj" + + cat < "$project_file" + + + net9.0 + enable + enable + true + true + true + true + + +EOL + + $scriptroot/.dotnet/dotnet pack "$project_file" +} + +function Generate { + for framework in "${frameworks[@]}"; do + echo "Processing framework: $framework" + + if ExtractABI "$framework"; then + InvokeProjectionTooling "$framework" + else + echo "Skipping framework '$framework' due to errors." + fi + done + + PackNuGet + + echo "Process completed." +} + +Generate diff --git a/src/Swift.Bindings/src/Program.cs b/src/Swift.Bindings/src/Program.cs index d4660e045594..986e4a6fff78 100644 --- a/src/Swift.Bindings/src/Program.cs +++ b/src/Swift.Bindings/src/Program.cs @@ -182,11 +182,18 @@ public static void GenerateBindings(Queue paths, string outputDirectory, } // Copy the Swift.Runtime library to the output directory - var libraryDirectory = Path.Combine(Directory.GetParent(outputDirectory)!.FullName, "Library"); - Directory.CreateDirectory(libraryDirectory); - var dirInfo = new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Library")); - foreach (var fileInfo in dirInfo.GetFiles()) - fileInfo.CopyTo(Path.Combine(libraryDirectory, fileInfo.Name), true); + string[] sourceDirectories = { "Metadata", "ManualBindings" }; + foreach (var sourceDir in sourceDirectories) + { + var destinationDirectory = Path.Combine(Directory.GetParent(outputDirectory)!.FullName, sourceDir); + Directory.CreateDirectory(destinationDirectory); + + var sourceDirInfo = new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, sourceDir)); + foreach (var fileInfo in sourceDirInfo.GetFiles()) + { + fileInfo.CopyTo(Path.Combine(destinationDirectory, fileInfo.Name), true); + } + } } /// diff --git a/src/samples/HikingApp/HikingApp.MacCatalyst/.gitignore b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/.gitignore similarity index 100% rename from src/samples/HikingApp/HikingApp.MacCatalyst/.gitignore rename to src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/.gitignore diff --git a/src/samples/HikingApp/HikingApp.MacCatalyst/AppDelegate.cs b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/AppDelegate.cs similarity index 100% rename from src/samples/HikingApp/HikingApp.MacCatalyst/AppDelegate.cs rename to src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/AppDelegate.cs diff --git a/src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Contents.json b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Contents.json rename to src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon1024.png b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon1024.png similarity index 100% rename from src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon1024.png rename to src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon1024.png diff --git a/src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon128.png b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon128.png similarity index 100% rename from src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon128.png rename to src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon128.png diff --git a/src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon16.png b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon16.png similarity index 100% rename from src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon16.png rename to src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon16.png diff --git a/src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon256.png b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon256.png similarity index 100% rename from src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon256.png rename to src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon256.png diff --git a/src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon32.png b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon32.png similarity index 100% rename from src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon32.png rename to src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon32.png diff --git a/src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon512.png b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon512.png similarity index 100% rename from src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon512.png rename to src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon512.png diff --git a/src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon64.png b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon64.png similarity index 100% rename from src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon64.png rename to src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/AppIcon.appiconset/Icon64.png diff --git a/src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/TrailImage.imageset/Contents.json b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/TrailImage.imageset/Contents.json similarity index 100% rename from src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/TrailImage.imageset/Contents.json rename to src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/TrailImage.imageset/Contents.json diff --git a/src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/TrailImage.imageset/TrailImage.svg b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/TrailImage.imageset/TrailImage.svg similarity index 100% rename from src/samples/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/TrailImage.imageset/TrailImage.svg rename to src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Assets.xcassets/TrailImage.imageset/TrailImage.svg diff --git a/src/samples/HikingApp/HikingApp.MacCatalyst/Directory.Build.props b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Directory.Build.props similarity index 100% rename from src/samples/HikingApp/HikingApp.MacCatalyst/Directory.Build.props rename to src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Directory.Build.props diff --git a/src/samples/HikingApp/HikingApp.MacCatalyst/Entitlements.plist b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Entitlements.plist similarity index 100% rename from src/samples/HikingApp/HikingApp.MacCatalyst/Entitlements.plist rename to src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/Entitlements.plist diff --git a/src/samples/HikingApp/HikingApp.MacCatalyst/HikingApp.MacCatalyst.csproj b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/HikingApp.MacCatalyst.csproj similarity index 94% rename from src/samples/HikingApp/HikingApp.MacCatalyst/HikingApp.MacCatalyst.csproj rename to src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/HikingApp.MacCatalyst.csproj index cd4c7496fec0..95699d919863 100644 --- a/src/samples/HikingApp/HikingApp.MacCatalyst/HikingApp.MacCatalyst.csproj +++ b/src/Swift.Bindings/tests/FrameworkTests/HikingApp/HikingApp.MacCatalyst/HikingApp.MacCatalyst.csproj @@ -24,9 +24,14 @@ false - + + + + - + diff --git a/src/Swift.Bindings/tests/TestsHelper.cs b/src/Swift.Bindings/tests/TestsHelper.cs deleted file mode 100644 index 4cc4b23d3917..000000000000 --- a/src/Swift.Bindings/tests/TestsHelper.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Reflection; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Emit; -using Swift.Runtime; - -namespace BindingsGeneration.Tests -{ - public static class TestsHelper - { - private static int uniqueId = 0; - - public static string Compile(string[] filePaths, string[] sourceCodes, string[] dependencies) - { - var expandedFilePaths = ExpandFilePaths(filePaths); - Console.WriteLine($"Expanded file paths: {string.Join(", ", expandedFilePaths)}"); - var fileSourceCodes = expandedFilePaths.Select(File.ReadAllText).ToArray(); - var allSourceCodes = fileSourceCodes.Concat(sourceCodes).ToArray(); - - var options = new CSharpCompilationOptions(OutputKind.ConsoleApplication, allowUnsafe: true); - var syntaxTrees = allSourceCodes.Select(code => CSharpSyntaxTree.ParseText(code)).ToArray(); - - var references = new List - { - MetadataReference.CreateFromFile(typeof(object).Assembly.Location), - MetadataReference.CreateFromFile(typeof(Console).Assembly.Location), - MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location), - MetadataReference.CreateFromFile(typeof(TypeMetadata).Assembly.Location), - MetadataReference.CreateFromFile(Assembly.Load("System.Runtime").Location), - MetadataReference.CreateFromFile(Assembly.Load("System.Runtime.InteropServices").Location), - }; - - foreach (string dependency in dependencies) - { - references.Add(MetadataReference.CreateFromFile(Assembly.Load(dependency).Location)); - } - - var compilation = CSharpCompilation.Create($"CompiledAssembly{uniqueId}", - syntaxTrees: syntaxTrees, - references: references, - options: options); - - string assemblyPath = Path.Combine(Path.GetTempPath(), $"CompiledAssembly{uniqueId++}.dll"); - using (var stream = new FileStream(assemblyPath, FileMode.Create)) - { - EmitResult emitResult = compilation.Emit(stream); - - if (!emitResult.Success) - { - string errorMessage = "Compilation failed:"; - foreach (var diagnostic in emitResult.Diagnostics) - { - errorMessage += $"\n{diagnostic}"; - } - throw new InvalidOperationException(errorMessage); - } - - return assemblyPath; - } - } - - public static object Execute(string assemblyPath, string typeName, string methodName, object[] args) - { - Assembly compiledAssembly = Assembly.LoadFile(assemblyPath); - Type targetType = compiledAssembly.GetType(typeName); - MethodInfo customMethod = targetType.GetMethod(methodName); - return customMethod.Invoke(null, args); - } - - private static IEnumerable ExpandFilePaths(IEnumerable filePaths) - { - foreach (var path in filePaths) - { - if (path.Contains("*")) - { - var dirPath = Path.GetDirectoryName(path); - var searchPattern = Path.GetFileName(path); - foreach (var expandedPath in Directory.GetFiles(dirPath, searchPattern)) - { - yield return expandedPath; - } - } - else - { - yield return path; - } - } - } - } -} diff --git a/src/Swift.Runtime/src/Library/ISwiftObject.cs b/src/Swift.Runtime/src/ManualBindings/ISwiftObject.cs similarity index 100% rename from src/Swift.Runtime/src/Library/ISwiftObject.cs rename to src/Swift.Runtime/src/ManualBindings/ISwiftObject.cs diff --git a/src/Swift.Runtime/src/Library/KnownLibraries.cs b/src/Swift.Runtime/src/ManualBindings/KnownLibraries.cs similarity index 100% rename from src/Swift.Runtime/src/Library/KnownLibraries.cs rename to src/Swift.Runtime/src/ManualBindings/KnownLibraries.cs diff --git a/src/Swift.Runtime/src/Library/SwiftHandle.cs b/src/Swift.Runtime/src/ManualBindings/SwiftHandle.cs similarity index 100% rename from src/Swift.Runtime/src/Library/SwiftHandle.cs rename to src/Swift.Runtime/src/ManualBindings/SwiftHandle.cs diff --git a/src/Swift.Runtime/src/Library/UnsafeBufferPointer.cs b/src/Swift.Runtime/src/ManualBindings/UnsafeBufferPointer.cs similarity index 100% rename from src/Swift.Runtime/src/Library/UnsafeBufferPointer.cs rename to src/Swift.Runtime/src/ManualBindings/UnsafeBufferPointer.cs diff --git a/src/Swift.Runtime/src/Library/UnsafePointer.cs b/src/Swift.Runtime/src/ManualBindings/UnsafePointer.cs similarity index 100% rename from src/Swift.Runtime/src/Library/UnsafePointer.cs rename to src/Swift.Runtime/src/ManualBindings/UnsafePointer.cs diff --git a/src/Swift.Runtime/src/Library/Arc.cs b/src/Swift.Runtime/src/Metadata/Arc.cs similarity index 100% rename from src/Swift.Runtime/src/Library/Arc.cs rename to src/Swift.Runtime/src/Metadata/Arc.cs diff --git a/src/Swift.Runtime/src/Swift.Runtime.csproj b/src/Swift.Runtime/src/Swift.Runtime.csproj index 259dec534f99..deac13e67bb4 100644 --- a/src/Swift.Runtime/src/Swift.Runtime.csproj +++ b/src/Swift.Runtime/src/Swift.Runtime.csproj @@ -15,10 +15,10 @@ PreserveNewest - + PreserveNewest - + PreserveNewest