Stable release: Update dependencies to sound null safety, minor changes. (#168)
Co-authored-by: Daco Harkes <dacoharkes@google.com>
diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml
index 7de66eb..d5e1f2d 100644
--- a/.github/workflows/test-package.yml
+++ b/.github/workflows/test-package.yml
@@ -13,14 +13,13 @@
PUB_ENVIRONMENT: bot.github
jobs:
- # Check code formatting and static analysis on a single OS (linux)
- # against Dart dev.
+ # Check code formatting and static analysis on a single OS (linux).
analyze:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
- sdk: [2.12.0-237.0.dev] # TODO(127): Revert to stable.
+ sdk: [2.12.0-259.9.beta] # TODO(127): Revert to stable.
steps:
- uses: actions/checkout@v2
- uses: dart-lang/setup-dart@v1.0
@@ -33,7 +32,7 @@
run: dart format --output=none --set-exit-if-changed .
if: always() && steps.install.outcome == 'success'
- name: Analyze code
- run: dart analyze # --fatal-infos # Removed till we stop using legacy libraries.
+ run: dart analyze --fatal-infos
if: always() && steps.install.outcome == 'success'
test:
@@ -44,7 +43,7 @@
- uses: actions/checkout@v2
- uses: dart-lang/setup-dart@v1.0
with:
- sdk: 2.12.0-237.0.dev # TODO(127): Revert to stable.
+ sdk: 2.12.0-259.9.beta # TODO(127): Revert to stable.
- name: Install dependencies
run: dart pub get
- name: Install libclang-10-dev
@@ -52,7 +51,7 @@
- name: Build test dylib
run: cd test/native_test && dart build_test_dylib.dart && cd ../..
- name: Run VM tests
- run: dart --no-sound-null-safety test --platform vm
+ run: dart test --platform vm
- name: Collect coverage
run: ./tool/coverage.sh
- name: Upload coverage
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9a3cbb6..4ab98d4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+# 2.0.1
+- Switch to preview release of `package:quiver`.
+
+# 2.0.0
+- Upgraded all dependencies. `package:ffigen` now runs with sound null safety.
+
# 2.0.0-dev.6
- Functions marked `inline` are now skipped.
diff --git a/README.md b/README.md
index f2c194e..d531b4d 100644
--- a/README.md
+++ b/README.md
@@ -60,7 +60,7 @@
Configurations can be provided in 2 ways-
1. In the project's `pubspec.yaml` file under the key `ffigen`.
2. Via a custom YAML file, then specify this file while running -
-`pub run ffigen --config config.yaml`
+`dart run ffigen --config config.yaml`
The following configuration options are available-
<table>
@@ -391,15 +391,15 @@
1. Multi OS support for types such as long. [Issue #7](https://github.com/dart-lang/ffigen/issues/7)
## Trying out examples
-1. `cd examples/<example_u_want_to_run>`, Run `pub get`.
-2. Run `pub run ffigen`.
+1. `cd examples/<example_u_want_to_run>`, Run `dart pub get`.
+2. Run `dart run ffigen`.
## Running Tests
1. Dynamic library for some tests need to be built before running the examples.
1. `cd test/native_test`.
2. Run `dart build_test_dylib.dart`.
-Run tests from the root of the package with `pub run test`.
+Run tests from the root of the package with `dart run test`.
> Note: If llvm is not installed in one of the default locations, tests may fail.
## FAQ
### Can ffigen be used for removing underscores or renaming declarations?
@@ -449,7 +449,7 @@
### How does ffigen handle C Strings?
Ffigen treats `char*` just as any other pointer,(`Pointer<Int8>`).
-To convert these to/from `String`, you can use [package:ffi](https://pub.dev/packages/ffi) and use `Utf8.fromUtf8(ptr.cast())` to convert `char*` to dart `string`.
+To convert these to/from `String`, you can use [package:ffi](https://pub.dev/packages/ffi). Use `ptr.cast<Utf8>().toDartString()` to convert `char*` to dart `string` and `"str".toNativeUtf8()` to convert `string` to `char*`.
### How does ffigen handle C99 bool data type?
Although `dart:ffi` doesn't have a NativeType for `bool`, they can be implemented as `Uint8`.
diff --git a/bin/ffigen.dart b/bin/ffigen.dart
index cfb482c..6156ed0 100644
--- a/bin/ffigen.dart
+++ b/bin/ffigen.dart
@@ -2,7 +2,5 @@
// 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.
//
-// TODO(128): Remove this when package can run with sound null safety.
-// @dart=2.7
export 'package:ffigen/src/executables/ffigen.dart';
diff --git a/example/c_json/README.md b/example/c_json/README.md
index d689ce5..229d65b 100644
--- a/example/c_json/README.md
+++ b/example/c_json/README.md
@@ -15,7 +15,7 @@
## Generating bindings
At the root of this example (`example/c_json`), run -
```
-pub run ffigen
+dart run ffigen
```
This will generate bindings in a file: [cjson_generated_bindings.dart](./cjson_generated_bindings.dart)
diff --git a/example/c_json/main.dart b/example/c_json/main.dart
index fbd6f69..2774c31 100644
--- a/example/c_json/main.dart
+++ b/example/c_json/main.dart
@@ -18,7 +18,7 @@
final jsonString = File('./example.json').readAsStringSync();
// Parse this json string using our cJSON library.
- final cjsonParsedJson = cjson.cJSON_Parse(Utf8.toUtf8(jsonString).cast());
+ final cjsonParsedJson = cjson.cJSON_Parse(jsonString.toNativeUtf8().cast());
if (cjsonParsedJson == nullptr) {
print('Error parsing cjson.');
exit(1);
@@ -78,7 +78,7 @@
ptr = ptr.ref.next;
}
} else if (cjson.cJSON_IsString(parsedcjson.cast()) == 1) {
- obj = Utf8.fromUtf8(parsedcjson.ref.valuestring.cast());
+ obj = parsedcjson.ref.valuestring.cast<Utf8>().toDartString();
} else if (cjson.cJSON_IsNumber(parsedcjson.cast()) == 1) {
obj = parsedcjson.ref.valueint == parsedcjson.ref.valuedouble
? parsedcjson.ref.valueint
@@ -90,7 +90,7 @@
void _addToObj(dynamic obj, dynamic o, [Pointer<Utf8>? name]) {
if (obj is Map<String, dynamic>) {
- obj[Utf8.fromUtf8(name!)] = o;
+ obj[name!.toDartString()] = o;
} else if (obj is List<dynamic>) {
obj.add(o);
}
diff --git a/example/c_json/pubspec.yaml b/example/c_json/pubspec.yaml
index 76e4198..929dccf 100644
--- a/example/c_json/pubspec.yaml
+++ b/example/c_json/pubspec.yaml
@@ -5,10 +5,10 @@
name: c_json_example
environment:
- sdk: '>=2.12.0-237.0.dev <3.0.0'
+ sdk: '>=2.12.0-259.9.beta <3.0.0'
dependencies:
- ffi: ^0.2.0-nullsafety.1
+ ffi: ^1.0.0
dev_dependencies:
ffigen:
diff --git a/example/libclang-example/pubspec.yaml b/example/libclang-example/pubspec.yaml
index efce084..61373da 100644
--- a/example/libclang-example/pubspec.yaml
+++ b/example/libclang-example/pubspec.yaml
@@ -5,7 +5,7 @@
name: libclang_example
environment:
- sdk: '>=2.12.0-237.0.dev <3.0.0'
+ sdk: '>=2.12.0-259.9.beta <3.0.0'
dev_dependencies:
ffigen:
diff --git a/example/libclang-example/readme.md b/example/libclang-example/readme.md
index 0b8da39..dab0bdf 100644
--- a/example/libclang-example/readme.md
+++ b/example/libclang-example/readme.md
@@ -6,6 +6,6 @@
## Generating bindings
At the root of this example (`example/libclang-example`), run -
```
-pub run ffigen
+dart run ffigen
```
This will generate bindings in a file: [generated_bindings.dart](./generated_bindings.dart).
diff --git a/example/simple/README.md b/example/simple/README.md
index d286dab..026ae9f 100644
--- a/example/simple/README.md
+++ b/example/simple/README.md
@@ -5,6 +5,6 @@
## Generating bindings
At the root of this example (`example/simple`), run -
```
-pub run ffigen
+dart run ffigen
```
This will generate bindings in a file: [generated_bindings.dart](./generated_bindings.dart).
diff --git a/example/simple/pubspec.yaml b/example/simple/pubspec.yaml
index d3562ef..bd45857 100644
--- a/example/simple/pubspec.yaml
+++ b/example/simple/pubspec.yaml
@@ -5,7 +5,7 @@
name: simple_example
environment:
- sdk: '>=2.12.0-237.0.dev <3.0.0'
+ sdk: '>=2.12.0-259.9.beta <3.0.0'
dev_dependencies:
ffigen:
diff --git a/lib/src/README.md b/lib/src/README.md
index cdfc01a..7564006 100644
--- a/lib/src/README.md
+++ b/lib/src/README.md
@@ -17,7 +17,7 @@
The config file for generating bindings is `tool/libclang_config.yaml`. The bindings are generated to `lib/src/header_parser/clang_bindings/clang_bindings.dart`. These are used by [Header Parser](#header-parser) for calling libclang functions.
# Scripts
## ffigen.dart
-This is the main entry point for the user- `pub run ffigen`.
+This is the main entry point for the user- `dart run ffigen`.
- Command-line options:
- `--verbose`: Sets log level.
- `--config`: Specifies a config file.
diff --git a/lib/src/code_generator/library.dart b/lib/src/code_generator/library.dart
index 139ef4f..fd16446 100644
--- a/lib/src/code_generator/library.dart
+++ b/lib/src/code_generator/library.dart
@@ -7,7 +7,6 @@
import 'package:cli_util/cli_util.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as p;
-import 'package:pub_semver/pub_semver.dart';
import 'binding.dart';
import 'utils.dart';
import 'writer.dart';
@@ -97,17 +96,9 @@
/// Formats a file using `dartfmt`.
void _dartFmt(String path) {
final sdkPath = getSdkPath();
- final versionAtleast2dot10 = Version.parse(
- File(p.join(sdkPath, 'version')).readAsStringSync().trim()) >=
- Version(2, 10, 0);
-
- /// Starting from version `>=2.10.0` the dart sdk has a unified `dart` tool
- /// So we call `dart format` instead of `dartfmt`.
- final result = versionAtleast2dot10
- ? Process.runSync(p.join(sdkPath, 'bin', 'dart'), ['format', path],
- runInShell: Platform.isWindows)
- : Process.runSync(p.join(sdkPath, 'bin', 'dartfmt'), ['-w', path],
- runInShell: Platform.isWindows);
+ final result = Process.runSync(
+ p.join(sdkPath, 'bin', 'dart'), ['format', path],
+ runInShell: Platform.isWindows);
if (result.stderr.toString().isNotEmpty) {
_logger.severe(result.stderr);
throw FormatException('Unable to format generated file: $path.');
diff --git a/lib/src/config_provider/config.dart b/lib/src/config_provider/config.dart
index 6c11b34..34f9de5 100644
--- a/lib/src/config_provider/config.dart
+++ b/lib/src/config_provider/config.dart
@@ -92,12 +92,12 @@
late String _wrapperName;
/// Doc comment for the wrapper class.
- String get wrapperDocComment => _wrapperDocComment;
- late String _wrapperDocComment;
+ String? get wrapperDocComment => _wrapperDocComment;
+ String? _wrapperDocComment;
/// Header of the generated bindings.
- String get preamble => _preamble;
- late String _preamble;
+ String? get preamble => _preamble;
+ String? _preamble;
/// If `Dart_Handle` should be mapped with Handle/Object.
bool get useDartHandle => _useDartHandle;
@@ -314,13 +314,13 @@
extractor: stringExtractor,
defaultValue: () => null,
extractedResult: (dynamic result) =>
- _wrapperDocComment = result as String,
+ _wrapperDocComment = result as String?,
),
- strings.preamble: Specification<String>(
+ strings.preamble: Specification<String?>(
requirement: Requirement.no,
validator: nonEmptyStringValidator,
extractor: stringExtractor,
- extractedResult: (dynamic result) => _preamble = result as String,
+ extractedResult: (dynamic result) => _preamble = result as String?,
),
strings.useDartHandle: Specification<bool>(
requirement: Requirement.no,
diff --git a/lib/src/config_provider/spec_utils.dart b/lib/src/config_provider/spec_utils.dart
index 839333a..d377c95 100644
--- a/lib/src/config_provider/spec_utils.dart
+++ b/lib/src/config_provider/spec_utils.dart
@@ -5,6 +5,7 @@
import 'dart:io';
import 'package:ffigen/src/code_generator.dart';
+import 'package:file/local.dart';
import 'package:glob/glob.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as p;
@@ -122,7 +123,8 @@
_logger.fine('Adding header/file: $headerGlob');
} else {
final glob = Glob(headerGlob);
- for (final file in glob.listSync(followLinks: true)) {
+ for (final file in glob.listFileSystemSync(const LocalFileSystem(),
+ followLinks: true)) {
final fixedPath = _replaceSeparators(file.path);
entryPoints.add(fixedPath);
_logger.fine('Adding header/file: ${fixedPath}');
diff --git a/lib/src/header_parser/parser.dart b/lib/src/header_parser/parser.dart
index 2ce1cb9..3d4c5f0 100644
--- a/lib/src/header_parser/parser.dart
+++ b/lib/src/header_parser/parser.dart
@@ -78,7 +78,7 @@
final tu = clang.clang_parseTranslationUnit(
index,
- Utf8.toUtf8(headerLocation).cast(),
+ headerLocation.toNativeUtf8().cast(),
clangCmdArgs.cast(),
cmdLen,
nullptr,
diff --git a/lib/src/header_parser/sub_parsers/macro_parser.dart b/lib/src/header_parser/sub_parsers/macro_parser.dart
index 4f18ce6..7d93814 100644
--- a/lib/src/header_parser/sub_parsers/macro_parser.dart
+++ b/lib/src/header_parser/sub_parsers/macro_parser.dart
@@ -65,7 +65,7 @@
cmdLen = config.compilerOpts.length;
final tu = clang.clang_parseTranslationUnit(
index,
- Utf8.toUtf8(file.path).cast(),
+ file.path.toNativeUtf8().cast(),
clangCmdArgs.cast(),
cmdLen,
nullptr,
@@ -247,7 +247,7 @@
sb.clear();
// This throws a Format Exception if string isn't Utf8 so that we handle it
// in the catch block.
- final result = Utf8.fromUtf8(strPtr.cast());
+ final result = strPtr.cast<Utf8>().toDartString();
for (final s in result.runes) {
sb.write(_getWritableChar(s));
}
@@ -257,7 +257,7 @@
_logger.warning(
"Couldn't decode Macro string '$macroName' as Utf8, using ASCII instead.");
sb.clear();
- final length = Utf8.strlen(strPtr.cast());
+ final length = strPtr.cast<Utf8>().length;
final charList = Uint8List.view(
strPtr.cast<Uint8>().asTypedList(length).buffer, 0, length);
diff --git a/lib/src/header_parser/utils.dart b/lib/src/header_parser/utils.dart
index 28ca657..915d4b7 100644
--- a/lib/src/header_parser/utils.dart
+++ b/lib/src/header_parser/utils.dart
@@ -52,7 +52,7 @@
extension CXSourceRangeExt on Pointer<clang_types.CXSourceRange> {
void dispose() {
- free(this);
+ calloc.free(this);
}
}
@@ -100,19 +100,19 @@
String sourceFileName() {
final cxsource = clang.clang_getCursorLocation(this);
- final cxfilePtr = allocate<Pointer<Void>>();
- final line = allocate<Uint32>();
- final column = allocate<Uint32>();
- final offset = allocate<Uint32>();
+ final cxfilePtr = calloc<Pointer<Void>>();
+ final line = calloc<Uint32>();
+ final column = calloc<Uint32>();
+ final offset = calloc<Uint32>();
// Puts the values in these pointers.
clang.clang_getFileLocation(cxsource, cxfilePtr, line, column, offset);
final s = clang.clang_getFileName(cxfilePtr.value).toStringAndDispose();
- free(cxfilePtr);
- free(line);
- free(column);
- free(offset);
+ calloc.free(cxfilePtr);
+ calloc.free(line);
+ calloc.free(column);
+ calloc.free(offset);
return s;
}
}
@@ -241,7 +241,7 @@
String string() {
final cstring = clang.clang_getCString(this);
if (cstring != nullptr) {
- return Utf8.fromUtf8(cstring.cast());
+ return cstring.cast<Utf8>().toDartString();
} else {
return '';
}
@@ -262,10 +262,10 @@
/// Converts a [List<String>] to [Pointer<Pointer<Utf8>>].
Pointer<Pointer<Utf8>> createDynamicStringArray(List<String> list) {
- final nativeCmdArgs = allocate<Pointer<Utf8>>(count: list.length);
+ final nativeCmdArgs = calloc<Pointer<Utf8>>(list.length);
for (var i = 0; i < list.length; i++) {
- nativeCmdArgs[i] = Utf8.toUtf8(list[i]);
+ nativeCmdArgs[i] = list[i].toNativeUtf8();
}
return nativeCmdArgs;
@@ -275,9 +275,9 @@
// Properly disposes a Pointer<Pointer<Utf8>, ensure that sure length is correct.
void dispose(int length) {
for (var i = 0; i < length; i++) {
- free(this[i]);
+ calloc.free(this[i]);
}
- free(this);
+ calloc.free(this);
}
}
diff --git a/pubspec.yaml b/pubspec.yaml
index e8501c0..ccb3e8b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,24 +3,24 @@
# BSD-style license that can be found in the LICENSE file.
name: ffigen
-version: 2.0.0-dev.6
+version: 2.0.1
homepage: https://github.com/dart-lang/ffigen
-description: Experimental generator for FFI bindings, using LibClang to parse C header files.
+description: Generator for FFI bindings, using LibClang to parse C header files.
environment:
- sdk: '>=2.12.0-237.0.dev <3.0.0'
+ sdk: '>=2.12.0-259.9.beta <3.0.0'
dependencies:
- ffi: ^0.2.0-nullsafety.1
- yaml: ^3.0.0-nullsafety.0
- path: ^1.8.0-nullsafety.3
- quiver: ^3.0.0-nullsafety.2
- args: ^1.6.0 # Not available
- logging: ^0.11.4 # test->coverage->logging
- cli_util: ^0.2.0 # test->analyzer->cli_util
- glob: ^1.0.3 # test->analyzer->glob
- pub_semver: ^1.4.4 # test->analyzer->pub_semver
+ ffi: ^1.0.0
+ yaml: ^3.0.0
+ path: ^1.8.0
+ quiver: ^3.0.0
+ args: ^2.0.0
+ logging: ^1.0.0
+ cli_util: ^0.3.0
+ glob: ^2.0.0
+ file: ^6.0.0
dev_dependencies:
- pedantic: ^1.10.0-nullsafety.3
- test: ^1.16.0-nullsafety.13
+ pedantic: ^1.10.0
+ test: ^1.16.2
diff --git a/test/native_test/config.yaml b/test/native_test/config.yaml
index 2b2ded2..3933518 100644
--- a/test/native_test/config.yaml
+++ b/test/native_test/config.yaml
@@ -3,7 +3,7 @@
# BSD-style license that can be found in the LICENSE file.
# =================== GENERATING TEST BINDINGS ==================
-# pub run ffigen --config test/native_test/config.yaml
+# dart run ffigen --config test/native_test/config.yaml
# ===============================================================
name: NativeLibrary
diff --git a/tool/coverage.sh b/tool/coverage.sh
index d43016d..7cecbfe 100755
--- a/tool/coverage.sh
+++ b/tool/coverage.sh
@@ -8,12 +8,12 @@
set -e
# Gather coverage.
-pub global activate remove_from_coverage
-pub global activate coverage
+dart pub global activate remove_from_coverage
+dart pub global activate coverage
# Generate coverage report.
-dart --no-sound-null-safety --pause-isolates-on-exit --disable-service-auth-codes --enable-vm-service=3000 test/test_coverage.dart &
+dart --pause-isolates-on-exit --disable-service-auth-codes --enable-vm-service=3000 test/test_coverage.dart &
dart pub global run coverage:collect_coverage --wait-paused --uri=http://127.0.0.1:3000/ -o coverage.json --resume-isolates
dart pub global run coverage:format_coverage --lcov -i coverage.json -o lcov.info
# Remove extra files from coverage report.
-pub global run remove_from_coverage -f lcov.info -r ".pub-cache"
+dart pub global run remove_from_coverage -f lcov.info -r ".pub-cache"
diff --git a/tool/libclang_config.yaml b/tool/libclang_config.yaml
index c27f17c..178aa97 100644
--- a/tool/libclang_config.yaml
+++ b/tool/libclang_config.yaml
@@ -6,7 +6,7 @@
# ===================== GENERATING BINDINGS =====================
# cd to project's root, and run -
-# pub run ffigen --config tool/libclang_config.yaml
+# dart run ffigen --config tool/libclang_config.yaml
# ===============================================================
name: Clang