| // 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(); | |
| } |