4
4
5
5
import 'dart:io' ;
6
6
7
+ import 'package:code_assets/code_assets.dart' ;
7
8
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;
17
16
18
17
void main (List <String > args) async {
19
18
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) {
24
24
throw ArgumentError ('''
25
+ Error: $e
26
+
27
+
28
+ Set the build mode with either `fetch`, `local`, or `checkout` by writing into your pubspec:
25
29
26
- Unknown build mode for icu4x. Set the build mode with either `fetch`, `local`, or `checkout` by writing into your pubspec:
27
30
* fetch: Fetch the precompiled binary from a CDN.
28
31
```
29
- ...
30
- hook:
31
- intl4x:
32
- buildMode: fetch
33
- ...
32
+ hooks:
33
+ user_defines:
34
+ intl4x:
35
+ buildMode: fetch
34
36
```
37
+
35
38
* local: Use a locally existing binary at the environment variable `LOCAL_ICU4X_BINARY`.
36
39
```
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
43
45
```
46
+
44
47
* checkout: Build a fresh library from a local git checkout of the icu4x repository.
45
48
```
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
52
54
```
53
55
54
56
''' );
@@ -70,25 +72,21 @@ hook:
70
72
};
71
73
72
74
final builtLibrary = await buildMode.build ();
73
- // For debugging purposes
74
- // ignore: deprecated_member_use
75
- output.addMetadatum ('ICU4X_BUILD_MODE' , buildOptions.buildMode.name);
76
75
77
- final targetOS = input.config.code.targetOS;
78
- final targetArchitecture = input.config.code.targetArchitecture;
79
76
output.assets.code.add (
80
77
CodeAsset (
81
78
package: package,
82
79
name: assetId,
83
80
linkMode: DynamicLoadingBundled (),
84
- architecture: targetArchitecture,
85
- os: targetOS,
86
81
file: builtLibrary,
87
82
),
88
- linkInPackage: input.config.linkingEnabled ? package : null ,
83
+ routing:
84
+ input.config.linkingEnabled
85
+ ? const ToLinkHook (package)
86
+ : const ToAppBundle (),
89
87
);
90
-
91
88
output.addDependencies (buildMode.dependencies);
89
+ output.addDependency (input.packageRoot.resolve ('pubspec.yaml' ));
92
90
});
93
91
}
94
92
@@ -155,12 +153,12 @@ final class FetchMode extends BuildMode {
155
153
}
156
154
157
155
final class LocalMode extends BuildMode {
158
- final String ? localPath;
156
+ final Uri ? localPath;
159
157
LocalMode (super .input, this .localPath, super .treeshake);
160
158
161
159
String get _localLibraryPath {
162
160
if (localPath != null ) {
163
- return localPath! ;
161
+ return localPath! . toFilePath (windows : Platform .isWindows) ;
164
162
}
165
163
throw ArgumentError (
166
164
'`LOCAL_ICU4X_BINARY` is empty. '
@@ -189,7 +187,7 @@ final class LocalMode extends BuildMode {
189
187
}
190
188
191
189
final class CheckoutMode extends BuildMode {
192
- final String ? checkoutPath;
190
+ final Uri ? checkoutPath;
193
191
194
192
CheckoutMode (super .input, this .checkoutPath, super .treeshake);
195
193
@@ -198,140 +196,35 @@ final class CheckoutMode extends BuildMode {
198
196
print ('Running in `checkout` mode' );
199
197
if (checkoutPath == null ) {
200
198
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. ' ,
203
201
);
204
202
}
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
+ ],
238
220
);
221
+ return builtLib.uri;
239
222
}
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
- }
287
223
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' )];
328
226
}
329
227
330
- bool _isNoStdTarget ((OS os, Architecture ? architecture) arg) => [
331
- (OS .android, Architecture .riscv64),
332
- (OS .linux, Architecture .riscv64),
333
- ].contains (arg);
334
-
335
228
extension on BuildConfig {
336
229
bool buildStatic (bool treeshake) =>
337
230
code.linkModePreference == LinkModePreference .static ||
0 commit comments