Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions .github/workflows/io_file.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,6 @@ jobs:
- run: dart analyze --fatal-infos
- run: dart format --output=none --set-exit-if-changed .

check-generation:
# Verify that the generated code is up-to-date. Every platform/arch should
# generate the same API bindings.
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c
with:
sdk: dev
- run: dart pub get
- run: dart --enable-experiment=native-assets run tool/generate.dart
- run: git diff --exit-code

desktop-vm-test:
strategy:
fail-fast: false
Expand Down
65 changes: 65 additions & 0 deletions .github/workflows/unix_api.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: package:unix_api

permissions: read-all

on:
# Run CI on pushes to the main branch, and on PRs against main.
push:
branches: [ main ]
paths:
- '.github/workflows/unix_api.yml'
- 'pkgs/unix_api/**'
pull_request:
branches: [ main ]
paths:
- '.github/workflows/unix_api.yml'
- 'pkgs/unix_api/**'
schedule:
- cron: '0 0 * * 0' # weekly

defaults:
run:
working-directory: pkgs/unix_api

jobs:
analyze_and_format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c
with:
sdk: dev
- run: dart pub get
- run: dart analyze --fatal-infos
- run: dart format --output=none --set-exit-if-changed .

check-generation:
# Verify that the generated code is up-to-date. Every platform/arch should
# generate the same API bindings.
strategy:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest, ubuntu-24.04-arm]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c
with:
sdk: dev
- run: dart pub get
- run: dart --enable-experiment=native-assets run tool/generate.dart
- run: git diff --exit-code

desktop-vm-test:
strategy:
fail-fast: false
matrix:
sdk: [dev]
os: [macos-latest, ubuntu-latest, ubuntu-24.04-arm]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c
with:
sdk: ${{ matrix.sdk }}
- run: dart --enable-experiment=native-assets test --reporter=failures-only --test-randomize-ordering-seed=random --platform vm
7 changes: 0 additions & 7 deletions pkgs/io_file/lib/src/libc.dart

This file was deleted.

2 changes: 1 addition & 1 deletion pkgs/io_file/lib/src/vm_posix_file_system.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import 'dart:typed_data';

import 'package:ffi/ffi.dart' as ffi;
import 'package:path/path.dart' as p;
import 'package:unix_api/unix_api.dart' as libc;

import 'exceptions.dart';
import 'file_system.dart';
import 'internal_constants.dart';
import 'libc.dart' as libc;

/// The default `mode` to use with `open` calls that may create a file.
const _defaultMode = 438; // => 0666 => rw-rw-rw-
Expand Down
1 change: 1 addition & 0 deletions pkgs/io_file/mobile_test/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ dev_dependencies:
url: https://github.com/canonical/stdlibc.dart.git
test: ^1.24.0
uuid: ^4.5.1

4 changes: 3 additions & 1 deletion pkgs/io_file/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ dependencies:
code_assets: ^0.19.0
ffi: ^2.1.4
hooks: ^0.19.0
logging: ^1.3.0
meta: ^1.16.0
native_toolchain_c: ^0.16.0
path: ^1.9.1
unix_api:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd try using something like ^0.1.0 here, and add a dependency_overrides section further down:

dependency_overrides:
  unix_api:
    path: ../unix_api

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed to back because changing this also trickles into the mobile_test subproject and it seemed better to contain the path reference here. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it's not normally how we'd try and reference a package - it'll mean that io_file won't be useable outside this repo. I'm not sure what the issue is w/ the subproject.

Feel free to use your best judgement here though; we're not trying to ship this currently. If you do use a relative reference into this repo, you might leave a comment that this isn't our normal practice.

# Change this to a released version when this package is published.
path: ../unix_api
win32: ^5.14.0

dev_dependencies:
Expand Down
2 changes: 1 addition & 1 deletion pkgs/io_file/test/copy_file_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import 'package:ffi/ffi.dart';
import 'package:io_file/io_file.dart';
import 'package:io_file/posix_file_system.dart';
import 'package:io_file/src/internal_constants.dart' show blockSize;
import 'package:io_file/src/libc.dart' as libc;
import 'package:io_file/src/vm_windows_file_system.dart';
import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import 'package:unix_api/unix_api.dart' as libc;
import 'package:win32/win32.dart' as win32;

import 'errors.dart' as errors;
Expand Down
3 changes: 2 additions & 1 deletion pkgs/io_file/test/remove_directory_tree_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import 'dart:io' as io;

import 'package:ffi/ffi.dart';
import 'package:io_file/io_file.dart';
import 'package:io_file/src/libc.dart' as libc;
import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import 'package:unix_api/unix_api.dart' as libc;
import 'package:win32/win32.dart' as win32;

import 'errors.dart' as errors;
import 'test_utils.dart';

Expand Down
File renamed without changes.
7 changes: 7 additions & 0 deletions pkgs/unix_api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# https://dart.dev/guides/libraries/private-files
# Created by `dart pub`
.dart_tool/

# Avoid committing pubspec.lock for library packages; see
# https://dart.dev/guides/libraries/private-files#pubspeclock.
pubspec.lock
3 changes: 3 additions & 0 deletions pkgs/unix_api/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 0.1.0-wip

- Initial version.
77 changes: 77 additions & 0 deletions pkgs/unix_api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
This package provides **experimental** bindings to POSIX APIs e.g. `open`,
`close`.

## Why have another POSIX API implementation for Dart?

Thare are two existing packages that provide POSIX API bindings for Dart:
1. [`package:posix`](https://pub.dev/packages/posix)
2. [`package:stdlibc`](https://pub.dev/packages/stdlibc)

`package:unix_api` requires a native tool chain and has a small amount of
native code that cannot be tree shaken away. In exchange, it works on all
POSIX platforms that Dart supports.

| Package | Required Tools | Supported Platforms | Fixed Disk Usage |
| :--- | :-------------- | :------------------------------------ | :-------------- |
| `posix` | Dart | iOS (arm64), Linux (x64), macOS (arm64) | 0 KiB |
| `stdlibc` | Dart | iOS (arm64), Linux (x64), macOS (arm64) | 0 KiB |
| `unix_api` | Dart, C compiler | Android (x64, arm32, arm64), iOS (arm64), Linux (x64, arm64), macOS (x64, arm64) | ~60 KiB |

## Design

The POSIX API is a defined in terms of source, not object compatibility.

For example, glibc defines `stat` as:

`#define stat(fname, buf) __xstat (_STAT_VER, fname, buf)`

So running `ffigen` on `sys/stat.h` will not produce an entry for `stat`.

libc may also reorder `struct` fields across architectures, add extra
fields, etc. For example, the glibc definition of `struct stat` starts
with:

```c
struct stat
{
__dev_t st_dev; /* Device. */
#ifndef __x86_64__
unsigned short int __pad1;
#endif
#if defined __x86_64__ || !defined __USE_FILE_OFFSET64
__ino_t st_ino; /* File serial number. */
#else
```


`package:unix_api` works around this problem by defining a native (C) function
for every POSIX function. The native function just calls the corresponding
POSIX function. For example:

```c
int libc_shim_rename(const char *old, const char *newy) {
return rename(old, newy);
}
```

This allows the platforms C compiler to deal with macro expansions,
platform-specific struct layout, etc.

Then `package:unix_api` uses `package:ffigen` to provide Dart bindings to
these functions.


## Status: Experimental

**NOTE**: This package is currently experimental and published under the
[labs.dart.dev](https://dart.dev/dart-team-packages) pub publisher in order to
solicit feedback.

For packages in the labs.dart.dev publisher we generally plan to either graduate
the package into a supported publisher (dart.dev, tools.dart.dev) after a period
of feedback and iteration, or discontinue the package. These packages have a
much higher expected rate of API and breaking changes.

Your feedback is valuable and will help us evolve this package. For general
feedback, suggestions, and comments, please file an issue in the
[bug tracker](https://github.com/dart-lang/labs/issues).
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ comments:
style: any
length: full
ffi-native:
asset-id: package:io_file/libc_shim
asset-id: package:unix_api/libc_shim
structs:
rename:
'libc_shim_(.*)': '$1'
Expand Down
File renamed without changes.
9 changes: 9 additions & 0 deletions pkgs/unix_api/example/unix_api_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// 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 'package:unix_api/unix_api.dart';

void main() {
print('I am ${getpid()} and my parent is ${getppid()}');
}
2 changes: 1 addition & 1 deletion pkgs/io_file/ffigen.yaml → pkgs/unix_api/ffigen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ comments:
style: any
length: full
ffi-native:
asset-id: package:io_file/libc_shim
asset-id: package:unix_api/libc_shim
structs:
rename:
'libc_shim_(.*)': '$1'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ void main(List<String> args) async {
).run(
input: input,
output: output,
logger:
Logger('')
..level = Level.ALL
..onRecord.listen((record) => print(record.message)),
logger: Logger('')
..level = Level.ALL
..onRecord.listen((record) => print(record.message)),
);
});
}
Loading
Loading