diff --git a/pkgs/swift2objc/lib/src/ast/declarations/built_in/built_in_declaration.dart b/pkgs/swift2objc/lib/src/ast/declarations/built_in/built_in_declaration.dart index 9c75ba42f..2634cd110 100644 --- a/pkgs/swift2objc/lib/src/ast/declarations/built_in/built_in_declaration.dart +++ b/pkgs/swift2objc/lib/src/ast/declarations/built_in/built_in_declaration.dart @@ -8,6 +8,8 @@ import '../../_core/interfaces/objc_annotatable.dart'; /// Describes a built-in Swift type (e.g Int, String, etc). enum BuiltInDeclaration implements Declaration, ObjCAnnotatable { swiftNSObject(id: 'c:objc(cs)NSObject', name: 'NSObject'), + swiftURL(id: 's:10Foundation3URLV', name: 'URL'), // HACK + swiftTimeInterval(id: 'c:@T@NSTimeInterval', name: 'TimeInterval'), // HACK swiftString(id: 's:SS', name: 'String'), swiftInt(id: 's:Si', name: 'Int'), swiftFloat(id: 's:Sf', name: 'Float'), diff --git a/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_compound_declaration.dart b/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_compound_declaration.dart index f4c4eb7b5..cf3e9a27a 100644 --- a/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_compound_declaration.dart +++ b/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_compound_declaration.dart @@ -83,7 +83,6 @@ T _parseCompoundDeclaration( compound.nestedDeclarations.fillNestingParents(compound); - return compound; } diff --git a/pkgs/swift2objc/lib/src/parser/parsers/parse_type.dart b/pkgs/swift2objc/lib/src/parser/parsers/parse_type.dart index c29746c08..6e7a4231f 100644 --- a/pkgs/swift2objc/lib/src/parser/parsers/parse_type.dart +++ b/pkgs/swift2objc/lib/src/parser/parsers/parse_type.dart @@ -73,7 +73,7 @@ typedef PrefixParselet = (ReferredType, TokenList) Function( if (symbol == null) { throw Exception( - 'The type at "${token.path}" does not exist among parsed symbols: $id'); + 'The type at "${token.path}" does not exist among parsed symbols.'); } final type = parseDeclaration(symbol, symbolgraph).asDeclaredType; diff --git a/pkgs/swiftgen/bin/swiftgen.dart b/pkgs/swiftgen/bin/swiftgen.dart deleted file mode 100644 index 425a61d77..000000000 --- a/pkgs/swiftgen/bin/swiftgen.dart +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:io'; - -import 'package:swiftgen/swiftgen.dart'; -import 'package:logging/logging.dart'; -import 'package:ffigen/ffigen.dart' as ffigen; -import 'package:pub_semver/pub_semver.dart'; - -Future main(List args) async { - Logger.root.onRecord.listen((record) { - stderr.writeln('${record.level.name}: ${record.message}'); - }); - /*generate(Config( - target: Target( - triple: 'x86_64-apple-macosx10.14', - sdk: Uri.directory('/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk'), - ), - input: SwiftFileInput( - module: 'SwiftgenTest', - files: [Uri.file('/Users/liama/dev/native/pkgs/swift2objc/test/integration/classes_and_methods_input.swift')], - ), - tempDir: Uri.directory('temp'), - outputModule: 'SwiftgenTestWrapper', - objcSwiftFile: Uri.file('SwiftgenTestWrapper.swift'), - ffigen: FfiGenConfig( - output: Uri.file('SwiftgenTestWrapper.dart'), - outputObjC: Uri.file('SwiftgenTestWrapper.m'), - externalVersions: ffigen.ExternalVersions( - ios: ffigen.Versions(min: Version(12, 0, 0)), - macos: ffigen.Versions(min: Version(10, 14, 0)), - ), - ), - ));*/ - generate(Config( - target: Target( - triple: 'x86_64-apple-macosx14.0', - sdk: Uri.directory( - '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk'), - ), - input: args.isEmpty - ? SwiftModuleInput( - module: 'AVFAudio', - ) - : JsonFileInput( - module: 'AVFAudio', - jsonFile: Uri.file(args[0]), - ), - tempDir: Uri.directory('temp'), - outputModule: 'AVFAudioWrapper', - objcSwiftFile: Uri.file('AVFAudioWrapper.swift'), - ffigen: FfiGenConfig( - output: Uri.file('AVFAudioWrapper.dart'), - outputObjC: Uri.file('AVFAudioWrapper.m'), - externalVersions: ffigen.ExternalVersions( - ios: ffigen.Versions(min: Version(12, 0, 0)), - macos: ffigen.Versions(min: Version(10, 14, 0)), - ), - objcInterfaces: ffigen.DeclarationFilters( - shouldInclude: (decl) => decl.originalName == 'AVAudioPlayerWrapper', - ), - ), - )); -} diff --git a/pkgs/swiftgen/example/avf_audio_wrapper.swift b/pkgs/swiftgen/example/avf_audio_wrapper.swift index fe189723a..0b2483346 100644 --- a/pkgs/swiftgen/example/avf_audio_wrapper.swift +++ b/pkgs/swiftgen/example/avf_audio_wrapper.swift @@ -1110,8 +1110,12 @@ import Foundation return result == nil ? nil : AVAudioTimeWrapper(result!) } - @objc public func scheduleFile(_ file: AVAudioFileWrapper, at when: AVAudioTimeWrapper?) { - return wrappedInstance.scheduleFile(file.wrappedInstance, at: when?.wrappedInstance) + @objc public func scheduleBuffer(_ buffer: AVAudioPCMBufferWrapper) async { + return await wrappedInstance.scheduleBuffer(buffer.wrappedInstance) + } + + @objc public func scheduleFile(_ file: AVAudioFileWrapper, at when: AVAudioTimeWrapper?) async { + return await wrappedInstance.scheduleFile(file.wrappedInstance, at: when?.wrappedInstance) } @objc public func stop() { diff --git a/pkgs/swiftgen/example/generate_code.dart b/pkgs/swiftgen/example/generate_code.dart index ecaada9c2..8bdd4a73c 100644 --- a/pkgs/swiftgen/example/generate_code.dart +++ b/pkgs/swiftgen/example/generate_code.dart @@ -40,4 +40,25 @@ Future main() async { ), ), )); + + final result = Process.runSync( + 'swiftc', + [ + '-emit-library', + '-o', + 'avf_audio_wrapper.dylib', + '-module-name', + 'AVFAudioWrapper', + 'avf_audio_wrapper.swift', + '-framework', + 'AVFAudio', + '-framework', + 'Foundation', + ], + ); + if (result.exitCode != 0) { + print("Failed to build the swift wrapper library"); + print(result.stdout); + print(result.stderr); + } } diff --git a/pkgs/swiftgen/example/play_audio.dart b/pkgs/swiftgen/example/play_audio.dart index 4e43efec9..dcc8d061f 100644 --- a/pkgs/swiftgen/example/play_audio.dart +++ b/pkgs/swiftgen/example/play_audio.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:ffi'; +import 'dart:io'; import 'package:objective_c/objective_c.dart'; import 'avf_audio_bindings.dart'; @@ -12,19 +13,23 @@ import '../../objective_c/test/setup.dart' as objCSetup; const _dylibPath = '/System/Library/Frameworks/AVFAudio.framework/Versions/Current/AVFAudio'; -// swiftc -emit-library -o avf_audio_wrapper.dylib -module-name AVFAudioWrapper avf_audio_wrapper.swift -framework AVFAudio -framework Foundation -const _wrapperDylibPath = 'avf_audio_wrapper.dylib'; +const _wrapperDylib = 'avf_audio_wrapper.dylib'; void main(List args) async { + if (args.length == 0) { + print("Usage: dart play_audio.dart file1.wav file2.mp3 ..."); + return; + } + objCSetup.main([]); DynamicLibrary.open(_dylibPath); - DynamicLibrary.open(_wrapperDylibPath); + DynamicLibrary.open(Platform.script.resolve(_wrapperDylib).toFilePath()); for (final file in args) { final fileStr = NSString(file); print('Loading $fileStr'); final fileUrl = NSURL.fileURLWithPath_(fileStr); - final player = - AVAudioPlayerWrapper.alloc().initWithContentsOf_error_(fileUrl, nullptr); + final player = AVAudioPlayerWrapper.alloc() + .initWithContentsOf_error_(fileUrl, nullptr); if (player == null) { print('Failed to load audio'); continue; diff --git a/pkgs/swiftgen/test/integration/util.dart b/pkgs/swiftgen/test/integration/util.dart index aac50482a..75716878b 100644 --- a/pkgs/swiftgen/test/integration/util.dart +++ b/pkgs/swiftgen/test/integration/util.dart @@ -24,7 +24,8 @@ class TestGenerator { late final String actualOutputFile; TestGenerator(this.name) { - testDir = path.absolute(path.join(Directory.current.path, 'test/integration')); + testDir = + path.absolute(path.join(Directory.current.path, 'test/integration')); tempDir = path.join(testDir, 'temp'); inputFile = path.join(testDir, '${name}.swift'); wrapperFile = path.join(tempDir, '${name}_wrapper.swift'); @@ -38,21 +39,21 @@ class TestGenerator { } Future generateBindings() async => generate(Config( - target: await Target.host(), - input: SwiftFileInput( - module: name, - files: [Uri.file(inputFile)], - ), - objcSwiftFile: Uri.file(wrapperFile), - tempDir: Directory(tempDir).uri, - ffigen: FfiGenConfig( - output: Uri.file(outputFile), - outputObjC: Uri.file(outputObjCFile), - objcInterfaces: DeclarationFilters( - shouldInclude: (decl) => decl.originalName.startsWith('Test'), + target: await Target.host(), + input: SwiftFileInput( + module: name, + files: [Uri.file(inputFile)], ), - ), - )); + objcSwiftFile: Uri.file(wrapperFile), + tempDir: Directory(tempDir).uri, + ffigen: FfiGenConfig( + output: Uri.file(outputFile), + outputObjC: Uri.file(outputObjCFile), + objcInterfaces: DeclarationFilters( + shouldInclude: (decl) => decl.originalName.startsWith('Test'), + ), + ), + )); Future generateAndVerifyBindings() async { // Run the generation pipeline. This produces the swift compatability @@ -68,16 +69,26 @@ class TestGenerator { expect(File(objWrapperFile).existsSync(), isTrue); // We also need to compile outputObjCFile to an obj file. - await run('clang', - ['-x', 'objective-c', '-c', outputObjCFile, '-fpic', '-o', objObjCFile], - tempDir); + await run( + 'clang', + ['-x', 'objective-c', '-c', outputObjCFile, '-fpic', '-o', objObjCFile], + tempDir); expect(File(objObjCFile).existsSync(), isTrue); // Link all the obj files into a dylib. - await run('clang', - ['-shared', '-framework', 'Foundation', objInputFile, - objWrapperFile, objObjCFile, '-o', dylibFile], - tempDir); + await run( + 'clang', + [ + '-shared', + '-framework', + 'Foundation', + objInputFile, + objWrapperFile, + objObjCFile, + '-o', + dylibFile + ], + tempDir); expect(File(dylibFile).existsSync(), isTrue); } } diff --git a/pkgs/swiftgen/tool/regen_test_bindings.dart b/pkgs/swiftgen/tool/regen_test_bindings.dart index fa307985d..84918a0c8 100644 --- a/pkgs/swiftgen/tool/regen_test_bindings.dart +++ b/pkgs/swiftgen/tool/regen_test_bindings.dart @@ -15,12 +15,12 @@ Future regenIntegrationTestBindings(String name) async { } const testSuffix = '_test.dart'; -List findAllIntegrationTests() => - Directory(TestGenerator('').testDir) - .listSync() - .map((entity) => path.basename(entity.path)) - .where((f) => f.endsWith(testSuffix)) - .map((f) => f.substring(0, f.length - testSuffix.length)).toList(); +List findAllIntegrationTests() => Directory(TestGenerator('').testDir) + .listSync() + .map((entity) => path.basename(entity.path)) + .where((f) => f.endsWith(testSuffix)) + .map((f) => f.substring(0, f.length - testSuffix.length)) + .toList(); Future main(List args) async { for (final name in args.isEmpty ? findAllIntegrationTests() : args) {