Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[engine_build_configs] Use dart:ffi Abi to determine the host cpu #50604

Merged
merged 1 commit into from
Feb 13, 2024
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
2 changes: 2 additions & 0 deletions tools/pkg/engine_build_configs/bin/run.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:ffi' as ffi;
import 'dart:io' as io;

import 'package:engine_build_configs/engine_build_configs.dart';
Expand Down Expand Up @@ -119,6 +120,7 @@ The build names are the "name" fields of the maps in the list of "builds".
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
platform: const LocalPlatform(),
processRunner: ProcessRunner(),
abi: ffi.Abi.current(),
engineSrcDir: engine.srcDir,
build: targetBuild,
extraGnArgs: extraGnArgs,
Expand Down
45 changes: 31 additions & 14 deletions tools/pkg/engine_build_configs/lib/src/build_config_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

import 'dart:async';
import 'dart:convert';
import 'dart:io' as io show Directory, Process, ProcessResult;
import 'dart:ffi' as ffi;
import 'dart:io' as io show Directory, Process;

import 'package:path/path.dart' as p;
import 'package:platform/platform.dart';
Expand Down Expand Up @@ -111,14 +112,23 @@ typedef RunnerEventHandler = void Function(RunnerEvent);
/// An abstract base clase for running the various tasks that a build config
/// specifies. Derived classes implement the `run()` method.
sealed class Runner {
Runner(this.platform, this.processRunner, this.engineSrcDir, this.dryRun);
Runner(
this.platform,
this.processRunner,
this.abi,
this.engineSrcDir,
this.dryRun,
);

/// Information about the platform that hosts the runner.
final Platform platform;

/// Runs the subprocesses required to run the element of the build config.
final ProcessRunner processRunner;

/// The [Abi] of the host platform.
final ffi.Abi abi;

/// The src/ directory of the engine checkout.
final io.Directory engineSrcDir;

Expand Down Expand Up @@ -162,6 +172,7 @@ final class GlobalBuildRunner extends Runner {
GlobalBuildRunner({
Platform? platform,
ProcessRunner? processRunner,
ffi.Abi? abi,
required io.Directory engineSrcDir,
required this.build,
this.extraGnArgs = const <String>[],
Expand All @@ -175,6 +186,7 @@ final class GlobalBuildRunner extends Runner {
}) : super(
platform ?? const LocalPlatform(),
processRunner ?? ProcessRunner(),
abi ?? ffi.Abi.current(),
engineSrcDir,
dryRun,
);
Expand Down Expand Up @@ -289,22 +301,20 @@ final class GlobalBuildRunner extends Runner {
}

late final String _hostCpu = (){
if (platform.isWindows) {
return platform.environment['PROCESSOR_ARCHITECTURE'] ?? 'x64';
}
final List<String> unameCommand = <String>['uname', '-m'];
final io.ProcessResult unameResult = processRunner.processManager.runSync(
unameCommand,
);
return unameResult.exitCode == 0 ? (unameResult.stdout as String).trim() : 'x64';
return switch (abi) {
ffi.Abi.linuxArm64 || ffi.Abi.macosArm64 || ffi.Abi.windowsArm64 => 'arm64',
ffi.Abi.linuxX64 || ffi.Abi.macosX64 || ffi.Abi.windowsX64 => 'x64',
_ => throw StateError('This host platform "$abi" is not supported.'),
};
}();

late final String _buildtoolsPath = (){
final String platformDir = switch (platform.operatingSystem) {
final String os = platform.operatingSystem;
final String platformDir = switch (os) {
Platform.linux => 'linux-$_hostCpu',
Platform.macOS => 'mac-$_hostCpu',
Platform.windows => 'windows-$_hostCpu',
_ => '<unknown>',
_ => throw StateError('This host OS "$os" is not supported.'),
};
return p.join(engineSrcDir.path, 'buildtools', platformDir);
}();
Expand All @@ -317,11 +327,12 @@ final class GlobalBuildRunner extends Runner {
final String exe = platform.isWindows ? '.exe' : '';
final String bootstrapPath = p.join(reclientPath, 'bootstrap$exe');
final String reproxyPath = p.join(reclientPath, 'reproxy$exe');
final String reclientConfigFile = switch (platform.operatingSystem) {
final String os = platform.operatingSystem;
final String reclientConfigFile = switch (os) {
Platform.linux => 'reclient-linux.cfg',
Platform.macOS => 'reclient-mac.cfg',
Platform.windows => 'reclient-win.cfg',
_ => '<unknown>',
_ => throw StateError('This host OS "$os" is not supported.'),
};
final String reclientConfigPath = p.join(
engineSrcDir.path, 'flutter', 'build', 'rbe', reclientConfigFile,
Expand Down Expand Up @@ -487,6 +498,7 @@ final class GlobalBuildRunner extends Runner {
final BuildTaskRunner runner = BuildTaskRunner(
processRunner: processRunner,
platform: platform,
abi: abi,
engineSrcDir: engineSrcDir,
task: task,
dryRun: dryRun,
Expand All @@ -503,6 +515,7 @@ final class GlobalBuildRunner extends Runner {
final BuildTestRunner runner = BuildTestRunner(
processRunner: processRunner,
platform: platform,
abi: abi,
engineSrcDir: engineSrcDir,
test: test,
extraTestArgs: extraTestArgs,
Expand All @@ -521,12 +534,14 @@ final class BuildTaskRunner extends Runner {
BuildTaskRunner({
Platform? platform,
ProcessRunner? processRunner,
ffi.Abi? abi,
required io.Directory engineSrcDir,
required this.task,
bool dryRun = false,
}) : super(
platform ?? const LocalPlatform(),
processRunner ?? ProcessRunner(),
abi ?? ffi.Abi.current(),
engineSrcDir,
dryRun,
);
Expand Down Expand Up @@ -571,13 +586,15 @@ final class BuildTestRunner extends Runner {
BuildTestRunner({
Platform? platform,
ProcessRunner? processRunner,
ffi.Abi? abi,
required io.Directory engineSrcDir,
required this.test,
this.extraTestArgs = const <String>[],
bool dryRun = false,
}) : super(
platform ?? const LocalPlatform(),
processRunner ?? ProcessRunner(),
abi ?? ffi.Abi.current(),
engineSrcDir,
dryRun,
);
Expand Down
51 changes: 41 additions & 10 deletions tools/pkg/engine_build_configs/test/build_config_runner_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

import 'dart:convert' as convert;
import 'dart:ffi' as ffi;
import 'dart:io' as io;

import 'package:engine_build_configs/src/build_config.dart';
Expand Down Expand Up @@ -39,6 +40,7 @@ void main() {
// dryRun should not try to spawn any processes.
processManager: _fakeProcessManager(),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
task: generator,
dryRun: true,
Expand All @@ -65,6 +67,7 @@ void main() {
// dryRun should not try to spawn any processes.
processManager: _fakeProcessManager(),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
test: test,
dryRun: true,
Expand Down Expand Up @@ -93,6 +96,7 @@ void main() {
// dryRun should not try to spawn any processes.
processManager: _fakeProcessManager(),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
build: targetBuild,
dryRun: true,
Expand Down Expand Up @@ -154,6 +158,7 @@ void main() {
// dryRun should not try to spawn any processes.
processManager: _fakeProcessManager(),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
build: targetBuild,
extraGnArgs: <String>['--extra-gn-arg'],
Expand Down Expand Up @@ -193,6 +198,7 @@ void main() {
// dryRun should not try to spawn any processes.
processManager: _fakeProcessManager(),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
build: targetBuild,
extraGnArgs: <String>['--goma'],
Expand All @@ -218,10 +224,9 @@ void main() {
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
platform: FakePlatform(operatingSystem: Platform.linux),
processRunner: ProcessRunner(
processManager: _fakeProcessManager(
unameResult: io.ProcessResult(1, 0, 'arm64', ''),
),
processManager: _fakeProcessManager(),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
build: targetBuild,
extraGnArgs: <String>['--rbe'],
Expand Down Expand Up @@ -263,6 +268,7 @@ void main() {
// dryRun should not try to spawn any processes.
processManager: _fakeProcessManager(),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
build: targetBuild,
runGn: false,
Expand Down Expand Up @@ -297,6 +303,7 @@ void main() {
// dryRun should not try to spawn any processes.
processManager: _fakeProcessManager(),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
build: targetBuild,
runNinja: false,
Expand Down Expand Up @@ -338,6 +345,7 @@ void main() {
// dryRun should not try to spawn any processes.
processManager: _fakeProcessManager(),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
build: targetBuild,
runGenerators: false,
Expand Down Expand Up @@ -381,6 +389,7 @@ void main() {
// dryRun should not try to spawn any processes.
processManager: _fakeProcessManager(),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
build: targetBuild,
runTests: false,
Expand Down Expand Up @@ -409,10 +418,9 @@ void main() {
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
platform: FakePlatform(operatingSystem: Platform.linux),
processRunner: ProcessRunner(
processManager: _fakeProcessManager(
unameResult: io.ProcessResult(1, 0, 'arm64', ''),
),
processManager: _fakeProcessManager(),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
build: targetBuild,
extraGnArgs: <String>['--no-lto', '--no-goma', '--rbe'],
Expand Down Expand Up @@ -448,6 +456,7 @@ void main() {
// dryRun should not try to spawn any processes.
processManager: _fakeProcessManager(),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
build: targetBuild,
dryRun: true,
Expand All @@ -469,6 +478,7 @@ void main() {
gnResult: io.ProcessResult(1, 1, '', ''),
),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
build: targetBuild,
);
Expand All @@ -495,6 +505,7 @@ void main() {
ninjaResult: io.ProcessResult(1, 1, '', ''),
),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
build: targetBuild,
);
Expand All @@ -518,10 +529,10 @@ void main() {
platform: FakePlatform(operatingSystem: Platform.linux),
processRunner: ProcessRunner(
processManager: _fakeProcessManager(
unameResult: io.ProcessResult(1, 0, 'arm64', ''),
bootstrapResult: io.ProcessResult(1, 1, '', ''),
),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
build: targetBuild,
extraGnArgs: <String>['--rbe'],
Expand All @@ -547,7 +558,6 @@ void main() {
platform: FakePlatform(operatingSystem: Platform.linux),
processRunner: ProcessRunner(
processManager: _fakeProcessManager(
unameResult: io.ProcessResult(1, 0, 'arm64', ''),
canRun: (Object? exe, {String? workingDirectory}) {
if (exe is String? && exe != null && exe.endsWith('bootstrap')) {
return false;
Expand All @@ -556,6 +566,7 @@ void main() {
},
),
),
abi: ffi.Abi.linuxX64,
engineSrcDir: engine.srcDir,
build: targetBuild,
extraGnArgs: <String>['--rbe'],
Expand All @@ -568,10 +579,31 @@ void main() {

expect(events[2] is RunnerError, isTrue);
});

test('GlobalBuildRunner throws a StateError on an unsupported host cpu', () async {
final GlobalBuild targetBuild = buildConfig.builds[0];
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
platform: FakePlatform(operatingSystem: Platform.linux),
processRunner: ProcessRunner(
processManager: _fakeProcessManager(),
),
abi: ffi.Abi.linuxRiscv32,
engineSrcDir: engine.srcDir,
build: targetBuild,
extraGnArgs: <String>['--rbe'],
);

bool caughtError = false;
try {
await buildRunner.run((RunnerEvent event) {});
} on StateError catch (_) {
caughtError = true;
}
expect(caughtError, isTrue);
});
}

FakeProcessManager _fakeProcessManager({
io.ProcessResult? unameResult,
io.ProcessResult? bootstrapResult,
io.ProcessResult? gnResult,
io.ProcessResult? ninjaResult,
Expand All @@ -587,7 +619,6 @@ FakeProcessManager _fakeProcessManager({
return FakeProcessManager(
canRun: canRun ?? (Object? exe, {String? workingDirectory}) => true,
onRun: (List<String> cmd) => switch (cmd) {
['uname', ...] => unameResult ?? success,
_ => failUnknown ? io.ProcessResult(1, 1, '', '') : success,
},
onStart: (List<String> cmd) => switch (cmd) {
Expand Down