blob: 20c82eb4612582b4a50f3b90aa8874ae0574b53d [file] [log] [blame] [edit]
// Copyright (c) 2025, 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:ffi';
import 'package:logging/logging.dart';
import 'code_generator.dart' show Constant, ObjCBuiltInFunctions;
import 'config_provider/config.dart';
import 'config_provider/config_types.dart';
import 'config_provider/spec_utils.dart';
import 'header_parser/clang_bindings/clang_bindings.dart' show Clang;
import 'header_parser/utils.dart';
/// Wrapper around various ffigen-wide variables.
class Context {
final Logger logger;
final Config config;
final CursorIndex cursorIndex;
final BindingsIndex bindingsIndex = BindingsIndex();
final IncrementalNamer incrementalNamer = IncrementalNamer();
final Map<String, Macro> savedMacros = {};
final List<Constant> unnamedEnumConstants = [];
final ObjCBuiltInFunctions objCBuiltInFunctions;
bool hasSourceErrors = false;
Set<((String, int), (String, int))> reportedCommentRanges = {};
late final compilerOpts = config.compilerOpts ?? defaultCompilerOpts(logger);
Context(this.logger, FfiGenerator generator, {Uri? libclangDylib})
: config = Config(generator),
cursorIndex = CursorIndex(logger),
objCBuiltInFunctions = ObjCBuiltInFunctions(
Config(generator).wrapperName,
// ignore: deprecated_member_use_from_same_package
generator.objectiveC?.generateForPackageObjectiveC ?? false,
) {
final libclangDylibPath =
// ignore: deprecated_member_use_from_same_package
generator.libclangDylib?.toFilePath() ??
libclangDylib?.toFilePath() ??
findDylibAtDefaultLocations(logger);
_clang ??= Clang(DynamicLibrary.open(libclangDylibPath));
}
}
/// The clang bindings.
//
// Ideally this would be in the Context, but the plumbing needed would be
// excessive. The point of putting globals in the Context is to allow multiple
// concurrent FfiGen runs without any risk of clobbering global state. The
// clang bindings are loaded from a dylib specified by the config, so it's
// possible that two different versions of clang could be loaded. But since we
// interact with clang through a stable API, there's no real danger of version
// skew. So the safest thing is to simply load clang the first time a Context
// is created, and reuse it for all subsequent runs.
Clang get clang => _clang!;
Clang? _clang;