Skip to content

Commit 438aca4

Browse files
authored
fix(cedar_ffi): Windows bundling workarounds (#104)
Workaround for: dart-lang/sdk#55207
1 parent 3c97655 commit 438aca4

12 files changed

+359
-136
lines changed

packages/cedar_ffi/build.dart

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,19 @@ final IOSink buildLogs = () {
1010
Platform.script.resolve('.dart_tool/build.log'),
1111
);
1212
logsFile.createSync(recursive: true);
13-
return logsFile.openWrite(mode: FileMode.write);
13+
return logsFile.openWrite(mode: FileMode.write)
14+
..writeln('Starting build: ${DateTime.now()}');
1415
}();
1516

1617
void main(List<String> args) async {
1718
try {
1819
await build(args, (config, output) async {
1920
buildLogs.writeln(config.toString());
2021

21-
output.addDependency(config.packageRoot.resolve('src/'));
22+
output.addDependencies([
23+
config.packageRoot.resolve('build.dart'),
24+
config.packageRoot.resolve('src/'),
25+
]);
2226

2327
// Build the Rust code in `src/` to `target/`.
2428
//
@@ -39,9 +43,27 @@ void main(List<String> args) async {
3943
if (!File.fromUri(binaryOut).existsSync()) {
4044
throw Exception('$binaryOut does not exist');
4145
}
46+
if (config.targetOS == OS.windows) {
47+
// Workaround for https://github.com/dart-lang/sdk/issues/55207
48+
//
49+
// Bundle a second asset which can resolve symbols from a previously
50+
// loaded DLL. This allows having a fallback mechanism, since you
51+
// cannot add duplicate assets.
52+
//
53+
// This only matters in release mode, but since `config.buildMode` is
54+
// always set to `release` in Dart, it's no good.
55+
final loadedAsset = NativeCodeAsset(
56+
package: packageName,
57+
name: 'src/ffi/cedar_bindings.loaded.ffi.dart',
58+
linkMode: LookupInProcess(),
59+
os: config.targetOS,
60+
architecture: config.targetArchitecture,
61+
);
62+
output.addAsset(loadedAsset);
63+
}
4264
final nativeAsset = NativeCodeAsset(
4365
package: packageName,
44-
name: 'src/ffi/cedar_bindings.g.dart',
66+
name: 'src/ffi/cedar_bindings.bundled.ffi.dart',
4567
linkMode: DynamicLoadingBundled(),
4668
os: config.targetOS,
4769
architecture: config.targetArchitecture,
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: CedarFfiBundled
2+
description: C bindings to the Cedar policy engine (bundled native asset)
3+
ffi-native:
4+
language: c
5+
headers:
6+
entry-points:
7+
- "src/include/bindings.h"
8+
compiler-opts:
9+
# Suppress nullability warnings on macOS
10+
- "-Wno-nullability-completeness"
11+
# Ignore warnings about availability macro
12+
- "-Wno-availability"
13+
output:
14+
bindings: "lib/src/ffi/cedar_bindings.bundled.ffi.dart"
15+
comments:
16+
style: any
17+
length: full
18+
exclude-all-by-default: true
19+
import:
20+
symbol-files:
21+
- 'package:cedar_ffi/src/ffi/symbols.yaml'
22+
functions:
23+
include:
24+
- "cedar_.*"
25+
leaf:
26+
# All C APIs are leaf functions (e.g. they do not call into Dart)
27+
include:
28+
- ".*"

packages/cedar_ffi/ffigen.loaded.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: CedarFfiLoaded
2+
description: C bindings to the Cedar policy engine (process native asset)
3+
ffi-native:
4+
language: c
5+
headers:
6+
entry-points:
7+
- "src/include/bindings.h"
8+
compiler-opts:
9+
# Suppress nullability warnings on macOS
10+
- "-Wno-nullability-completeness"
11+
# Ignore warnings about availability macro
12+
- "-Wno-availability"
13+
output:
14+
bindings: "lib/src/ffi/cedar_bindings.loaded.ffi.dart"
15+
comments:
16+
style: any
17+
length: full
18+
exclude-all-by-default: true
19+
import:
20+
symbol-files:
21+
- 'package:cedar_ffi/src/ffi/symbols.yaml'
22+
functions:
23+
include:
24+
- "cedar_.*"
25+
expose-typedefs:
26+
include:
27+
- "cedar_.*"
28+
leaf:
29+
# All C APIs are leaf functions (e.g. they do not call into Dart)
30+
include:
31+
- ".*"
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: CedarFfiSymbols
2+
description: C bindings to the Cedar policy engine (symbols-only)
3+
ffi-native:
4+
language: c
5+
headers:
6+
entry-points:
7+
- "src/include/bindings.h"
8+
compiler-opts:
9+
# Suppress nullability warnings on macOS
10+
- "-Wno-nullability-completeness"
11+
# Ignore warnings about availability macro
12+
- "-Wno-availability"
13+
output:
14+
bindings: "lib/src/ffi/cedar_bindings.symbols.ffi.dart"
15+
symbol-file:
16+
output: 'package:cedar_ffi/src/ffi/symbols.yaml'
17+
import-path: 'package:cedar_ffi/src/ffi/cedar_bindings.symbols.ffi.dart'
18+
comments:
19+
style: any
20+
length: full
21+
exclude-all-by-default: true
22+
structs:
23+
include:
24+
- "CCedar.*"
25+
- "CedarStore"
26+
- "CInitResult"
27+
- "CAuthorizationDecision"

packages/cedar_ffi/lib/src/cedar_policy_set_ffi.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import 'dart:convert';
22
import 'dart:ffi';
33

44
import 'package:cedar/cedar.dart';
5-
import 'package:cedar_ffi/src/ffi/cedar_bindings.g.dart' as bindings;
5+
import 'package:cedar_ffi/src/ffi/cedar_bindings.dart';
66
import 'package:ffi/ffi.dart';
77

88
/// An FFI extension of [CedarPolicySet].
@@ -21,7 +21,7 @@ Map<String, Map<String, Object?>> parsePolicies(String policiesIdl) {
2121
policiesIdl.toNativeUtf8(allocator: arena).cast(),
2222
);
2323
switch (cPolicies) {
24-
case bindings.CCedarPolicySetResult(:final errors, :final errors_len)
24+
case CCedarPolicySetResult(:final errors, :final errors_len)
2525
when errors_len > 0:
2626
final errorStrings = <String>[];
2727
for (var i = 0; i < errors_len; i++) {
@@ -32,7 +32,7 @@ Map<String, Map<String, Object?>> parsePolicies(String policiesIdl) {
3232
'${errorStrings.join(', ')}',
3333
policiesIdl,
3434
);
35-
case bindings.CCedarPolicySetResult(
35+
case CCedarPolicySetResult(
3636
:final policies,
3737
:final policy_ids,
3838
:final policies_len,

packages/cedar_ffi/lib/src/engine/cedar_engine.dart

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import 'dart:convert';
22
import 'dart:ffi';
33

44
import 'package:cedar/cedar.dart';
5-
import 'package:cedar_ffi/src/ffi/cedar_bindings.g.dart' as bindings;
5+
import 'package:cedar_ffi/src/ffi/cedar_bindings.dart';
66
import 'package:ffi/ffi.dart';
77
import 'package:meta/meta.dart';
88

@@ -24,7 +24,7 @@ final class CedarEngine implements CedarAuthorizer, Finalizable {
2424
@visibleForTesting bool validate = true,
2525
}) {
2626
final storeRef = using((arena) {
27-
final config = arena<bindings.CCedarConfig>();
27+
final config = arena<CCedarConfig>();
2828
config.ref
2929
..schema_json =
3030
jsonEncode(schema.toJson()).toNativeUtf8(allocator: arena).cast()
@@ -61,16 +61,16 @@ final class CedarEngine implements CedarAuthorizer, Finalizable {
6161
}
6262

6363
CedarEngine._({
64-
required Pointer<bindings.CedarStore> ref,
64+
required Pointer<CedarStore> ref,
6565
}) : _ref = ref;
6666

67-
static final Finalizer<Pointer<bindings.CedarStore>> _finalizer = Finalizer(
67+
static final Finalizer<Pointer<CedarStore>> _finalizer = Finalizer(
6868
bindings.cedar_deinit,
6969
);
7070

7171
var _closed = false;
7272

73-
final Pointer<bindings.CedarStore> _ref;
73+
final Pointer<CedarStore> _ref;
7474

7575
@override
7676
CedarAuthorizationResponse isAuthorized(
@@ -82,7 +82,7 @@ final class CedarEngine implements CedarAuthorizer, Finalizable {
8282
throw StateError('Cedar engine is closed');
8383
}
8484
return using((arena) {
85-
final query = arena<bindings.CCedarQuery>();
85+
final query = arena<CCedarQuery>();
8686
query.ref
8787
..principal_str = switch (request.principal) {
8888
final principal? => principal.normalized
@@ -122,13 +122,13 @@ final class CedarEngine implements CedarAuthorizer, Finalizable {
122122
};
123123
final cDecision = bindings.cedar_is_authorized(_ref, query);
124124
return switch (cDecision) {
125-
bindings.CAuthorizationDecision(:final completion_error)
125+
CAuthorizationDecision(:final completion_error)
126126
when completion_error != nullptr =>
127127
throw Exception(
128128
'Error performing authorization: '
129129
'${completion_error.cast<Utf8>().toDartString()}',
130130
),
131-
bindings.CAuthorizationDecision(
131+
CAuthorizationDecision(
132132
:final is_authorized,
133133
:final reasons,
134134
:final reasons_len,

packages/cedar_ffi/lib/src/ffi/cedar_bindings.bundled.ffi.dart

Lines changed: 55 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// ignore_for_file: non_constant_identifier_names
2+
3+
import 'dart:ffi';
4+
5+
import 'package:cedar_ffi/src/ffi/cedar_bindings.bundled.ffi.dart' as bundled;
6+
import 'package:cedar_ffi/src/ffi/cedar_bindings.loaded.ffi.dart' as loaded;
7+
8+
export 'package:cedar_ffi/src/ffi/cedar_bindings.symbols.ffi.dart';
9+
10+
final bindings = CedarBindings._();
11+
12+
enum _LinkMode { bundled, loaded }
13+
14+
final class CedarBindings {
15+
CedarBindings._() {
16+
try {
17+
Native.addressOf<NativeFunction<loaded.NativeCedar_init>>(
18+
loaded.cedar_init);
19+
_linkMode = _LinkMode.loaded;
20+
} on Object {
21+
Native.addressOf<NativeFunction<loaded.NativeCedar_init>>(
22+
bundled.cedar_init);
23+
_linkMode = _LinkMode.bundled;
24+
}
25+
}
26+
27+
late final _LinkMode _linkMode;
28+
29+
late final cedar_init =
30+
_linkMode == _LinkMode.loaded ? loaded.cedar_init : bundled.cedar_init;
31+
32+
late final cedar_deinit = _linkMode == _LinkMode.loaded
33+
? loaded.cedar_deinit
34+
: bundled.cedar_deinit;
35+
36+
late final cedar_is_authorized = _linkMode == _LinkMode.loaded
37+
? loaded.cedar_is_authorized
38+
: bundled.cedar_is_authorized;
39+
40+
late final cedar_link_policy_template = _linkMode == _LinkMode.loaded
41+
? loaded.cedar_link_policy_template
42+
: bundled.cedar_link_policy_template;
43+
44+
late final cedar_parse_policy_set = _linkMode == _LinkMode.loaded
45+
? loaded.cedar_parse_policy_set
46+
: bundled.cedar_parse_policy_set;
47+
}

0 commit comments

Comments
 (0)