gpt4 book ai didi

Dart build_runner 只能扫描/读取/写入web/目录下的文件?

转载 作者:IT王子 更新时间:2023-10-29 06:55:05 58 4
gpt4 key购买 nike

我正在开发一个 Flutter 应用程序,并想编写一个构建脚本来将某种原始文件(CSV 格式)转换为格式化的 JSON 文件,以作为 Flutter Assets 包含在内。

通过使用像 json_serializablejaguar_serializer 这样的库,我了解了 build_runner,所以看起来我要编写自己的 Builder 并通过 build_runner 调用它是一种明智的方式。

由于有关编写我们自己的构建脚本的资源非常有限,我首先修改找到的示例 here .但是我在尝试更改输入和输出文件的路径时卡住了:当我运行 flutter pub pub run build_runner build 时,结果发现 Dart 仅在 [ project_dir]/web 目录,只允许我将文件写入此 web 目录。所以这段代码

buildStep.writeAsString(new AssetId(buildStep.inputId.package, 'assets/resources/foo.json'), '[]');

将产生以下异常:

UnexpectedOutputException: myapp|assets/resources/foo.json
Expected only: {myapp|web/.json}
[SEVERE] Failed after 24.4s

json_serializablejaguar_serializer 可以在任何地方自由生成代码这一事实似乎表明我的配置存在问题。但是我在我的代码和 build.yaml 文件中的任何地方都找不到这个 web 东西,所以这真的很令人费解。

FWIW,这是我的 builder.yaml 文件的内容:

builders:
jsonBuilder:
import: "package:myapp/builder.dart"
builder_factories: ["jsonFileBuilder"]
build_extensions: {"source.csv": [".json"]}
build_to: source
auto_apply: root_package

这是 builder.dart 文件

import 'dart:async';
import 'package:build/build.dart';

Builder jsonFileBuilder(BuilderOptions options) => new JsonFileBuilder();

class JsonFileBuilder implements Builder {
@override
Future build(BuildStep buildStep) async {
await buildStep.writeAsString(
new AssetId(buildStep.inputId.package, 'assets/resources/foo.json'),
'hello');
}

@override
final buildExtensions = const {
'source.csv': const ['.json']
};
}

提前致谢!

最佳答案

好吧,看来这个问题实际上是双重的。

关于输入

我的问题是,如果我将源 CSV 文件放在某个任意目录下(例如 offline),我的构建脚本将不会运行,因为没有找到匹配的文件。但是当我将文件放在 web 下时(如示例中所示),脚本将被调用。这让我产生了文件扫描仅限于web/的错觉。事实上,有一个列表 hard-coded file/directory whitelist :

const List<String> _defaultRootPackageWhitelist = const [
'benchmark/**',
'bin/**',
'example/**',
'lib/**',
'test/**',
'tool/**',
'web/**',
'pubspec.yaml',
'pubspec.lock',
];

如果我将 CSV 文件放在 lib/ 下,我的构建脚本也会被调用。

要将我的非白名单文件附加到列表中,我必须将以下部分添加到 build.yaml

targets:
$default:
sources:
# Need to replicate the default whitelist here or other build will break:
- "benchmark/**"
- "bin/**"
- "example/**"
- "lib/**"
- "test/**"
- "tool/**"
- "web/**"
- "pubspec.yaml"
- "pubspec.lock"
# My new source
- "offline/source.csv"

关于输出

我的问题是我无法写入任意目录,构建系统一直提示我只能写入web/。所以我以为文件写入被锁定到web/。同样,这也不完全正确,因为文件写入实际上锁定到输入文件的目录。这意味着我只能在构建运行器成功识别此目录中的文件后才能写入 offline/

文件写入权限的检查由this method in build_step_impl.dart控制:

  void _checkOutput(AssetId id) {
if (!_expectedOutputs.contains(id)) {
throw new UnexpectedOutputException(id, expected: _expectedOutputs);
}
}

_expectedOutputs 是我的构建器类的 buildExtensions 映射的扁平化值。所以如果我真的想写入 assets/resources/foo.json 我必须这样写:

  @override
final buildExtensions = const {
'source.csv': const ['/../../assets/resources/foo.json']
};

必须对 build.yaml 进行类似的调整:

build_extensions: {".csv": ["/../../assets/resources/foo.json"]}

这基本上解决了我的大部分问题,但还有一些问题:

首先,我打算编写一个读取单个文件并写入多个文件的构建脚本。文件的数量及其文件名取决于源文件的内容。鉴于检查代码,这似乎不是受支持的功能。不是障碍物,但有点不方便。

第二个是关于输出文件路径。您可以看到我的源文件位于 [projectDir]/offline 中,我想写入 [projectDir]/assets,但输出文件名显示为 /。 ./../assets/...,向上两层。这是因为原始文件名(没有扩展名)被添加到输出路径之前,这就是为什么人们会在生成 Dart 代码的构建器配置中看到 .g.dart 的原因。我需要编写 /../../assets 这样我的文件的完整输出路径将变为 [projectDir]/offline/source/../../assets 使其解析为所需的输出文件路径。但是默认行为给我的印象是构建系统不希望我的脚本写入当前文件目录之外的任何地方,而我所做的是对系统的黑客攻击或滥用。

关于Dart build_runner 只能扫描/读取/写入web/目录下的文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51188114/

58 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com