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

Commit 933b97a

Browse files
authored
[engine_build_configs] Use dart:ffi Abi to determine the host cpu (#50604)
Follow-up on #50543 (comment)
1 parent 400f156 commit 933b97a

File tree

3 files changed

+74
-24
lines changed

3 files changed

+74
-24
lines changed

tools/pkg/engine_build_configs/bin/run.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'dart:ffi' as ffi;
56
import 'dart:io' as io;
67

78
import 'package:engine_build_configs/engine_build_configs.dart';
@@ -119,6 +120,7 @@ The build names are the "name" fields of the maps in the list of "builds".
119120
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
120121
platform: const LocalPlatform(),
121122
processRunner: ProcessRunner(),
123+
abi: ffi.Abi.current(),
122124
engineSrcDir: engine.srcDir,
123125
build: targetBuild,
124126
extraGnArgs: extraGnArgs,

tools/pkg/engine_build_configs/lib/src/build_config_runner.dart

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
import 'dart:async';
66
import 'dart:convert';
7-
import 'dart:io' as io show Directory, Process, ProcessResult;
7+
import 'dart:ffi' as ffi;
8+
import 'dart:io' as io show Directory, Process;
89

910
import 'package:path/path.dart' as p;
1011
import 'package:platform/platform.dart';
@@ -111,14 +112,23 @@ typedef RunnerEventHandler = void Function(RunnerEvent);
111112
/// An abstract base clase for running the various tasks that a build config
112113
/// specifies. Derived classes implement the `run()` method.
113114
sealed class Runner {
114-
Runner(this.platform, this.processRunner, this.engineSrcDir, this.dryRun);
115+
Runner(
116+
this.platform,
117+
this.processRunner,
118+
this.abi,
119+
this.engineSrcDir,
120+
this.dryRun,
121+
);
115122

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

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

129+
/// The [Abi] of the host platform.
130+
final ffi.Abi abi;
131+
122132
/// The src/ directory of the engine checkout.
123133
final io.Directory engineSrcDir;
124134

@@ -162,6 +172,7 @@ final class GlobalBuildRunner extends Runner {
162172
GlobalBuildRunner({
163173
Platform? platform,
164174
ProcessRunner? processRunner,
175+
ffi.Abi? abi,
165176
required io.Directory engineSrcDir,
166177
required this.build,
167178
this.extraGnArgs = const <String>[],
@@ -175,6 +186,7 @@ final class GlobalBuildRunner extends Runner {
175186
}) : super(
176187
platform ?? const LocalPlatform(),
177188
processRunner ?? ProcessRunner(),
189+
abi ?? ffi.Abi.current(),
178190
engineSrcDir,
179191
dryRun,
180192
);
@@ -289,22 +301,20 @@ final class GlobalBuildRunner extends Runner {
289301
}
290302

291303
late final String _hostCpu = (){
292-
if (platform.isWindows) {
293-
return platform.environment['PROCESSOR_ARCHITECTURE'] ?? 'x64';
294-
}
295-
final List<String> unameCommand = <String>['uname', '-m'];
296-
final io.ProcessResult unameResult = processRunner.processManager.runSync(
297-
unameCommand,
298-
);
299-
return unameResult.exitCode == 0 ? (unameResult.stdout as String).trim() : 'x64';
304+
return switch (abi) {
305+
ffi.Abi.linuxArm64 || ffi.Abi.macosArm64 || ffi.Abi.windowsArm64 => 'arm64',
306+
ffi.Abi.linuxX64 || ffi.Abi.macosX64 || ffi.Abi.windowsX64 => 'x64',
307+
_ => throw StateError('This host platform "$abi" is not supported.'),
308+
};
300309
}();
301310

302311
late final String _buildtoolsPath = (){
303-
final String platformDir = switch (platform.operatingSystem) {
312+
final String os = platform.operatingSystem;
313+
final String platformDir = switch (os) {
304314
Platform.linux => 'linux-$_hostCpu',
305315
Platform.macOS => 'mac-$_hostCpu',
306316
Platform.windows => 'windows-$_hostCpu',
307-
_ => '<unknown>',
317+
_ => throw StateError('This host OS "$os" is not supported.'),
308318
};
309319
return p.join(engineSrcDir.path, 'buildtools', platformDir);
310320
}();
@@ -317,11 +327,12 @@ final class GlobalBuildRunner extends Runner {
317327
final String exe = platform.isWindows ? '.exe' : '';
318328
final String bootstrapPath = p.join(reclientPath, 'bootstrap$exe');
319329
final String reproxyPath = p.join(reclientPath, 'reproxy$exe');
320-
final String reclientConfigFile = switch (platform.operatingSystem) {
330+
final String os = platform.operatingSystem;
331+
final String reclientConfigFile = switch (os) {
321332
Platform.linux => 'reclient-linux.cfg',
322333
Platform.macOS => 'reclient-mac.cfg',
323334
Platform.windows => 'reclient-win.cfg',
324-
_ => '<unknown>',
335+
_ => throw StateError('This host OS "$os" is not supported.'),
325336
};
326337
final String reclientConfigPath = p.join(
327338
engineSrcDir.path, 'flutter', 'build', 'rbe', reclientConfigFile,
@@ -487,6 +498,7 @@ final class GlobalBuildRunner extends Runner {
487498
final BuildTaskRunner runner = BuildTaskRunner(
488499
processRunner: processRunner,
489500
platform: platform,
501+
abi: abi,
490502
engineSrcDir: engineSrcDir,
491503
task: task,
492504
dryRun: dryRun,
@@ -503,6 +515,7 @@ final class GlobalBuildRunner extends Runner {
503515
final BuildTestRunner runner = BuildTestRunner(
504516
processRunner: processRunner,
505517
platform: platform,
518+
abi: abi,
506519
engineSrcDir: engineSrcDir,
507520
test: test,
508521
extraTestArgs: extraTestArgs,
@@ -521,12 +534,14 @@ final class BuildTaskRunner extends Runner {
521534
BuildTaskRunner({
522535
Platform? platform,
523536
ProcessRunner? processRunner,
537+
ffi.Abi? abi,
524538
required io.Directory engineSrcDir,
525539
required this.task,
526540
bool dryRun = false,
527541
}) : super(
528542
platform ?? const LocalPlatform(),
529543
processRunner ?? ProcessRunner(),
544+
abi ?? ffi.Abi.current(),
530545
engineSrcDir,
531546
dryRun,
532547
);
@@ -571,13 +586,15 @@ final class BuildTestRunner extends Runner {
571586
BuildTestRunner({
572587
Platform? platform,
573588
ProcessRunner? processRunner,
589+
ffi.Abi? abi,
574590
required io.Directory engineSrcDir,
575591
required this.test,
576592
this.extraTestArgs = const <String>[],
577593
bool dryRun = false,
578594
}) : super(
579595
platform ?? const LocalPlatform(),
580596
processRunner ?? ProcessRunner(),
597+
abi ?? ffi.Abi.current(),
581598
engineSrcDir,
582599
dryRun,
583600
);

tools/pkg/engine_build_configs/test/build_config_runner_test.dart

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// found in the LICENSE file.
44

55
import 'dart:convert' as convert;
6+
import 'dart:ffi' as ffi;
67
import 'dart:io' as io;
78

89
import 'package:engine_build_configs/src/build_config.dart';
@@ -39,6 +40,7 @@ void main() {
3940
// dryRun should not try to spawn any processes.
4041
processManager: _fakeProcessManager(),
4142
),
43+
abi: ffi.Abi.linuxX64,
4244
engineSrcDir: engine.srcDir,
4345
task: generator,
4446
dryRun: true,
@@ -65,6 +67,7 @@ void main() {
6567
// dryRun should not try to spawn any processes.
6668
processManager: _fakeProcessManager(),
6769
),
70+
abi: ffi.Abi.linuxX64,
6871
engineSrcDir: engine.srcDir,
6972
test: test,
7073
dryRun: true,
@@ -93,6 +96,7 @@ void main() {
9396
// dryRun should not try to spawn any processes.
9497
processManager: _fakeProcessManager(),
9598
),
99+
abi: ffi.Abi.linuxX64,
96100
engineSrcDir: engine.srcDir,
97101
build: targetBuild,
98102
dryRun: true,
@@ -154,6 +158,7 @@ void main() {
154158
// dryRun should not try to spawn any processes.
155159
processManager: _fakeProcessManager(),
156160
),
161+
abi: ffi.Abi.linuxX64,
157162
engineSrcDir: engine.srcDir,
158163
build: targetBuild,
159164
extraGnArgs: <String>['--extra-gn-arg'],
@@ -193,6 +198,7 @@ void main() {
193198
// dryRun should not try to spawn any processes.
194199
processManager: _fakeProcessManager(),
195200
),
201+
abi: ffi.Abi.linuxX64,
196202
engineSrcDir: engine.srcDir,
197203
build: targetBuild,
198204
extraGnArgs: <String>['--goma'],
@@ -218,10 +224,9 @@ void main() {
218224
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
219225
platform: FakePlatform(operatingSystem: Platform.linux),
220226
processRunner: ProcessRunner(
221-
processManager: _fakeProcessManager(
222-
unameResult: io.ProcessResult(1, 0, 'arm64', ''),
223-
),
227+
processManager: _fakeProcessManager(),
224228
),
229+
abi: ffi.Abi.linuxX64,
225230
engineSrcDir: engine.srcDir,
226231
build: targetBuild,
227232
extraGnArgs: <String>['--rbe'],
@@ -263,6 +268,7 @@ void main() {
263268
// dryRun should not try to spawn any processes.
264269
processManager: _fakeProcessManager(),
265270
),
271+
abi: ffi.Abi.linuxX64,
266272
engineSrcDir: engine.srcDir,
267273
build: targetBuild,
268274
runGn: false,
@@ -297,6 +303,7 @@ void main() {
297303
// dryRun should not try to spawn any processes.
298304
processManager: _fakeProcessManager(),
299305
),
306+
abi: ffi.Abi.linuxX64,
300307
engineSrcDir: engine.srcDir,
301308
build: targetBuild,
302309
runNinja: false,
@@ -338,6 +345,7 @@ void main() {
338345
// dryRun should not try to spawn any processes.
339346
processManager: _fakeProcessManager(),
340347
),
348+
abi: ffi.Abi.linuxX64,
341349
engineSrcDir: engine.srcDir,
342350
build: targetBuild,
343351
runGenerators: false,
@@ -381,6 +389,7 @@ void main() {
381389
// dryRun should not try to spawn any processes.
382390
processManager: _fakeProcessManager(),
383391
),
392+
abi: ffi.Abi.linuxX64,
384393
engineSrcDir: engine.srcDir,
385394
build: targetBuild,
386395
runTests: false,
@@ -409,10 +418,9 @@ void main() {
409418
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
410419
platform: FakePlatform(operatingSystem: Platform.linux),
411420
processRunner: ProcessRunner(
412-
processManager: _fakeProcessManager(
413-
unameResult: io.ProcessResult(1, 0, 'arm64', ''),
414-
),
421+
processManager: _fakeProcessManager(),
415422
),
423+
abi: ffi.Abi.linuxX64,
416424
engineSrcDir: engine.srcDir,
417425
build: targetBuild,
418426
extraGnArgs: <String>['--no-lto', '--no-goma', '--rbe'],
@@ -448,6 +456,7 @@ void main() {
448456
// dryRun should not try to spawn any processes.
449457
processManager: _fakeProcessManager(),
450458
),
459+
abi: ffi.Abi.linuxX64,
451460
engineSrcDir: engine.srcDir,
452461
build: targetBuild,
453462
dryRun: true,
@@ -469,6 +478,7 @@ void main() {
469478
gnResult: io.ProcessResult(1, 1, '', ''),
470479
),
471480
),
481+
abi: ffi.Abi.linuxX64,
472482
engineSrcDir: engine.srcDir,
473483
build: targetBuild,
474484
);
@@ -495,6 +505,7 @@ void main() {
495505
ninjaResult: io.ProcessResult(1, 1, '', ''),
496506
),
497507
),
508+
abi: ffi.Abi.linuxX64,
498509
engineSrcDir: engine.srcDir,
499510
build: targetBuild,
500511
);
@@ -518,10 +529,10 @@ void main() {
518529
platform: FakePlatform(operatingSystem: Platform.linux),
519530
processRunner: ProcessRunner(
520531
processManager: _fakeProcessManager(
521-
unameResult: io.ProcessResult(1, 0, 'arm64', ''),
522532
bootstrapResult: io.ProcessResult(1, 1, '', ''),
523533
),
524534
),
535+
abi: ffi.Abi.linuxX64,
525536
engineSrcDir: engine.srcDir,
526537
build: targetBuild,
527538
extraGnArgs: <String>['--rbe'],
@@ -547,7 +558,6 @@ void main() {
547558
platform: FakePlatform(operatingSystem: Platform.linux),
548559
processRunner: ProcessRunner(
549560
processManager: _fakeProcessManager(
550-
unameResult: io.ProcessResult(1, 0, 'arm64', ''),
551561
canRun: (Object? exe, {String? workingDirectory}) {
552562
if (exe is String? && exe != null && exe.endsWith('bootstrap')) {
553563
return false;
@@ -556,6 +566,7 @@ void main() {
556566
},
557567
),
558568
),
569+
abi: ffi.Abi.linuxX64,
559570
engineSrcDir: engine.srcDir,
560571
build: targetBuild,
561572
extraGnArgs: <String>['--rbe'],
@@ -568,10 +579,31 @@ void main() {
568579

569580
expect(events[2] is RunnerError, isTrue);
570581
});
582+
583+
test('GlobalBuildRunner throws a StateError on an unsupported host cpu', () async {
584+
final GlobalBuild targetBuild = buildConfig.builds[0];
585+
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
586+
platform: FakePlatform(operatingSystem: Platform.linux),
587+
processRunner: ProcessRunner(
588+
processManager: _fakeProcessManager(),
589+
),
590+
abi: ffi.Abi.linuxRiscv32,
591+
engineSrcDir: engine.srcDir,
592+
build: targetBuild,
593+
extraGnArgs: <String>['--rbe'],
594+
);
595+
596+
bool caughtError = false;
597+
try {
598+
await buildRunner.run((RunnerEvent event) {});
599+
} on StateError catch (_) {
600+
caughtError = true;
601+
}
602+
expect(caughtError, isTrue);
603+
});
571604
}
572605

573606
FakeProcessManager _fakeProcessManager({
574-
io.ProcessResult? unameResult,
575607
io.ProcessResult? bootstrapResult,
576608
io.ProcessResult? gnResult,
577609
io.ProcessResult? ninjaResult,
@@ -587,7 +619,6 @@ FakeProcessManager _fakeProcessManager({
587619
return FakeProcessManager(
588620
canRun: canRun ?? (Object? exe, {String? workingDirectory}) => true,
589621
onRun: (List<String> cmd) => switch (cmd) {
590-
['uname', ...] => unameResult ?? success,
591622
_ => failUnknown ? io.ProcessResult(1, 1, '', '') : success,
592623
},
593624
onStart: (List<String> cmd) => switch (cmd) {

0 commit comments

Comments
 (0)