[native_assets_builder] Fix hook kernel compilation caching (#1406)
diff --git a/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart b/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart
index 70a37a8..e86b36d 100644
--- a/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart
+++ b/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart
@@ -610,9 +610,20 @@
}
}
- /// Compiles the hook to dill and caches the dill.
+ /// Compiles the hook to kernel and caches the kernel.
///
- /// It does not reuse the cached dill for different [config]s, due to
+ /// If any of the Dart source files, or the package config changed after
+ /// the last time the kernel file is compiled, the kernel file is
+ /// recompiled. Otherwise a cached version is used.
+ ///
+ /// Due to some OSes only providing last-modified timestamps with second
+ /// precision. The kernel compilation cache might be considered stale if
+ /// the last modification and the kernel compilation happened within one
+ /// second of each other. We error on the side of caution, rather recompile
+ /// one time too many, then not recompiling when recompilation should have
+ /// happened.
+ ///
+ /// It does not reuse the cached kernel for different [config]s, due to
/// reentrancy requirements. For more info see:
/// https://github.com/dart-lang/native/issues/1319
Future<(bool success, File kernelFile, DateTime lastSourceChange)>
@@ -639,7 +650,7 @@
final dartSourceFiles = depFileContents
.trim()
.split(' ')
- .skip(1) // '<dill>:'
+ .skip(1) // '<kernel file>:'
.map((u) => Uri.file(u).fileSystemEntity)
.toList();
final dartFilesLastChange = await dartSourceFiles.lastModified();
@@ -648,8 +659,9 @@
sourceLastChange = packageConfigLastChange.isAfter(dartFilesLastChange)
? packageConfigLastChange
: dartFilesLastChange;
- final dillLastChange = await kernelFile.lastModified();
- mustCompile = sourceLastChange.isAfter(dillLastChange);
+ final kernelLastChange = await kernelFile.lastModified();
+ mustCompile = sourceLastChange == kernelLastChange ||
+ sourceLastChange.isAfter(kernelLastChange);
}
final bool success;
if (!mustCompile) {
diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart
index 10f3231..88501a2 100644
--- a/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart
+++ b/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart
@@ -110,26 +110,35 @@
test(
'add C file, modify hook',
timeout: longTimeout,
- onPlatform: {
- 'linux': const Skip('https://github.com/dart-lang/native/issues/1391.'),
- },
() async {
await inTempDir((tempUri) async {
await copyTestProjects(targetUri: tempUri);
final packageUri = tempUri.resolve('native_add/');
+ final logMessages = <String>[];
+ final logger = createCapturingLogger(logMessages);
+
await runPubGet(workingDirectory: packageUri, logger: logger);
+ logMessages.clear();
// Make sure the first compile is at least one second after the
// package_config.json is written, otherwise dill compilation isn't
// cached.
await Future<void>.delayed(const Duration(seconds: 1));
+ final result = await build(packageUri, logger, dartExecutable);
{
- final result = await build(packageUri, logger, dartExecutable);
- await expectSymbols(
- asset: result.assets.single as NativeCodeAssetImpl,
- symbols: ['add']);
+ final compiledHook = logMessages
+ .where((m) =>
+ m.contains('dart compile kernel') ||
+ m.contains('dart.exe compile kernel'))
+ .isNotEmpty;
+ expect(compiledHook, isTrue);
}
+ logMessages.clear();
+ await expectSymbols(
+ asset: result.assets.single as NativeCodeAssetImpl,
+ symbols: ['add'],
+ );
await copyTestProjects(
sourceUri: testDataUri.resolve('native_add_add_source/'),
@@ -137,9 +146,19 @@
{
final result = await build(packageUri, logger, dartExecutable);
+ {
+ final compiledHook = logMessages
+ .where((m) =>
+ m.contains('dart compile kernel') ||
+ m.contains('dart.exe compile kernel'))
+ .isNotEmpty;
+ expect(compiledHook, isTrue);
+ }
+ logMessages.clear();
await expectSymbols(
- asset: result.assets.single as NativeCodeAssetImpl,
- symbols: ['add', 'multiply']);
+ asset: result.assets.single as NativeCodeAssetImpl,
+ symbols: ['add', 'multiply'],
+ );
}
});
},
diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart
index 2c2d33f..cdd19fa 100644
--- a/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart
+++ b/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart
@@ -24,6 +24,11 @@
logger: logger,
);
+ // Make sure the first compile is at least one second after the
+ // package_config.json is written, otherwise dill compilation isn't
+ // cached.
+ await Future<void>.delayed(const Duration(seconds: 1));
+
// Trigger a build, should invoke build for libraries with native assets.
{
final logMessages = <String>[];