Skip to content

Commit 43214dd

Browse files
authored
Upgrade to new native_assets (#964)
* Upgrade * Works now * Use default build mode * Upgrade * fix options * Format * Add changelog * Clean up * More fixes * Small fixes
1 parent e44af54 commit 43214dd

File tree

14 files changed

+344
-268
lines changed

14 files changed

+344
-268
lines changed

pkgs/intl4x/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.11.4
2+
3+
- Remove `native_assets_*` dependencies for `hooks` and `code_assets`.
4+
15
## 0.11.3
26

37
- Use new artifacts from `intl4x-icu-v.0.11.2-artifacts` release.

pkgs/intl4x/analysis_options.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ analyzer:
1212
exclude:
1313
- "submodules/*"
1414
- "lib/src/bindings/*"
15+
- lib/src/hook_helpers/build_libs.g.dart
16+
- tool/build_libs.g.dart
1517

1618
enable-experiment:
1719
- native-assets

pkgs/intl4x/example_native/pubspec.yaml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ dependencies:
1111
path: ../
1212

1313
dev_dependencies:
14-
lints: ^5.0.0
14+
lints: ^6.0.0
1515

16-
hook:
17-
intl4x:
18-
buildMode: fetch
19-
treeshake: true
16+
hooks:
17+
user_defines:
18+
intl4x:
19+
buildMode: checkout
20+
checkoutPath: ../../../submodules/icu4x/

pkgs/intl4x/hook/build.dart

Lines changed: 63 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -4,51 +4,53 @@
44

55
import 'dart:io';
66

7+
import 'package:code_assets/code_assets.dart';
78
import 'package:crypto/crypto.dart' show sha256;
8-
import 'package:intl4x/src/hook_helpers/build_options.dart';
9-
import 'package:intl4x/src/hook_helpers/hashes.dart';
10-
import 'package:intl4x/src/hook_helpers/shared.dart'
11-
show assetId, package, runProcess;
12-
import 'package:intl4x/src/hook_helpers/version.dart';
13-
import 'package:native_assets_cli/code_assets.dart';
14-
import 'package:path/path.dart' as path;
15-
16-
const crateName = 'icu_capi';
9+
import 'package:hooks/hooks.dart';
10+
import 'package:intl4x/src/hook_helpers/build_libs.g.dart' show buildLib;
11+
import 'package:intl4x/src/hook_helpers/build_options.dart'
12+
show BuildModeEnum, BuildOptions;
13+
import 'package:intl4x/src/hook_helpers/hashes.dart' show fileHashes;
14+
import 'package:intl4x/src/hook_helpers/shared.dart' show assetId, package;
15+
import 'package:intl4x/src/hook_helpers/version.dart' show version;
1716

1817
void main(List<String> args) async {
1918
await build(args, (input, output) async {
20-
final buildOptions = await getBuildOptions(
21-
input.outputDirectory.toFilePath(),
22-
);
23-
if (buildOptions == null) {
19+
BuildOptions buildOptions;
20+
try {
21+
buildOptions = BuildOptions.fromDefines(input.userDefines);
22+
print('Got build options: ${buildOptions.toJson()}');
23+
} catch (e) {
2424
throw ArgumentError('''
25+
Error: $e
26+
27+
28+
Set the build mode with either `fetch`, `local`, or `checkout` by writing into your pubspec:
2529
26-
Unknown build mode for icu4x. Set the build mode with either `fetch`, `local`, or `checkout` by writing into your pubspec:
2730
* fetch: Fetch the precompiled binary from a CDN.
2831
```
29-
...
30-
hook:
31-
intl4x:
32-
buildMode: fetch
33-
...
32+
hooks:
33+
user_defines:
34+
intl4x:
35+
buildMode: fetch
3436
```
37+
3538
* local: Use a locally existing binary at the environment variable `LOCAL_ICU4X_BINARY`.
3639
```
37-
...
38-
hook:
39-
intl4x:
40-
buildMode: local
41-
localDylibPath: path/to/dylib.so
42-
...
40+
hooks:
41+
user_defines:
42+
intl4x:
43+
buildMode: local
44+
localDylibPath: path/to/dylib.so
4345
```
46+
4447
* checkout: Build a fresh library from a local git checkout of the icu4x repository.
4548
```
46-
...
47-
hook:
48-
intl4x:
49-
buildMode: checkout
50-
checkoutPath: path/to/checkout
51-
...
49+
hooks:
50+
user_defines:
51+
intl4x:
52+
buildMode: checkout
53+
checkoutPath: path/to/checkout
5254
```
5355
5456
''');
@@ -70,25 +72,21 @@ hook:
7072
};
7173

7274
final builtLibrary = await buildMode.build();
73-
// For debugging purposes
74-
// ignore: deprecated_member_use
75-
output.addMetadatum('ICU4X_BUILD_MODE', buildOptions.buildMode.name);
7675

77-
final targetOS = input.config.code.targetOS;
78-
final targetArchitecture = input.config.code.targetArchitecture;
7976
output.assets.code.add(
8077
CodeAsset(
8178
package: package,
8279
name: assetId,
8380
linkMode: DynamicLoadingBundled(),
84-
architecture: targetArchitecture,
85-
os: targetOS,
8681
file: builtLibrary,
8782
),
88-
linkInPackage: input.config.linkingEnabled ? package : null,
83+
routing:
84+
input.config.linkingEnabled
85+
? const ToLinkHook(package)
86+
: const ToAppBundle(),
8987
);
90-
9188
output.addDependencies(buildMode.dependencies);
89+
output.addDependency(input.packageRoot.resolve('pubspec.yaml'));
9290
});
9391
}
9492

@@ -155,12 +153,12 @@ final class FetchMode extends BuildMode {
155153
}
156154

157155
final class LocalMode extends BuildMode {
158-
final String? localPath;
156+
final Uri? localPath;
159157
LocalMode(super.input, this.localPath, super.treeshake);
160158

161159
String get _localLibraryPath {
162160
if (localPath != null) {
163-
return localPath!;
161+
return localPath!.toFilePath(windows: Platform.isWindows);
164162
}
165163
throw ArgumentError(
166164
'`LOCAL_ICU4X_BINARY` is empty. '
@@ -189,7 +187,7 @@ final class LocalMode extends BuildMode {
189187
}
190188

191189
final class CheckoutMode extends BuildMode {
192-
final String? checkoutPath;
190+
final Uri? checkoutPath;
193191

194192
CheckoutMode(super.input, this.checkoutPath, super.treeshake);
195193

@@ -198,140 +196,35 @@ final class CheckoutMode extends BuildMode {
198196
print('Running in `checkout` mode');
199197
if (checkoutPath == null) {
200198
throw ArgumentError(
201-
'Specify the ICU4X checkout folder'
202-
'with the LOCAL_ICU4X_CHECKOUT variable',
199+
'Specify the ICU4X checkout folder with the `checkoutPath` key in your '
200+
'pubspec build options.',
203201
);
204202
}
205-
return await buildLib(input, checkoutPath!, treeshake);
206-
}
207-
208-
@override
209-
List<Uri> get dependencies => [
210-
Uri.directory(checkoutPath!).resolve('Cargo.lock'),
211-
];
212-
}
213-
214-
//TODO: Reuse code from package:icu4x as soon as it is published.
215-
Future<Uri> buildLib(
216-
BuildInput input,
217-
String workingDirectory,
218-
bool treeshake,
219-
) async {
220-
final crateNameFixed = crateName.replaceAll('-', '_');
221-
final libFileName = input.config.filename(treeshake)(crateNameFixed);
222-
final libFileUri = input.outputDirectory.resolve(libFileName);
223-
224-
final code = input.config.code;
225-
final targetOS = code.targetOS;
226-
final targetArchitecture = code.targetArchitecture;
227-
final buildStatic = input.config.buildStatic(treeshake);
228-
229-
final isNoStd = _isNoStdTarget((targetOS, targetArchitecture));
230-
final target = asRustTarget(input);
231-
232-
if (!isNoStd) {
233-
final rustArguments = ['target', 'add', target];
234-
await runProcess(
235-
'rustup',
236-
rustArguments,
237-
workingDirectory: workingDirectory,
203+
final builtLib = await buildLib(
204+
input.config.code.targetOS,
205+
input.config.code.targetArchitecture,
206+
input.config.buildStatic(treeshake),
207+
input.config.code.targetOS == OS.iOS &&
208+
input.config.code.iOS.targetSdk == IOSSdk.iPhoneSimulator,
209+
Directory.fromUri(checkoutPath!),
210+
[
211+
'icu_collator',
212+
'icu_datetime',
213+
'icu_list',
214+
'icu_decimal',
215+
'icu_plurals',
216+
'experimental_components',
217+
'default_components',
218+
'compiled_data',
219+
],
238220
);
221+
return builtLib.uri;
239222
}
240-
final stdFeatures = ['logging', 'simple_logger'];
241-
final noStdFeatures = ['libc_alloc', 'panic_handler'];
242-
final features = {
243-
'default_components',
244-
'icu_collator',
245-
'icu_datetime',
246-
'icu_list',
247-
'icu_decimal',
248-
'icu_plurals',
249-
'compiled_data',
250-
'buffer_provider',
251-
'experimental_components',
252-
...(isNoStd ? noStdFeatures : stdFeatures),
253-
};
254-
final arguments = [
255-
if (buildStatic || isNoStd) '+nightly',
256-
'rustc',
257-
'--manifest-path=$workingDirectory/ffi/capi/Cargo.toml',
258-
'--crate-type=${buildStatic ? 'staticlib' : 'cdylib'}',
259-
'--release',
260-
'--config=profile.release.panic="abort"',
261-
'--config=profile.release.codegen-units=1',
262-
'--no-default-features',
263-
'--features=${features.join(',')}',
264-
if (isNoStd) '-Zbuild-std=core,alloc',
265-
if (buildStatic || isNoStd) ...[
266-
'-Zbuild-std=std,panic_abort',
267-
'-Zbuild-std-features=panic_immediate_abort',
268-
],
269-
'--target=$target',
270-
];
271-
await runProcess('cargo', arguments, workingDirectory: workingDirectory);
272-
273-
final builtPath = path.join(
274-
workingDirectory,
275-
'target',
276-
target,
277-
'release',
278-
libFileName,
279-
);
280-
final file = File(builtPath);
281-
if (!(await file.exists())) {
282-
throw FileSystemException('Building the dylib failed', builtPath);
283-
}
284-
await file.copy(libFileUri.toFilePath(windows: Platform.isWindows));
285-
return libFileUri;
286-
}
287223

288-
String asRustTarget(BuildInput input) {
289-
final rustTarget = _asRustTarget(
290-
input.config.code.targetOS,
291-
input.config.code.targetArchitecture,
292-
input.config.code.targetOS == OS.iOS &&
293-
input.config.code.iOS.targetSdk == IOSSdk.iPhoneSimulator,
294-
);
295-
return rustTarget;
296-
}
297-
298-
String _asRustTarget(OS os, Architecture? architecture, bool isSimulator) {
299-
if (os == OS.iOS && architecture == Architecture.arm64 && isSimulator) {
300-
return 'aarch64-apple-ios-sim';
301-
}
302-
return switch ((os, architecture)) {
303-
(OS.android, Architecture.arm) => 'armv7-linux-androideabi',
304-
(OS.android, Architecture.arm64) => 'aarch64-linux-android',
305-
(OS.android, Architecture.ia32) => 'i686-linux-android',
306-
(OS.android, Architecture.riscv64) => 'riscv64-linux-android',
307-
(OS.android, Architecture.x64) => 'x86_64-linux-android',
308-
(OS.fuchsia, Architecture.arm64) => 'aarch64-unknown-fuchsia',
309-
(OS.fuchsia, Architecture.x64) => 'x86_64-unknown-fuchsia',
310-
(OS.iOS, Architecture.arm64) => 'aarch64-apple-ios',
311-
(OS.iOS, Architecture.x64) => 'x86_64-apple-ios',
312-
(OS.linux, Architecture.arm) => 'armv7-unknown-linux-gnueabihf',
313-
(OS.linux, Architecture.arm64) => 'aarch64-unknown-linux-gnu',
314-
(OS.linux, Architecture.ia32) => 'i686-unknown-linux-gnu',
315-
(OS.linux, Architecture.riscv32) => 'riscv32gc-unknown-linux-gnu',
316-
(OS.linux, Architecture.riscv64) => 'riscv64gc-unknown-linux-gnu',
317-
(OS.linux, Architecture.x64) => 'x86_64-unknown-linux-gnu',
318-
(OS.macOS, Architecture.arm64) => 'aarch64-apple-darwin',
319-
(OS.macOS, Architecture.x64) => 'x86_64-apple-darwin',
320-
(OS.windows, Architecture.arm64) => 'aarch64-pc-windows-msvc',
321-
(OS.windows, Architecture.ia32) => 'i686-pc-windows-msvc',
322-
(OS.windows, Architecture.x64) => 'x86_64-pc-windows-msvc',
323-
(_, _) =>
324-
throw UnimplementedError(
325-
'Target ${(os, architecture)} not available for rust',
326-
),
327-
};
224+
@override
225+
List<Uri> get dependencies => [checkoutPath!.resolve('Cargo.lock')];
328226
}
329227

330-
bool _isNoStdTarget((OS os, Architecture? architecture) arg) => [
331-
(OS.android, Architecture.riscv64),
332-
(OS.linux, Architecture.riscv64),
333-
].contains(arg);
334-
335228
extension on BuildConfig {
336229
bool buildStatic(bool treeshake) =>
337230
code.linkModePreference == LinkModePreference.static ||

pkgs/intl4x/hook/link.dart

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
import 'dart:convert';
66
import 'dart:io';
77

8-
import 'package:collection/collection.dart';
8+
import 'package:code_assets/code_assets.dart' show LinkInputCodeAssets;
9+
import 'package:collection/collection.dart' show IterableExtension;
10+
import 'package:hooks/hooks.dart' show LinkInput, link;
911
import 'package:intl4x/src/hook_helpers/shared.dart' show assetId, package;
1012
import 'package:logging/logging.dart';
11-
import 'package:native_assets_cli/code_assets.dart';
1213
import 'package:native_toolchain_c/native_toolchain_c.dart';
1314
import 'package:record_use/record_use.dart' as record_use;
1415

@@ -31,22 +32,19 @@ Future<void> main(List<String> args) async {
3132

3233
output.addDependency(staticLib.file!);
3334

34-
final usedSymbols = input.usages
35-
.instancesOf(recordSymbolId)!
36-
.map(
37-
(instance) =>
38-
// Get the "symbol" field value from "RecordSymbol"
39-
(instance.instanceConstant.fields.values.first
40-
as record_use.StringConstant)
41-
.value,
42-
);
43-
final linker = CLinker.library(
35+
final usages = input.usages;
36+
final usedSymbols = usages
37+
?.constantsOf(recordSymbolId)
38+
.map((instance) => instance['symbol'] as String);
39+
40+
print('Using symbols: $usedSymbols');
41+
42+
await CLinker.library(
4443
name: input.packageName,
4544
assetName: assetId,
4645
sources: [staticLib.file!.path],
4746
linkerOptions: LinkerOptions.treeshake(symbols: usedSymbols),
48-
);
49-
await linker.run(
47+
).run(
5048
input: input,
5149
output: output,
5250
logger:
@@ -58,9 +56,11 @@ Future<void> main(List<String> args) async {
5856
}
5957

6058
extension on LinkInput {
61-
record_use.RecordedUsages get usages {
62-
final usagesFile = recordedUsagesFile;
63-
final usagesContent = File.fromUri(usagesFile!).readAsStringSync();
59+
record_use.RecordedUsages? get usages {
60+
if (recordedUsagesFile == null) {
61+
return null;
62+
}
63+
final usagesContent = File.fromUri(recordedUsagesFile!).readAsStringSync();
6464
final usagesJson = jsonDecode(usagesContent) as Map<String, dynamic>;
6565
return record_use.RecordedUsages.fromJson(usagesJson);
6666
}

0 commit comments

Comments
 (0)