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

Commit 1c488c7

Browse files
authored
Add and use mergeGnArgs with --gn-args from et. (#56228)
Closes flutter/flutter#156909. This PR adds (and implements) the `--gn-args` (extra command-line GN args) functionality by generalizing on the concept of "merged" GN args that @zanderso had special-cased for `--lto` and `--rbe`, and further testing it. There is also a logical place for us to expand support of merged arguments at a future point in time.
1 parent 9295eeb commit 1c488c7

File tree

7 files changed

+543
-39
lines changed

7 files changed

+543
-39
lines changed

tools/engine_tool/lib/src/build_plan.dart

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const _flagConcurrency = 'concurrency';
1616
const _flagStrategy = 'build-strategy';
1717
const _flagRbe = 'rbe';
1818
const _flagLto = 'lto';
19+
const _flagExtraGnArgs = 'gn-args';
1920

2021
/// Describes what (platform, targets) and how (strategy, options) to build.
2122
///
@@ -75,6 +76,11 @@ final class BuildPlan {
7576
}
7677
throw FatalError('Invalid value for --$_flagConcurrency: $value');
7778
}(),
79+
extraGnArgs: () {
80+
final value = args.multiOption(_flagExtraGnArgs);
81+
_checkExtraGnArgs(value);
82+
return value;
83+
}(),
7884
);
7985
}
8086

@@ -84,14 +90,63 @@ final class BuildPlan {
8490
required this.useRbe,
8591
required this.useLto,
8692
required this.concurrency,
87-
}) {
93+
required Iterable<String> extraGnArgs,
94+
}) : extraGnArgs = List.unmodifiable(extraGnArgs) {
8895
if (!useRbe && strategy == BuildStrategy.remote) {
8996
throw FatalError(
9097
'Cannot use remote builds without RBE enabled.\n\n$_rbeInstructions',
9198
);
9299
}
93100
}
94101

102+
/// Arguments that cannot be provided to [BuildPlan.extraGnArgs].
103+
///
104+
/// Instead, provide them explicitly as other [BuildPlan] arguments.
105+
@visibleForTesting
106+
static const reservedGnArgs = {
107+
_flagRbe,
108+
_flagLto,
109+
'no-$_flagRbe',
110+
'no-$_flagLto',
111+
// If we are to expand this list to include flags that are not a 1:1 mapping
112+
// - for example we want to reserve "--foo-bar" but it's called "--use-baz"
113+
// in "et", let's (a) re-think having these arguments named differently and
114+
// (b) if necessary, consider changing this set to a map instead so a clear
115+
// error can be presented below.
116+
};
117+
118+
/// Error thrown when [reservedGnArgs] are used as [extraGnArgs].
119+
@visibleForTesting
120+
static final reservedGnArgsError = FatalError(
121+
'Flags such as ${reservedGnArgs.join(', ')} should be specified as '
122+
'direct arguments to "et" and not using "--gn-args". For example, '
123+
'`et build --no-lto` instead of `et build --gn-args="--no-lto"`.',
124+
);
125+
126+
/// Error thrown when a non-flag argument is provided as [extraGnArgs].
127+
@visibleForTesting
128+
static final argumentsMustBeFlagsError = FatalError(
129+
'Arguments provided to --gn-args must be flags (booleans) and be '
130+
'specified as either in the format "--flag" or "--no-flag". Options '
131+
'that are not flags or are abberviated ("-F") are not currently '
132+
'supported; consider filing a request: '
133+
'https://fluter.dev/to/engine-tool-bug.',
134+
);
135+
136+
static void _checkExtraGnArgs(Iterable<String> gnArgs) {
137+
for (final arg in gnArgs) {
138+
if (!arg.startsWith('--') || arg.contains('=') || arg.contains(' ')) {
139+
throw argumentsMustBeFlagsError;
140+
}
141+
142+
// Strip off the prefix and compare it to reserved flags.
143+
final withoutPrefix = arg.replaceFirst('--', '');
144+
if (reservedGnArgs.contains(withoutPrefix)) {
145+
throw reservedGnArgsError;
146+
}
147+
}
148+
}
149+
95150
static String _defaultHostDebug() {
96151
return 'host_debug';
97152
}
@@ -175,6 +230,18 @@ final class BuildPlan {
175230
help: 'How many jobs to run in parallel.',
176231
);
177232

233+
// Add --gn-args.
234+
parser.addMultiOption(
235+
_flagExtraGnArgs,
236+
help: ''
237+
'Additional arguments to provide to "gn".\n'
238+
'GN arguments change the parameters of the compiler and invalidate '
239+
'the current build, and should be used sparingly. If there is an '
240+
'engine build that should be reused and tested on CI prefer adding '
241+
'the arguments to "//flutter/ci/builders/local_engine.json".',
242+
hide: !environment.verbose,
243+
);
244+
178245
return builds;
179246
}
180247

@@ -201,19 +268,34 @@ final class BuildPlan {
201268
/// Whether to build with LTO (link-time optimization).
202269
final bool useLto;
203270

271+
/// Additional GN arguments to use for a build.
272+
///
273+
/// By contract, these arguments are always strictly _flags_ (not options),
274+
/// and specified as either `--flag`, `-F`, or as the negative variant (such
275+
/// as `--no-flag`).
276+
final List<String> extraGnArgs;
277+
204278
@override
205279
bool operator ==(Object other) {
206280
return other is BuildPlan &&
207281
build.name == other.build.name &&
208282
strategy == other.strategy &&
209283
useRbe == other.useRbe &&
210284
useLto == other.useLto &&
211-
concurrency == other.concurrency;
285+
concurrency == other.concurrency &&
286+
const ListEquality<Object?>().equals(extraGnArgs, other.extraGnArgs);
212287
}
213288

214289
@override
215290
int get hashCode {
216-
return Object.hash(build.name, strategy, useRbe, useLto, concurrency);
291+
return Object.hash(
292+
build.name,
293+
strategy,
294+
useRbe,
295+
useLto,
296+
concurrency,
297+
Object.hashAll(extraGnArgs),
298+
);
217299
}
218300

219301
/// Converts this build plan to its equivalent [RbeConfig].
@@ -236,6 +318,7 @@ final class BuildPlan {
236318
return [
237319
if (!useRbe) '--no-rbe',
238320
if (useLto) '--lto' else '--no-lto',
321+
...extraGnArgs,
239322
];
240323
}
241324

@@ -248,6 +331,7 @@ final class BuildPlan {
248331
buffer.writeln(' useRbe: $useRbe');
249332
buffer.writeln(' strategy: $strategy');
250333
buffer.writeln(' concurrency: $concurrency');
334+
buffer.writeln(' extraGnArgs: $extraGnArgs');
251335
buffer.write('>');
252336
return buffer.toString();
253337
}

tools/engine_tool/lib/src/logger.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ class FlutterSpinner extends Spinner {
367367
}
368368

369369
/// FatalErrors are thrown when a fatal error has occurred.
370-
class FatalError extends Error {
370+
final class FatalError extends Error {
371371
/// Constructs a FatalError with a message.
372372
FatalError(this._message);
373373

0 commit comments

Comments
 (0)