blob: c376625a7f9c807cf65ae59f72803dfe57b68d93 [file] [edit]
// Copyright (c) 2026, 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:ffigen/ffigen.dart';
const ffiImport = LibraryImport('ffi', 'dart:ffi');
const customImport = LibraryImport('custom_import', 'custom_import.dart');
ImportedType? importType(Declaration declaration) {
if (declaration.originalName == 'time_t') {
return ImportedType(ffiImport, 'Int64', 'int', 'time_t');
}
if (declaration.originalName == 'CXCursorSetImpl') {
return ImportedType(
customImport,
'CXCursorSetImpl',
'CXCursorSetImpl',
'CXCursorSetImpl',
);
}
return null;
}
FfiGenerator getConfig([Uri? packageRoot]) {
packageRoot ??= Platform.script.resolve('../');
final libclangInclude = packageRoot
.resolve('../../third_party/libclang/include')
.toFilePath();
return FfiGenerator(
output: Output(
dart: DartOutput(path: packageRoot.resolve('generated_bindings.dart')),
style: const DynamicLibraryBindings(
wrapperName: 'LibClang',
wrapperDocComment: 'Holds bindings to LibClang.',
),
preamble: '''
// Part of the LLVM Project, under the Apache License v2.0 with LLVM
// Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
''',
),
input: Input(
entryPoints: [
packageRoot.resolve(
'../../third_party/libclang/include/clang-c/Index.h',
),
],
include: (uri) =>
uri.path.endsWith('CXString.h') || uri.path.endsWith('Index.h'),
compilerOptions: [
'-I$libclangInclude',
if (Platform.isMacOS)
'-I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/',
],
),
importType: importType,
visitors: [
Visitor(
func: (node) {
if (node.name.startsWith('clang_')) {
node.isIncluded = true;
node.exposeSymbolAddress = true;
node.generateTypedefs = true;
}
},
struct: (node) {
node.dependencies = CompoundDependencies.full;
if (node.name.startsWith('CX')) {
node.isIncluded = true;
}
},
enumClass: (node) {
if (node.name == 'CXTypeKind' || node.name == 'CXGlobalOptFlags') {
node.isIncluded = true;
}
},
typealias: (node) => node.isIncluded = .ifUsed,
macroConstant: (node) => node.isIncluded = true,
),
],
);
}
Future<void> main() async {
await getConfig().generate();
}