[ffigen] Added key `llvm-path`. Deprecate `llvm-lib`. (#194)
diff --git a/pkgs/ffigen/CHANGELOG.md b/pkgs/ffigen/CHANGELOG.md index 40ae92a..1f2afa4 100644 --- a/pkgs/ffigen/CHANGELOG.md +++ b/pkgs/ffigen/CHANGELOG.md
@@ -1,3 +1,7 @@ +# 2.4.0 +- Added new config key `llvm-path` that accepts a list of `path/to/llvm`. +- Deprecated config key `llvm-lib`. + # 2.3.0 - Added config key `compiler-opts-automatic -> macos -> include-c-standard-library` (default: true) to automatically find and add C standard library on macOS.
diff --git a/pkgs/ffigen/README.md b/pkgs/ffigen/README.md index e3faf97..19cbf56 100644 --- a/pkgs/ffigen/README.md +++ b/pkgs/ffigen/README.md
@@ -87,12 +87,15 @@ </td> </tr> <tr> - <td>llvm-lib</td> - <td>Path to <i>llvm/lib</i> folder. Required if ffigen is unable to find this at default locations.</td> + <td>llvm-path</td> + <td>Path to <i>llvm</i> folder. ffigen will sequentially search all the specified paths. Required if ffigen is unable to find this at default locations.</td> <td> ```yaml -llvm-lib: '/usr/local/opt/llvm/lib' +llvm-path: + - '/usr/local/opt/llvm/lib' + - 'C:\Program Files\llvm` + - '/usr/lib/llvm-11' ``` </td> </tr>
diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index 673daea..2830366 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart
@@ -181,12 +181,25 @@ /// Key: Name, Value: [Specification] Map<List<String>, Specification> _getSpecs() { return <List<String>, Specification>{ + //TODO: Deprecated, remove in next major update. [strings.llvmLib]: Specification<String>( requirement: Requirement.no, validator: llvmLibValidator, extractor: llvmLibExtractor, + defaultValue: () => '', + extractedResult: (dynamic result) { + _libclangDylib = result as String; + }, + ), + [strings.llvmPath]: Specification<String>( + requirement: Requirement.no, + validator: llvmPathValidator, + extractor: llvmPathExtractor, defaultValue: () => findDylibAtDefaultLocations(), - extractedResult: (dynamic result) => _libclangDylib = result as String, + extractedResult: (dynamic result) { + // If this key wasn't already set by `llvm-lib` use this result. + if (_libclangDylib.isEmpty) _libclangDylib = result as String; + }, ), [strings.output]: Specification<String>( requirement: Requirement.yes,
diff --git a/pkgs/ffigen/lib/src/config_provider/spec_utils.dart b/pkgs/ffigen/lib/src/config_provider/spec_utils.dart index ce6aae5..68246b4 100644 --- a/pkgs/ffigen/lib/src/config_provider/spec_utils.dart +++ b/pkgs/ffigen/lib/src/config_provider/spec_utils.dart
@@ -302,7 +302,7 @@ } /// Returns location of dynamic library by searching default locations. Logs -/// error and exits if not found. +/// error and throws an Exception if not found. String findDylibAtDefaultLocations() { String? k; if (Platform.isLinux) { @@ -326,7 +326,7 @@ _logger.severe("Couldn't find dynamic library in default locations."); _logger.severe( - "Please supply the path/to/llvm/lib in ffigen's config under the key 'llvm-lib'."); + "Please supply one or more path/to/llvm in ffigen's config under the key '${strings.llvmPath}'."); throw Exception("Couldn't find dynamic library in default locations."); } @@ -351,6 +351,8 @@ } bool llvmLibValidator(List<String> name, dynamic value) { + _logger.warning( + 'Deprecated ${strings.llvmLib}: please use ${strings.llvmPath} instead.'); if (!checkType<String>(name, value) || !Directory(value as String).existsSync()) { _logger.severe('Expected $name to be a valid folder Path.'); @@ -359,6 +361,37 @@ return true; } +String llvmPathExtractor(dynamic value) { + // Extract libclang's dylib from user specified paths. + for (final path in (value as YamlList)) { + if (path is! String) continue; + final dylibPath = + findLibclangDylib(p.join(path, strings.dynamicLibParentName)); + if (dylibPath != null) { + _logger.fine('Found dynamic library at: $dylibPath'); + return dylibPath; + } + } + _logger.fine( + "Couldn't find dynamic library under paths specified by ${strings.llvmPath}."); + // Extract path from default locations. + try { + final res = findDylibAtDefaultLocations(); + return res; + } catch (e) { + _logger.severe( + "Couldn't find libclang dynamic library in specified locations."); + exit(1); + } +} + +bool llvmPathValidator(List<String> name, dynamic value) { + if (!checkType<YamlList>(name, value)) { + return false; + } + return true; +} + String outputExtractor(dynamic value) => _replaceSeparators(value as String); bool outputValidator(List<String> name, dynamic value) =>
diff --git a/pkgs/ffigen/lib/src/strings.dart b/pkgs/ffigen/lib/src/strings.dart index a4f1d68..dcbae34 100644 --- a/pkgs/ffigen/lib/src/strings.dart +++ b/pkgs/ffigen/lib/src/strings.dart
@@ -23,6 +23,10 @@ } const llvmLib = 'llvm-lib'; +const llvmPath = 'llvm-path'; + +/// Name of the parent folder of dynamic library `lib` or `bin` (on windows). +String get dynamicLibParentName => Platform.isWindows ? 'bin' : 'lib'; const output = 'output';
diff --git a/pkgs/ffigen/pubspec.yaml b/pkgs/ffigen/pubspec.yaml index 4104cd3..bc514bf 100644 --- a/pkgs/ffigen/pubspec.yaml +++ b/pkgs/ffigen/pubspec.yaml
@@ -3,7 +3,7 @@ # BSD-style license that can be found in the LICENSE file. name: ffigen -version: 2.3.0 +version: 2.4.0 homepage: https://github.com/dart-lang/ffigen description: Generator for FFI bindings, using LibClang to parse C header files.