Skip to content

Commit

Permalink
[engine_build_configs] Use dart:ffi Abi to determine the host cpu (fl…
Browse files Browse the repository at this point in the history
  • Loading branch information
zanderso authored Feb 13, 2024
1 parent 400f156 commit 933b97a
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 24 deletions.
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

0 comments on commit 933b97a

Please sign in to comment.