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
2 changes: 1 addition & 1 deletion eng/pipelines/common/templates/build-job.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
displayName: Build and Test

- ${{ if and(eq(parameters.bindings.isBindingsBuild, true), ne(parameters.osGroup, 'Windows_NT')) }}:
- script: ./generate.sh ${{ parameters.bindings.scriptArgs }}
- script: ./generate.sh --configuration $(_BuildConfig) ${{ parameters.bindings.scriptArgs }}
displayName: Generate Bindings

- ${{ if eq(parameters.isOfficialBuild, true) }}:
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/runtimelab-official.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ extends:
os: macOS
bindings:
isBindingsBuild: true
scriptArgs: '--platform MacOSX --arch arm64e-apple-macos --framework StoreKit --framework SwiftUI --experimental'
scriptArgs: '--platform MacOSX --arch arm64e-apple-macos --framework StoreKit --experimental'

- ${{ if eq(variables.isOfficialBuild, true) }}:
- template: /eng/pipelines/common/templates/publish.yml
Expand Down
6 changes: 6 additions & 0 deletions eng/pipelines/runtimelab.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ stages:
runTests: true
pool:
vmImage: 'macOS-latest'
bindings:
isBindingsBuild: true
scriptArgs: '--platform MacOSX --arch arm64e-apple-macos --framework StoreKit'

- template: /eng/pipelines/common/templates/build-job.yml
parameters:
Expand All @@ -65,3 +68,6 @@ stages:
runTests: true
pool:
vmImage: 'macOS-latest'
bindings:
isBindingsBuild: true
scriptArgs: '--platform MacOSX --arch x86_64-apple-macos --framework StoreKit'
20 changes: 17 additions & 3 deletions generate.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#!/usr/bin/env bash
set -e
set -o pipefail

usage()
{
echo "Common settings:"
echo " --platform <value> Platform: MacOSX, iPhoneOS, iPhoneSimulator, AppleTVOS, AppleTVSimulator"
echo " --arch <value> Architecture: arm64e-apple-macos, x86_64-apple-macos"
echo " --framework Framework to generate bindings for"
echo " --framework <value> Framework to generate bindings for"
echo " --configuration <value> Configuration: Debug, Release"
echo " --help Print help and exit (short: -h)"
echo ""

Expand All @@ -30,6 +33,7 @@ scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
platform=''
arch=''
frameworks=()
configuration='Debug'
experimental=false

output_dir="./GeneratedBindings"
Expand All @@ -56,6 +60,10 @@ while [[ $# > 0 ]]; do
frameworks+=("$2")
shift
;;
-configuration)
configuration=$2
shift
;;
esac

shift
Expand Down Expand Up @@ -84,14 +92,19 @@ function ExtractABI {
xcrun swift-frontend -compile-module-from-interface "$swift_interface_path" \
-module-name "$framework" \
-sdk "$sdk_path" \
-emit-abi-descriptor-path "./${framework}.abi.json"
-emit-abi-descriptor-path "./$framework.abi.json"
}

# Function to generate bindings
function InvokeProjectionTooling {
local framework=$1

$scriptroot/dotnet.sh $scriptroot/artifacts/bin/Swift.Bindings/Release/net9.0/Swift.Bindings.dll -a "$framework" -o "./"
$scriptroot/dotnet.sh $scriptroot/artifacts/bin/Swift.Bindings/$configuration/net9.0/Swift.Bindings.dll -a "./$framework.abi.json" -d "/System/Library/Frameworks/$framework.framework/$framework" -o "./"

echo ""
echo "C# source code for Swift.$framework.cs:"
cat "./Swift.$framework.cs"
echo ""

if $experimental; then
rm -rf "./Swift.$framework.cs"
Expand Down Expand Up @@ -124,6 +137,7 @@ function Generate {
echo "Processing framework: $framework"

if ExtractABI "$framework"; then
echo "Generating bindings for framework '$framework'"
InvokeProjectionTooling "$framework"
else
echo "Skipping framework '$framework' due to errors."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ public IEnvironment Marshal(BaseDecl decl, TypeDatabase typeDatabase)
public void Emit(IndentedTextWriter writer, IEnvironment env, Conductor conductor)
{
var methodEnv = (MethodEnvironment)env;
if (methodEnv.SignatureHandler.GetWrapperSignature().ContainsPlaceholder)
{
Console.WriteLine($"Method {methodEnv.MethodDecl.Name} has unsupported signature: ({methodEnv.SignatureHandler.GetWrapperSignature().ParametersString()}) -> {methodEnv.SignatureHandler.GetWrapperSignature().ReturnType}");
return;
}

EmitWrapper(writer, methodEnv);
PInvokeEmitter.EmitPInvoke(writer, methodEnv);
writer.WriteLine();
Expand Down Expand Up @@ -159,6 +165,11 @@ public IEnvironment Marshal(BaseDecl decl, TypeDatabase typeDatabase)
public void Emit(IndentedTextWriter writer, IEnvironment env, Conductor conductor)
{
var methodEnv = (MethodEnvironment)env;
if (methodEnv.SignatureHandler.GetWrapperSignature().ContainsPlaceholder)
{
Console.WriteLine($"Method {methodEnv.MethodDecl.Name} has unsupported signature: ({methodEnv.SignatureHandler.GetWrapperSignature().ParametersString()}) -> {methodEnv.SignatureHandler.GetWrapperSignature().ReturnType}");
return;
}

EmitWrapperMethod(writer, methodEnv);
PInvokeEmitter.EmitPInvoke(writer, methodEnv);
Expand All @@ -178,7 +189,7 @@ private void EmitWrapperMethod(IndentedTextWriter writer, MethodEnvironment env)
var pInvokeName = NameProvider.GetPInvokeName(methodDecl);
var staticKeyword = methodDecl.MethodType == MethodType.Static || parentDecl is ModuleDecl ? "static " : "";

writer.WriteLine($"public {staticKeyword}{methodDecl.CSSignature.First().CSTypeIdentifier.Name} {methodDecl.Name}({env.SignatureHandler.GetWrapperSignature().ParametersString()})");
writer.WriteLine($"public {staticKeyword}{env.SignatureHandler.GetWrapperSignature().ReturnType} {methodDecl.Name}({env.SignatureHandler.GetWrapperSignature().ParametersString()})");
writer.WriteLine("{");
writer.Indent++;

Expand Down Expand Up @@ -220,6 +231,7 @@ public record Parameter(string Type, string Name)
/// <param name="Parameters"></param>
public record Signature(string ReturnType, IReadOnlyList<Parameter> Parameters)
{
public bool ContainsPlaceholder => Parameters.Any(p => p.Type == "AnyType") || ReturnType == "AnyType";
public string ParametersString() => string.Join(", ", Parameters.Select(p => p.ToString()));

public string CallArgumentsString() => string.Join(", ", Parameters.Select(p =>
Expand All @@ -230,7 +242,6 @@ public class WrapperSignatureBuilder
{
private string _returnType = "invalid";
private readonly List<Parameter> _parameters = new();

MethodDecl MethodDecl { get; }
BaseDecl ParentDecl { get; }
TypeDatabase TypeDatabase { get; }
Expand All @@ -247,7 +258,14 @@ public WrapperSignatureBuilder(MethodDecl methodDecl, TypeDatabase typeDatabase)
/// </summary>
public void HandleReturnType()
{
var returnType = MethodDecl.CSSignature.First().CSTypeIdentifier.Name;
var argument = MethodDecl.CSSignature.First();
var returnType = argument.CSTypeIdentifier.Name;
var typeRecord = MarshallingHelpers.GetType(argument, TypeDatabase.Registrar);
if (typeRecord == null || !typeRecord.IsProcessed)
{
Console.WriteLine($"Method {MethodDecl.Name} has unprocessed return type {returnType}");
returnType = "AnyType";
}
SetReturnType(returnType);
}

Expand All @@ -258,7 +276,14 @@ public void HandleArguments()
{
foreach (var argument in MethodDecl.CSSignature.Skip(1))
{
AddParameter(argument.CSTypeIdentifier.Name, argument.Name);
string typeIdentifier = argument.CSTypeIdentifier.Name;
var typeRecord = MarshallingHelpers.GetType(argument, TypeDatabase.Registrar);
if (typeRecord == null || !typeRecord.IsProcessed)
{
Console.WriteLine($"Method {MethodDecl.Name} has unprocessed argument {typeIdentifier}");
typeIdentifier = "AnyType";
}
AddParameter(typeIdentifier, argument.Name);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,8 @@ public void Emit(IndentedTextWriter writer, IEnvironment env, Conductor conducto
writer.WriteLine($"using System.Runtime.CompilerServices;");
writer.WriteLine($"using System.Runtime.InteropServices;");
writer.WriteLine($"using System.Runtime.InteropServices.Swift;");
writer.WriteLine($"using Swift;");
writer.WriteLine($"using Swift.Runtime;");

foreach (var dependency in moduleDecl.Dependencies)
writer.WriteLine(dependency.Contains("Swift.") ? $"using {dependency};" : $"using Swift.{dependency};");


writer.WriteLine();
writer.WriteLine($"namespace {generatedNamespace}");
writer.WriteLine("{");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ private static void WriteDisposeMethod(IndentedTextWriter writer, string classNa
writer.WriteLine("{");
writer.Indent++;
writer.WriteLine("NativeMemory.Free((void*)_payload);");
writer.WriteLine("_payload = SwiftHandle.Zero;");
writer.WriteLine("_disposed = true;");
writer.WriteLine("GC.SuppressFinalize(this);");
writer.Indent--;
Expand All @@ -251,6 +252,7 @@ private static void WriteFinalizer(IndentedTextWriter writer, string className)
writer.WriteLine("{");
writer.Indent++;
writer.WriteLine("NativeMemory.Free((void*)_payload);");
writer.WriteLine("_payload = SwiftHandle.Zero;");
writer.Indent--;
writer.WriteLine("}");
}
Expand Down
17 changes: 10 additions & 7 deletions src/Swift.Bindings/src/Marshaler/MarshallingHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,22 @@ public static bool StructIsMarshalledAsCSStruct(StructDecl decl)

public static bool ArgumentIsMarshalledAsCSStruct(ArgumentDecl argumentDecl, TypeDatabase typeDatabase)
{
var typeRecord = GetType(argumentDecl, typeDatabase.Registrar); //TODO: Add information to typeRecord if thing is a struct
var typeRecord = GetType(argumentDecl, typeDatabase.Registrar) ?? throw new NotImplementedException($"Type {argumentDecl.Name} not found in type database"); //TODO: Add information to typeRecord if thing is a struct
return typeRecord.IsFrozen && typeRecord.IsBlittable;
}

private static TypeRecord GetType(ArgumentDecl argumentDecl, TypeRegistrar typeRegistrar)
public static TypeRecord GetType(ArgumentDecl argumentDecl, TypeRegistrar typeRegistrar)
{
if (argumentDecl.SwiftTypeSpec is not NamedTypeSpec swiftTypeSpec)
switch (argumentDecl.SwiftTypeSpec)
{
throw new NotImplementedException($"{argumentDecl} is not a NamedTypeSpec");
case NamedTypeSpec namedTypeSpec:
string typeIdentifier = namedTypeSpec.GenericParameters.Count > 0 ? $"{namedTypeSpec.NameWithoutModule}`{namedTypeSpec.GenericParameters.Count}" : namedTypeSpec.NameWithoutModule;
return typeRegistrar.GetType(namedTypeSpec.Module, typeIdentifier) ?? throw new NotImplementedException($"Type ${argumentDecl} not found in type database");
case TupleTypeSpec tupleTypeSpec:
return typeRegistrar.GetType(string.Empty, tupleTypeSpec.ToString(true)) ?? throw new NotImplementedException($"Type ${argumentDecl} not found in type database");
default:
throw new NotImplementedException($"{argumentDecl} is not supported");
}

var typeRecord = typeRegistrar.GetType(swiftTypeSpec.Module, swiftTypeSpec.NameWithoutModule) ?? throw new NotImplementedException($"Type {swiftTypeSpec.Name} not found in type database");
return typeRecord;
}
}
}
11 changes: 11 additions & 0 deletions src/Swift.Bindings/src/Model/BaseDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,19 @@ public record BaseDecl
/// </summary>
public required string Name { get; set; }

/// <summary>
/// The fully qualified name of the declaration used for type registration.
/// </summary>
public required string FullyQualifiedName { get; set; }

/// <summary>
/// The parent declaration.
/// </summary>
public required BaseDecl? ParentDecl { get; set; }

/// <summary>
/// The module declaration.
/// </summary>
public required BaseDecl? ModuleDecl { get; set; }
}
}
5 changes: 0 additions & 5 deletions src/Swift.Bindings/src/Parser/ISwiftParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@ namespace BindingsGeneration
/// </summary>
public interface ISwiftParser
{
/// <summary>
/// Sets parser filter.
/// </summary>
public void SetFilter(List<string> filters);

/// <summary>
/// Gets the module name.
/// </summary>
Expand Down
Loading