Skip to content
Merged
25 changes: 17 additions & 8 deletions pkgs/ffigen/lib/src/code_generator/library.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import 'package:yaml_edit/yaml_edit.dart';

import '../code_generator.dart';
import '../code_generator/utils.dart';
import '../config_provider/config_types.dart';
import '../config_provider/config.dart';
import '../context.dart';

import 'writer.dart';
Expand All @@ -27,15 +27,19 @@ class Library {
required List<Binding> bindings,
required Context context,
}) => Library(
description: context.config.wrapperDocComment,
description: switch (context.config.output.style) {
final DynamicLibraryBindings e => e.wrapperDocComment,
_ => null,
},
bindings: bindings,
header: context.config.preamble,
header: context.config.output.preamble,
generateForPackageObjectiveC:
// ignore: deprecated_member_use_from_same_package
context.config.objectiveC?.generateForPackageObjectiveC ?? false,
libraryImports: context.config.libraryImports.values.toList(),
// ignore: deprecated_member_use_from_same_package
libraryImports: context.config.libraryImports,
silenceEnumWarning: context.config.enums.silenceWarning,
nativeEntryPoints: context.config.entryPoints
nativeEntryPoints: context.config.headers.entryPoints
.map((uri) => uri.toFilePath())
.toList(),
context: context,
Expand All @@ -54,13 +58,18 @@ class Library {
// Seperate bindings which require lookup.
final lookupBindings = <LookUpBinding>[];
final nativeBindings = <LookUpBinding>[];
FfiNativeConfig? nativeConfig;
String? nativeAssetId;

final outputStyle = context.config.output.style;
final outputStyleAssetId = outputStyle is NativeExternalBindings
? outputStyle.assetId
: null;

for (final binding in bindings.whereType<LookUpBinding>()) {
final loadFromNativeAsset = binding.loadFromNativeAsset;

// At the moment, all bindings share their native config.
if (loadFromNativeAsset) nativeConfig = context.config.ffiNativeConfig;
if (loadFromNativeAsset) nativeAssetId = outputStyleAssetId;

(loadFromNativeAsset ? nativeBindings : lookupBindings).add(binding);
}
Expand All @@ -69,7 +78,7 @@ class Library {
final writer = Writer(
lookUpBindings: lookupBindings,
ffiNativeBindings: nativeBindings,
nativeAssetId: nativeConfig?.assetId,
nativeAssetId: nativeAssetId,
noLookUpBindings: noLookUpBindings,
classDocComment: description,
header: header,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,9 @@ class ObjCBuiltInFunctions {
// a hash of parts of the config.
static String _libraryIdFromConfigHash(Config config) => fnvHash32(
[
...config.entryPoints,
config.output,
config.outputObjC,
...config.headers.entryPoints,
config.output.dartFile,
config.output.objCFile,
].map((uri) => path.basename(uri.toFilePath())).join('\n'),
).toRadixString(36);
}
Expand Down
71 changes: 1 addition & 70 deletions pkgs/ffigen/lib/src/config_provider/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -647,8 +647,7 @@ final class Output {
/// The output Objective-C file for the generated Objective-C bindings.
final Uri? objectiveCFile;

Uri get _objectiveCFile =>
objectiveCFile ?? Uri.file('${dartFile.toFilePath()}.m');
Uri get objCFile => objectiveCFile ?? Uri.file('${dartFile.toFilePath()}.m');

/// The config for the symbol file.
final SymbolFile? symbolFile;
Expand Down Expand Up @@ -717,74 +716,8 @@ final class DynamicLibraryBindings implements BindingStyle {
}

extension type Config(FfiGenerator ffiGen) implements FfiGenerator {
ObjectiveC get _objectiveC => ffiGen.objectiveC ?? const ObjectiveC();
bool get includeTransitiveObjCInterfaces =>
_objectiveC.interfaces.includeTransitive;
bool get includeTransitiveObjCProtocols =>
_objectiveC.protocols.includeTransitive;
bool get includeTransitiveObjCCategories =>
_objectiveC.categories.includeTransitive;
String? Function(Declaration declaration) get interfaceModule =>
(declaration) => _objectiveC.interfaces.module(declaration);
String? Function(Declaration declaration) get protocolModule =>
(declaration) => _objectiveC.protocols.module(declaration);
bool get generateForPackageObjectiveC =>
// ignore: deprecated_member_use_from_same_package
_objectiveC.generateForPackageObjectiveC;
Categories get objcCategories => _objectiveC.categories;
Interfaces get objcInterfaces => _objectiveC.interfaces;
Protocols get objcProtocols => _objectiveC.protocols;
ExternalVersions get externalVersions => _objectiveC.externalVersions;
// ignore: deprecated_member_use_from_same_package
Map<String, ImportedType> get importedTypesByUsr => ffiGen.importedTypesByUsr;
String get wrapperName =>
(ffiGen.output.style as DynamicLibraryBindings).wrapperName;

String? get wrapperDocComment => switch (ffiGen.output.style) {
final DynamicLibraryBindings e => e.wrapperDocComment,
_ => null,
};

FfiNativeConfig get ffiNativeConfig => FfiNativeConfig(
enabled: ffiGen.output.style is NativeExternalBindings,
assetId: switch (ffiGen.output.style) {
final NativeExternalBindings e => e.assetId,
_ => null,
},
);

bool shouldIncludeHeader(Uri header) => ffiGen.headers.include(header);

bool get ignoreSourceErrors => ffiGen.headers.ignoreSourceErrors;

List<String>? get compilerOpts => ffiGen.headers.compilerOptions;

List<Uri> get entryPoints => ffiGen.headers.entryPoints;

Uri get output => ffiGen.output.dartFile;

Uri get outputObjC => ffiGen.output._objectiveCFile;

BindingStyle get outputStyle => ffiGen.output.style;

SymbolFile? get symbolFile => ffiGen.output.symbolFile;

bool get sort => ffiGen.output.sort;

CommentType get commentType => ffiGen.output.commentType;

String? get preamble => ffiGen.output.preamble;

bool get formatOutput => ffiGen.output.format;

// Override declarative user spec with what FFIgen internals expect.
Map<String, LibraryImport> get libraryImports =>
Map<String, LibraryImport>.fromEntries(
// ignore: deprecated_member_use_from_same_package
ffiGen.libraryImports.map(
(import) => MapEntry<String, LibraryImport>(import.name, import),
),
);

// Override declarative user spec with what FFIgen internals expect.
Map<String, ImportedType> get typedefTypeMappings =>
Expand Down Expand Up @@ -820,6 +753,4 @@ extension type Config(FfiGenerator ffiGen) implements FfiGenerator {
(import) => MapEntry<String, ImportedType>(import.nativeType, import),
),
);

Language get language => objectiveC != null ? Language.objc : Language.c;
}
3 changes: 2 additions & 1 deletion pkgs/ffigen/lib/src/context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class Context {
bool hasSourceErrors = false;
final reportedCommentRanges = <((String, int), (String, int))>{};
final libs = LibraryImports();
late final compilerOpts = config.compilerOpts ?? defaultCompilerOpts(logger);
late final compilerOpts =
config.headers.compilerOptions ?? defaultCompilerOpts(logger);
final Scope rootScope = Scope.createRoot('root');
final Scope rootObjCScope = Scope.createRoot('objc_root');
late final ExtraSymbols extraSymbols;
Expand Down
13 changes: 7 additions & 6 deletions pkgs/ffigen/lib/src/ffigen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ extension FfiGenGenerator on FfiGenerator {
final library = parse(context);

// Generate files for the parsed bindings.
final gen = File(config.output.toFilePath());
library.generateFile(gen, format: config.formatOutput);
final gen = File(config.output.dartFile.toFilePath());
library.generateFile(gen, format: config.ffiGen.output.format);
logger.info(
_successPen('Finished, Bindings generated in ${gen.absolute.path}'),
);

final objCGen = File(config.outputObjC.toFilePath());
final objCGen = File(config.output.objCFile.toFilePath());
if (library.generateObjCFile(objCGen)) {
logger.info(
_successPen(
Expand All @@ -44,11 +44,12 @@ extension FfiGenGenerator on FfiGenerator {
);
}

if (config.symbolFile != null) {
final symbolFileGen = File(config.symbolFile!.output.toFilePath());
final symbolFile = config.output.symbolFile;
if (symbolFile != null) {
final symbolFileGen = File(symbolFile.output.toFilePath());
library.generateSymbolOutputFile(
symbolFileGen,
config.symbolFile!.importPath.toString(),
symbolFile.importPath.toString(),
);
logger.info(
_successPen(
Expand Down
18 changes: 9 additions & 9 deletions pkgs/ffigen/lib/src/header_parser/parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ List<Binding> parseToBindings(Context context) {
Pointer<Pointer<Utf8>> clangCmdArgs = nullptr;
final compilerOpts = <String>[
// Add compiler opt for comment parsing for clang based on config.
if (config.commentType.length != CommentLength.none &&
config.commentType.style == CommentStyle.any)
if (config.output.commentType.length != CommentLength.none &&
config.output.commentType.style == CommentStyle.any)
strings.fparseAllComments,

// If the config targets Objective C, add a compiler opt for it.
if (config.language == Language.objc) ...[
if (config.objectiveC != null) ...[
...strings.clangLangObjC,
..._findObjectiveCSysroot(),
],
Expand All @@ -72,12 +72,12 @@ List<Binding> parseToBindings(Context context) {
final bindings = <Binding>{};

// Log all headers for user.
context.logger.info('Input Headers: ${config.entryPoints}');
context.logger.info('Input Headers: ${config.headers.entryPoints}');

final tuList = <Pointer<clang_types.CXTranslationUnitImpl>>[];

// Parse all translation units from entry points.
for (final headerLocationUri in config.entryPoints) {
for (final headerLocationUri in config.headers.entryPoints) {
final headerLocation = headerLocationUri.toFilePath();
context.logger.fine('Creating TranslationUnit for header: $headerLocation');

Expand Down Expand Up @@ -114,11 +114,11 @@ List<Binding> parseToBindings(Context context) {
'The compiler found warnings/errors in source files.',
);
context.logger.warning('This will likely generate invalid bindings.');
if (config.ignoreSourceErrors) {
if (config.headers.ignoreSourceErrors) {
context.logger.warning(
'Ignored source errors. (User supplied --ignore-source-errors)',
);
} else if (config.language == Language.objc) {
} else if (config.objectiveC != null) {
context.logger.warning('Ignored source errors. (ObjC)');
} else {
context.logger.severe(
Expand Down Expand Up @@ -219,7 +219,7 @@ List<Binding> transformBindings(List<Binding> bindings, Context context) {

/// Sort bindings.
var finalBindingsList = finalBindings.toList();
if (config.sort) {
if (config.output.sort) {
finalBindingsList = visit(
context,
SorterVisitation(finalBindings, SorterVisitation.nameSortKey),
Expand Down Expand Up @@ -283,7 +283,7 @@ void _nameAllSymbols(Context context, Set<Binding> bindings) {
}

ExtraSymbols _createExtraSymbols(Context context) {
final bindingStyle = context.config.outputStyle;
final bindingStyle = context.config.output.style;
Symbol? wrapperClassName;
Symbol? lookupFuncName;
if (bindingStyle is DynamicLibraryBindings) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class ApiAvailability {
this.alwaysUnavailable = false,
this.ios,
this.macos,
required ExternalVersions externalVersions,
required ExternalVersions? externalVersions,
}) {
availability = _getAvailability(externalVersions);
}
Expand Down Expand Up @@ -88,7 +88,7 @@ class ApiAvailability {
alwaysUnavailable: alwaysUnavailable.value != 0,
ios: ios,
macos: macos,
externalVersions: context.config.externalVersions,
externalVersions: context.config.objectiveC?.externalVersions,
);

for (var i = 0; i < platformsLength; ++i) {
Expand All @@ -101,9 +101,9 @@ class ApiAvailability {
return api;
}

Availability _getAvailability(ExternalVersions externalVersions) {
final macosVer = _normalizeVersions(externalVersions.macos);
final iosVer = _normalizeVersions(externalVersions.ios);
Availability _getAvailability(ExternalVersions? externalVersions) {
final macosVer = _normalizeVersions(externalVersions?.macos);
final iosVer = _normalizeVersions(externalVersions?.ios);

// If no versions are specified, everything is available.
if (iosVer == null && macosVer == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.

import '../../code_generator.dart';
import '../../config_provider/config.dart';
import '../../config_provider/config_types.dart';
import '../../context.dart';
import '../clang_bindings/clang_bindings.dart' as clang_types;
Expand Down Expand Up @@ -151,7 +152,7 @@ List<Func> parseFunctionDeclaration(
exposeFunctionTypedefs: config.functions.includeTypedef(decl),
isLeaf: config.functions.isLeaf(decl),
objCReturnsRetained: objCReturnsRetained,
loadFromNativeAsset: config.ffiNativeConfig.enabled,
loadFromNativeAsset: config.output.style is NativeExternalBindings,
),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ File createFileForMacros(Context context) {

// Write file contents.
final sb = StringBuffer();
for (final h in context.config.entryPoints) {
for (final h in context.config.headers.entryPoints) {
final fullHeaderPath = File(h.toFilePath()).absolute.path;
sb.writeln('#include "$fullHeaderPath"');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ ObjCCategory? parseObjCCategoryDeclaration(
Context context,
clang_types.CXCursor cursor,
) {
final config = context.config;
final objcCategories = context.config.objectiveC?.categories;
if (objcCategories == null) {
return null;
}

final logger = context.logger;
final usr = cursor.usr();
final name = cursor.spelling();
Expand Down Expand Up @@ -58,7 +62,7 @@ ObjCCategory? parseObjCCategoryDeclaration(
final category = ObjCCategory(
usr: usr,
originalName: name,
name: config.objcCategories.rename(decl),
name: objcCategories.rename(decl),
parent: parentInterface,
dartDoc: getCursorDocComment(
context,
Expand All @@ -84,15 +88,15 @@ ObjCCategory? parseObjCCategoryDeclaration(
context,
child,
decl,
config.objcCategories,
objcCategories,
);
category.addMethod(getter);
category.addMethod(setter);
break;
case clang_types.CXCursorKind.CXCursor_ObjCInstanceMethodDecl:
case clang_types.CXCursorKind.CXCursor_ObjCClassMethodDecl:
category.addMethod(
parseObjCMethod(context, child, decl, config.objcCategories),
parseObjCMethod(context, child, decl, objcCategories),
);
break;
}
Expand Down
Loading
Loading