Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add collation from ICU4X #740

Merged
merged 58 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
0327cde
Add collation
mosuem Nov 7, 2023
f90d888
Remove unused import
mosuem Nov 7, 2023
44a8e36
Update to merged
mosuem Nov 15, 2023
a7e253c
Merge branch 'main' into addCollationICU4X
mosuem Dec 6, 2023
2d40719
Merge branch 'main' into addCollationICU4X
mosuem Jan 3, 2024
f36d1cf
Merge branch 'main' into addCollationICU4X
mosuem Jan 11, 2024
e57d200
Setup submodule
mosuem Jan 11, 2024
c204c09
Checkout submodules
mosuem Jan 11, 2024
bf61fbc
Add build.dart
mosuem Jan 12, 2024
78da54e
move bindings
mosuem Jan 12, 2024
79a21b8
Use path to build output dir
mosuem Jan 12, 2024
2842d2c
Fix build.dart
mosuem Jan 12, 2024
5bb56c7
Enable test
mosuem Jan 12, 2024
d48fd3f
Add help
mosuem Jan 12, 2024
eeddc31
Fix help
mosuem Jan 12, 2024
f7ec5d0
Make data default
mosuem Jan 12, 2024
09535cc
Move collation test to general testing
mosuem Jan 12, 2024
aafb7d1
Fix workflow
mosuem Jan 12, 2024
1e0e5e6
Run tests on dev
mosuem Jan 12, 2024
2987977
Fix imports
mosuem Jan 12, 2024
92c6626
Add changelog and rev version
mosuem Jan 12, 2024
ec50fab
take health from branch
mosuem Jan 12, 2024
2a39b17
Add todo
mosuem Jan 15, 2024
21beea9
Add top level analysis options
mosuem Jan 15, 2024
b41e661
Merge branch 'main' into addCollationICU4X
mosuem Jan 15, 2024
7a10af1
Fix collator options
mosuem Jan 16, 2024
2aad31a
Do checkout submodules
mosuem Jan 16, 2024
e8f3570
Use checkout submodules
mosuem Jan 16, 2024
c9beb3a
Make casefirst non null
mosuem Jan 16, 2024
cea2e3e
enable native assets experiment
mosuem Jan 16, 2024
6f27941
Rev SDK
mosuem Jan 16, 2024
8d8bd35
And env
mosuem Jan 16, 2024
480ab1b
set default mode
mosuem Jan 16, 2024
9761887
Add licenses
mosuem Jan 16, 2024
493f420
Adapt option matching
mosuem Jan 23, 2024
910bf87
Update icu4x
mosuem Jan 23, 2024
778ccb9
Update icu4x ref
mosuem Jan 29, 2024
de1383b
Add ignores
mosuem Jan 29, 2024
c14158f
Merge branch 'main' into addCollationICU4X
mosuem Jan 29, 2024
8aa9a69
Update submodule
mosuem Jan 29, 2024
0184312
Remove cached
mosuem Jan 29, 2024
021c27a
Remove branch
mosuem Jan 29, 2024
caf8477
remove submodule
mosuem Jan 29, 2024
7086061
Add submodule
mosuem Jan 29, 2024
60321b3
Remove submodules
mosuem Jan 29, 2024
3eb3e80
Add submodule
mosuem Jan 29, 2024
03f1127
Merge main
mosuem Jan 29, 2024
2a30df8
Test current_repo
mosuem Jan 29, 2024
f317d47
remove bracket
mosuem Jan 29, 2024
aafef74
Add ignores
mosuem Jan 29, 2024
fcc4afa
Add changelog
mosuem Jan 29, 2024
2290897
Add trailing newline
mosuem Jan 29, 2024
f369e56
Merge branch 'main' into addCollationICU4X
mosuem Feb 1, 2024
bf67394
Incorporate build_libs.dart
mosuem Feb 1, 2024
8c90889
Add simulator special casing
mosuem Feb 1, 2024
eed6b05
Update pkgs/intl4x/build.dart
mosuem Feb 1, 2024
9462035
Update pkgs/intl4x/build.dart
mosuem Feb 1, 2024
e1c5662
Reintroduce platform name for `ubuntu`
mosuem Feb 1, 2024
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
7 changes: 7 additions & 0 deletions .github/workflows/health.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,17 @@ on:
pull_request:
branches: [ main ]
types: [opened, synchronize, reopened, labeled, unlabeled]

jobs:
health:
uses: dart-lang/ecosystem/.github/workflows/health.yaml@main
with:
coverage_web: true
checkout_submodules: true
experiments: native-assets
sdk: dev
ignore_license: "**.g.dart,pkgs/intl_translation/example/lib/generated/**,pkgs/intl_translation/test/generate_localized/**,pkgs/intl_translation/test/two_components/**"
ignore_coverage: "**.g.dart"
ignore_packages: "submodules"
permissions:
pull-requests: write
19 changes: 13 additions & 6 deletions .github/workflows/intl4x.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,37 @@ on:
jobs:
build:
runs-on: ubuntu-latest

env:
ICU4X_BUILD_MODE: fetch

defaults:
run:
working-directory: pkgs/intl4x
strategy:
matrix:
sdk: [stable, dev] # {pkgs.versions}
include:
- sdk: stable
- sdk: dev
run-tests: true
steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
with:
submodules: true

- uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3
with:
sdk: ${{matrix.sdk}}

- run: dart pub get
- run: dart --enable-experiment=native-assets pub get

- run: dart analyze --fatal-infos
- run: dart --enable-experiment=native-assets analyze --fatal-infos

- run: dart format --output=none --set-exit-if-changed .
- run: dart --enable-experiment=native-assets format --output=none --set-exit-if-changed .
if: ${{matrix.run-tests}}

- run: dart test
- run: dart --enable-experiment=native-assets test
if: ${{matrix.run-tests}}

- run: dart test -p chrome
- run: dart --enable-experiment=native-assets test -p chrome
if: ${{matrix.run-tests}}
1 change: 1 addition & 0 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ jobs:
uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main
with:
write-comments: false
checkout_submodules: true
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@

# Specific files
pkgs/intl/test/number_format_compact_google3_icu_test.dart
pkgs/intl/update_from_cldr_data.sh
pkgs/intl/update_from_cldr_data.sh
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "submodules/icu4x"]
path = submodules/icu4x
url = https://github.com/unicode-org/icu4x.git
3 changes: 3 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
analyzer:
exclude:
- "submodules/*"
4 changes: 4 additions & 0 deletions pkgs/intl4x/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.8.0

- Add ICU4X support for collation.

## 0.7.1

- Export plural rules.
Expand Down
5 changes: 5 additions & 0 deletions pkgs/intl4x/analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ linter:
- prefer_final_locals
- prefer_relative_imports
- unnecessary_parenthesis

analyzer:
exclude:
- "submodules/*"
- "lib/src/bindings/*"
256 changes: 256 additions & 0 deletions pkgs/intl4x/build.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
// Copyright (c) 2024, 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 'dart:io';

import 'package:archive/archive_io.dart';
import 'package:native_assets_cli/native_assets_cli.dart';
import 'package:path/path.dart' as path;

const crateName = 'icu_capi';
const assetId = 'package:intl4x/src/bindings/lib.g.dart';

void main(List<String> args) async {
final config = await BuildConfig.fromArgs(args);

final libFolder = path.join(config.outDir.path, 'release');
Directory(libFolder).createSync();
final libPath = path.join(
libFolder,
config.targetOs.dylibFileName(crateName.replaceAll('-', '_')),
);

final buildMode = switch (Platform.environment['ICU4X_BUILD_MODE']) {
'local' => LocalMode(libPath),
'checkout' => CheckoutMode(config, libPath),
'fetch' || null => FetchMode(libPath),
String() => throw ArgumentError('''


Unknown build mode for icu4x. Set the `ICU4X_BUILD_MODE` environment variable with either `fetch`, `local`, or `checkout`.
* fetch: Fetch the precompiled binary from a CDN.
* local: Use a locally existing binary at the environment variable `LOCAL_ICU4X_BINARY`.
* checkout: Build a fresh library from a local git checkout of the icu4x repository at the environment variable `LOCAL_ICU4X_CHECKOUT`.

'''),
};

await buildMode.build();

await BuildOutput(
assets: [
Asset(
id: assetId,
linkMode: LinkMode.dynamic,
target: Target.current,
path: AssetAbsolutePath(Uri.file(libPath)),
)
],
dependencies: Dependencies([Uri.file('build.dart')]),
).writeToFile(outDir: config.outDir);
}

void unzipFirstFile({required File input, required File output}) {
final inputStream = InputFileStream(input.path);
final archive = ZipDecoder().decodeBuffer(inputStream);
final file = archive.files.firstOrNull;
// If it's a file and not a directory
if (file?.isFile ?? false) {
final outputStream = OutputFileStream(output.path);
file!.writeContent(outputStream);
outputStream.close();
}
}

sealed class BuildMode {
Future<void> build();
}

final class FetchMode implements BuildMode {
final String libPath;

FetchMode(this.libPath);

@override
Future<void> build() async {
// TODO: Get a nicer CDN than a generated link to a privately owned repo.
final request = await HttpClient().getUrl(Uri.parse(
'https://nightly.link/mosuem/i18n/workflows/intl4x_artifacts/main/lib-$platformName-latest.zip'));
final response = await request.close();

final zippedDynamicLibrary =
File(path.join(Directory.systemTemp.path, 'tmp.zip'));
zippedDynamicLibrary.createSync();
await response.pipe(zippedDynamicLibrary.openWrite());

final dynamicLibrary = File(libPath);
dynamicLibrary.createSync(recursive: true);
unzipFirstFile(input: zippedDynamicLibrary, output: dynamicLibrary);
}

String get platformName {
if (Platform.isMacOS) {
return 'macos';
} else if (Platform.isWindows) {
return 'windows';
} else {
return 'ubuntu';
}
}
}

final class LocalMode implements BuildMode {
final String libPath;

LocalMode(this.libPath);

String get _localBinaryPath => Platform.environment['LOCAL_ICU4X_BINARY']!;

@override
Future<void> build() async {
await File(_localBinaryPath).copy(libPath);
}
}

final class CheckoutMode implements BuildMode {
final BuildConfig config;
final String libPath;
CheckoutMode(this.config, this.libPath);

@override
Future<void> build() async {
final workingDirectory = Platform.environment['LOCAL_ICU4X_CHECKOUT'];
if (workingDirectory == null) {
throw ArgumentError('Specify the ICU4X checkout folder'
'with the LOCAL_ICU4X_CHECKOUT variable');
}
final lib = await buildLib(
config,
workingDirectory,
);
await File(lib).copy(libPath);
}
}

Future<String> buildLib(
BuildConfig config,
String workingDirectory,
) async {
final rustTarget =
config.target.asRustTarget(config.targetIOSSdk == IOSSdk.iPhoneSimulator);
final isNoStd = config.target.isNoStdTarget;

if (!isNoStd) {
final rustArguments = ['target', 'add', rustTarget];
final rustup = await Process.run(
'rustup',
rustArguments,
workingDirectory: workingDirectory,
);

if (rustup.exitCode != 0) {
throw ProcessException(
'rustup',
rustArguments,
rustup.stderr.toString(),
rustup.exitCode,
);
}
}

final stdFeatures = [
'default_components',
'compiled_data',
'buffer_provider',
'logging',
'simple_logger',
];
final noStdFeatures = [
'default_components',
'compiled_data',
'buffer_provider',
'libc-alloc',
'panic-handler'
];
final tempDir = Directory.systemTemp.createTempSync();
final linkModeType =
config.linkModePreference.preferredLinkMode == LinkMode.static
? 'staticlib'
: 'cdylib';
final arguments = [
if (isNoStd) '+nightly',
'rustc',
'-p={crateName}',
'--crate-type=$linkModeType',
'--release',
'--config=profile.release.panic="abort"',
'--config=profile.release.codegen-units=1',
'--no-default-features',
if (!isNoStd) '--features=${stdFeatures.join(',')}',
if (isNoStd) '--features=${noStdFeatures.join(',')}',
if (isNoStd) '-Zbuild-std=core,alloc',
if (isNoStd) '-Zbuild-std-features=panic_immediate_abort',
'--target=$rustTarget',
'--target-dir=${tempDir.path}'
];
final cargo = await Process.run(
'cargo',
arguments,
workingDirectory: workingDirectory,
);

if (cargo.exitCode != 0) {
throw ProcessException(
'cargo',
arguments,
cargo.stderr.toString(),
cargo.exitCode,
);
}

final dylibFilePath = path.join(
tempDir.path,
rustTarget,
'release',
config.target.os.dylibFileName(crateName.replaceAll('-', '_')),
);
if (!File(dylibFilePath).existsSync()) {
throw FileSystemException('Building the dylib failed', dylibFilePath);
}
return dylibFilePath;
}

extension on Target {
String asRustTarget(bool isSimulator) {
if (this == Target.iOSArm64 && isSimulator) {
return 'aarch64-apple-ios-sim';
}
return switch (this) {
Target.androidArm => 'armv7-linux-androideabi',
Target.androidArm64 => 'aarch64-linux-android',
Target.androidIA32 => 'i686-linux-android',
Target.androidRiscv64 => 'riscv64-linux-android',
Target.androidX64 => 'x86_64-linux-android',
Target.fuchsiaArm64 => 'aarch64-unknown-fuchsia',
Target.fuchsiaX64 => 'x86_64-unknown-fuchsia',
Target.iOSArm64 => 'aarch64-apple-ios',
Target.iOSX64 => 'x86_64-apple-ios',
Target.linuxArm => 'armv7-unknown-linux-gnueabihf',
Target.linuxArm64 => 'aarch64-unknown-linux-gnu',
Target.linuxIA32 => 'i686-unknown-linux-gnu',
Target.linuxRiscv32 => 'riscv32gc-unknown-linux-gnu',
Target.linuxRiscv64 => 'riscv64gc-unknown-linux-gnu',
Target.linuxX64 => 'x86_64-unknown-linux-gnu',
Target.macOSArm64 => 'aarch64-apple-darwin',
Target.macOSX64 => 'x86_64-apple-darwin',
Target.windowsArm64 => 'aarch64-pc-windows-msvc',
Target.windowsIA32 => 'i686-pc-windows-msvc',
Target.windowsX64 => 'x86_64-pc-windows-msvc',
Target() => throw UnimplementedError('Target not available for rust'),
};
}

bool get isNoStdTarget =>
[Target.androidRiscv64, Target.linuxRiscv32].contains(this);
}
Loading
Loading