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

[native_assets_builder] Make hook environment configurable #1853

Merged
merged 1 commit into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions pkgs/native_assets_builder/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.10.1

- Pass in the environment for hook invocations.

## 0.10.0

- Removed support for dry run (Flutter no long requires it).
Expand Down
9 changes: 8 additions & 1 deletion pkgs/native_assets_builder/lib/native_assets_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
// 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.

export 'package:native_assets_builder/src/build_runner/build_runner.dart';
export 'package:native_assets_builder/src/build_runner/build_runner.dart'
show
ApplicationAssetValidator,
BuildConfigValidator,
BuildValidator,
LinkConfigValidator,
LinkValidator,
NativeAssetsBuildRunner;
export 'package:native_assets_builder/src/model/build_result.dart';
export 'package:native_assets_builder/src/model/kernel_assets.dart';
export 'package:native_assets_builder/src/model/link_result.dart';
Expand Down
30 changes: 16 additions & 14 deletions pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,18 @@ class NativeAssetsBuildRunner {
final Logger logger;
final Uri dartExecutable;
final Duration singleHookTimeout;
final Map<String, String> hookEnvironment;

NativeAssetsBuildRunner({
required this.logger,
required this.dartExecutable,
required FileSystem fileSystem,
Duration? singleHookTimeout,
Map<String, String>? hookEnvironment,
}) : _fileSystem = fileSystem,
singleHookTimeout = singleHookTimeout ?? const Duration(minutes: 5);
singleHookTimeout = singleHookTimeout ?? const Duration(minutes: 5),
hookEnvironment = hookEnvironment ??
filteredEnvironment(hookEnvironmentVariablesFilter);

/// [workingDirectory] is expected to contain `.dart_tool`.
///
Expand Down Expand Up @@ -321,7 +325,6 @@ class NativeAssetsBuildRunner {
Uri? resources,
PackageLayout packageLayout,
) async {
final environment = _filteredEnvironment(_environmentVariablesFilter);
final outDir = config.outputDirectory;
return await runUnderDirectoriesLock(
_fileSystem,
Expand Down Expand Up @@ -367,7 +370,7 @@ ${e.message}
}

final outdatedDependency =
await dependenciesHashes.findOutdatedDependency(environment);
await dependenciesHashes.findOutdatedDependency(hookEnvironment);
if (outdatedDependency == null) {
logger.info(
'Skipping ${hook.name} for ${config.packageName}'
Expand All @@ -393,7 +396,7 @@ ${e.message}
resources,
hookKernelFile,
packageLayout,
environment,
hookEnvironment,
);
if (result == null) {
if (await dependenciesHashes.exists()) {
Expand All @@ -409,7 +412,7 @@ ${e.message}
hookKernelFile.uri,
],
lastModifiedCutoffTime,
environment,
hookEnvironment,
);
if (modifiedDuringBuild != null) {
logger.severe('File modified during build. Build must be rerun.');
Expand All @@ -420,11 +423,11 @@ ${e.message}
);
}

/// Limit the environment that hook invocations get to see.
///
/// The list of environment variables used if [hookEnvironment] is not passed
/// in.
/// This allowlist lists environment variables needed to run mainstream
/// compilers.
static const _environmentVariablesFilter = {
static const hookEnvironmentVariablesFilter = {
'ANDROID_HOME', // Needed for the NDK.
'HOME', // Needed to find tools in default install locations.
'PATH', // Needed to invoke native tools.
Expand Down Expand Up @@ -530,12 +533,6 @@ ${e.message}
}
}

Map<String, String> _filteredEnvironment(Set<String> allowList) => {
for (final entry in Platform.environment.entries)
if (allowList.contains(entry.key.toUpperCase()))
entry.key: entry.value,
};

/// Compiles the hook to kernel and caches the kernel.
///
/// If any of the Dart source files, or the package config changed after
Expand Down Expand Up @@ -842,3 +839,8 @@ Future<List<Uri>> _readDepFile(File depFile) async {
final dartSources = parseDepFileInputs(depFileContents);
return dartSources.map(Uri.file).toList();
}

Map<String, String> filteredEnvironment(Set<String> allowList) => {
for (final entry in Platform.environment.entries)
if (allowList.contains(entry.key.toUpperCase())) entry.key: entry.value,
};
2 changes: 1 addition & 1 deletion pkgs/native_assets_builder/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: native_assets_builder
description: >-
This package is the backend that invokes build hooks.
version: 0.10.0
version: 0.10.1
repository: https://github.com/dart-lang/native/tree/main/pkgs/native_assets_builder

# publish_to: none
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import 'dart:convert';
import 'dart:io';

import 'package:native_assets_builder/src/build_runner/build_runner.dart';
import 'package:test/test.dart';

import '../helpers.dart';
Expand Down Expand Up @@ -221,75 +222,81 @@ void main() async {
},
);

test(
'change environment',
timeout: longTimeout,
() async {
await inTempDir((tempUri) async {
await copyTestProjects(targetUri: tempUri);
final packageUri = tempUri.resolve('native_add/');
for (final modifiedEnvKey in ['PATH', 'CUSTOM_KEY_123']) {
test(
'change environment $modifiedEnvKey',
timeout: longTimeout,
() async {
await inTempDir((tempUri) async {
await copyTestProjects(targetUri: tempUri);
final packageUri = tempUri.resolve('native_add/');

final logMessages = <String>[];
final logger = createCapturingLogger(logMessages);
final logMessages = <String>[];
final logger = createCapturingLogger(logMessages);

await runPubGet(workingDirectory: packageUri, logger: logger);
logMessages.clear();
await runPubGet(workingDirectory: packageUri, logger: logger);
logMessages.clear();

final result = (await build(
packageUri,
logger,
dartExecutable,
buildAssetTypes: [CodeAsset.type],
configValidator: validateCodeAssetBuildConfig,
buildValidator: validateCodeAssetBuildOutput,
applicationAssetValidator: validateCodeAssetInApplication,
))!;
logMessages.clear();
final result = (await build(
packageUri,
logger,
dartExecutable,
buildAssetTypes: [CodeAsset.type],
configValidator: validateCodeAssetBuildConfig,
buildValidator: validateCodeAssetBuildOutput,
applicationAssetValidator: validateCodeAssetInApplication,
hookEnvironment: modifiedEnvKey == 'PATH'
? null
: filteredEnvironment(
NativeAssetsBuildRunner.hookEnvironmentVariablesFilter,
),
))!;
logMessages.clear();

// Simulate that the environment variables changed by augmenting the
// persisted environment from the last invocation.
final dependenciesHashFile = File.fromUri(
CodeAsset.fromEncoded(result.encodedAssets.single)
.file!
.parent
.parent
.resolve('dependencies.dependencies_hash_file.json'),
);
expect(await dependenciesHashFile.exists(), true);
final dependenciesContent =
jsonDecode(await dependenciesHashFile.readAsString())
as Map<Object, Object?>;
const modifiedEnvKey = 'PATH';
(dependenciesContent['environment'] as List<dynamic>).add({
'key': modifiedEnvKey,
'hash': 123456789,
});
await dependenciesHashFile
.writeAsString(jsonEncode(dependenciesContent));
// Simulate that the environment variables changed by augmenting the
// persisted environment from the last invocation.
final dependenciesHashFile = File.fromUri(
CodeAsset.fromEncoded(result.encodedAssets.single)
.file!
.parent
.parent
.resolve('dependencies.dependencies_hash_file.json'),
);
expect(await dependenciesHashFile.exists(), true);
final dependenciesContent =
jsonDecode(await dependenciesHashFile.readAsString())
as Map<Object, Object?>;
(dependenciesContent['environment'] as List<dynamic>).add({
'key': modifiedEnvKey,
'hash': 123456789,
});
await dependenciesHashFile
.writeAsString(jsonEncode(dependenciesContent));

(await build(
packageUri,
logger,
dartExecutable,
buildAssetTypes: [CodeAsset.type],
configValidator: validateCodeAssetBuildConfig,
buildValidator: validateCodeAssetBuildOutput,
applicationAssetValidator: validateCodeAssetInApplication,
))!;
expect(
logMessages.join('\n'),
contains('hook.dill'),
);
expect(
logMessages.join('\n'),
isNot(contains('Skipping build for native_add')),
);
expect(
logMessages.join('\n'),
contains('Environment variable changed: $modifiedEnvKey.'),
);
logMessages.clear();
});
},
);
(await build(
packageUri,
logger,
dartExecutable,
buildAssetTypes: [CodeAsset.type],
configValidator: validateCodeAssetBuildConfig,
buildValidator: validateCodeAssetBuildOutput,
applicationAssetValidator: validateCodeAssetInApplication,
))!;
expect(
logMessages.join('\n'),
contains('hook.dill'),
);
expect(
logMessages.join('\n'),
isNot(contains('Skipping build for native_add')),
);
expect(
logMessages.join('\n'),
contains('Environment variable changed: $modifiedEnvKey.'),
);
logMessages.clear();
});
},
);
}
}
2 changes: 2 additions & 0 deletions pkgs/native_assets_builder/test/build_runner/helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,15 @@ Future<BuildResult?> build(
Target? target,
bool linkingEnabled = false,
required List<String> buildAssetTypes,
Map<String, String>? hookEnvironment,
}) async {
final targetOS = target?.os ?? OS.current;
return await runWithLog(capturedLogs, () async {
final result = await NativeAssetsBuildRunner(
logger: logger,
dartExecutable: dartExecutable,
fileSystem: const LocalFileSystem(),
hookEnvironment: hookEnvironment,
).build(
configCreator: () {
final configBuilder = BuildConfigBuilder();
Expand Down
Loading