mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
[flutter_tools] quality pass on Linux build (#55556)
- Update the Linux build to support most of the build configuration, though like windows most only make sense for profile/release. - Ensure VERBOSE_SCRIPT_LOGGING is set when the logger is verbose - Automatically run pub get like other build commands
This commit is contained in:
parent
d72eea539e
commit
dd88b20435
@ -116,6 +116,29 @@ class BuildInfo {
|
||||
bool get supportsSimulator => isEmulatorBuildMode(mode);
|
||||
String get modeName => getModeName(mode);
|
||||
String get friendlyModeName => getFriendlyModeName(mode);
|
||||
|
||||
/// Convert to a structued string encoded structure appropriate for usage as
|
||||
/// environment variables or to embed in other scripts.
|
||||
///
|
||||
/// Fields that are `null` are excluded from this configration.
|
||||
Map<String, String> toEnvironmentConfig() {
|
||||
return <String, String>{
|
||||
if (dartDefines?.isNotEmpty ?? false)
|
||||
'DART_DEFINES': dartDefines.join(','),
|
||||
if (dartObfuscation != null)
|
||||
'DART_OBFUSCATION': dartObfuscation.toString(),
|
||||
if (extraFrontEndOptions?.isNotEmpty ?? false)
|
||||
'EXTRA_FRONT_END_OPTIONS': extraFrontEndOptions.join(','),
|
||||
if (extraGenSnapshotOptions?.isNotEmpty ?? false)
|
||||
'EXTRA_GEN_SNAPSHOT_OPTIONS': extraGenSnapshotOptions.join(','),
|
||||
if (splitDebugInfoPath != null)
|
||||
'SPLIT_DEBUG_INFO': splitDebugInfoPath,
|
||||
if (trackWidgetCreation != null)
|
||||
'TRACK_WIDGET_CREATION': trackWidgetCreation.toString(),
|
||||
if (treeShakeIcons != null)
|
||||
'TREE_SHAKE_ICONS': treeShakeIcons.toString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about an Android build to be performed or used.
|
||||
|
@ -34,7 +34,7 @@ class BuildCommand extends FlutterCommand {
|
||||
addSubcommand(BuildBundleCommand(verboseHelp: verboseHelp));
|
||||
addSubcommand(BuildWebCommand(verboseHelp: verboseHelp));
|
||||
addSubcommand(BuildMacosCommand(verboseHelp: verboseHelp));
|
||||
addSubcommand(BuildLinuxCommand());
|
||||
addSubcommand(BuildLinuxCommand(verboseHelp: verboseHelp));
|
||||
addSubcommand(BuildWindowsCommand(verboseHelp: verboseHelp));
|
||||
addSubcommand(BuildFuchsiaCommand(verboseHelp: verboseHelp));
|
||||
}
|
||||
|
@ -16,10 +16,17 @@ import 'build.dart';
|
||||
|
||||
/// A command to build a linux desktop target through a build shell script.
|
||||
class BuildLinuxCommand extends BuildSubCommand {
|
||||
BuildLinuxCommand() {
|
||||
BuildLinuxCommand({ bool verboseHelp = false }) {
|
||||
addTreeShakeIconsFlag();
|
||||
addBuildModeFlags();
|
||||
usesTargetOption();
|
||||
addBuildModeFlags(verboseHelp: verboseHelp);
|
||||
usesPubOption();
|
||||
addSplitDebugInfoOption();
|
||||
addDartObfuscationOption();
|
||||
usesDartDefineOption();
|
||||
usesExtraFrontendOptions();
|
||||
addEnableExperimentation(hide: !verboseHelp);
|
||||
usesTrackWidgetCreation(verboseHelp: verboseHelp);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -14,7 +14,11 @@ import '../plugins.dart';
|
||||
import '../project.dart';
|
||||
|
||||
/// Builds the Linux project through the Makefile.
|
||||
Future<void> buildLinux(LinuxProject linuxProject, BuildInfo buildInfo, {String target = 'lib/main.dart'}) async {
|
||||
Future<void> buildLinux(
|
||||
LinuxProject linuxProject,
|
||||
BuildInfo buildInfo, {
|
||||
String target = 'lib/main.dart',
|
||||
}) async {
|
||||
if (!linuxProject.makeFile.existsSync()) {
|
||||
throwToolExit('No Linux desktop project configured. See '
|
||||
'https://github.com/flutter/flutter/wiki/Desktop-shells#create '
|
||||
@ -38,10 +42,15 @@ Future<void> buildLinux(LinuxProject linuxProject, BuildInfo buildInfo, {String
|
||||
final StringBuffer buffer = StringBuffer('''
|
||||
# Generated code do not commit.
|
||||
export FLUTTER_ROOT=${Cache.flutterRoot}
|
||||
export TRACK_WIDGET_CREATION=${buildInfo?.trackWidgetCreation == true}
|
||||
export FLUTTER_TARGET=$target
|
||||
export PROJECT_DIR=${linuxProject.project.directory.path}
|
||||
''');
|
||||
final Map<String, String> environmentConfig = buildInfo.toEnvironmentConfig();
|
||||
for (final String key in environmentConfig.keys) {
|
||||
final String value = environmentConfig[key];
|
||||
buffer.writeln('export $key=$value');
|
||||
}
|
||||
|
||||
if (globals.artifacts is LocalEngineArtifacts) {
|
||||
final LocalEngineArtifacts localEngineArtifacts = globals.artifacts as LocalEngineArtifacts;
|
||||
final String engineOutPath = localEngineArtifacts.engineOutPath;
|
||||
@ -73,12 +82,18 @@ export PROJECT_DIR=${linuxProject.project.directory.path}
|
||||
);
|
||||
int result;
|
||||
try {
|
||||
result = await processUtils.stream(<String>[
|
||||
'make',
|
||||
'-C',
|
||||
linuxProject.makeFile.parent.path,
|
||||
'BUILD=$buildFlag',
|
||||
], trace: true);
|
||||
result = await processUtils.stream(
|
||||
<String>[
|
||||
'make',
|
||||
'-C',
|
||||
linuxProject.makeFile.parent.path,
|
||||
'BUILD=$buildFlag',
|
||||
],
|
||||
environment: <String, String>{
|
||||
if (globals.logger.isVerbose)
|
||||
'VERBOSE_SCRIPT_LOGGING': 'true'
|
||||
}, trace: true,
|
||||
);
|
||||
} on ArgumentError {
|
||||
throwToolExit("make not found. Run 'flutter doctor' for more information.");
|
||||
} finally {
|
||||
|
@ -119,22 +119,9 @@ void _writeGeneratedFlutterProperties(
|
||||
'FLUTTER_ROOT': Cache.flutterRoot,
|
||||
'FLUTTER_EPHEMERAL_DIR': windowsProject.ephemeralDirectory.path,
|
||||
'PROJECT_DIR': windowsProject.project.directory.path,
|
||||
if (buildInfo.trackWidgetCreation != null)
|
||||
'TRACK_WIDGET_CREATION': buildInfo.trackWidgetCreation.toString(),
|
||||
if (buildInfo.treeShakeIcons != null)
|
||||
'TREE_SHAKE_ICONS': buildInfo.treeShakeIcons.toString(),
|
||||
if (buildInfo.extraGenSnapshotOptions?.isNotEmpty ?? false)
|
||||
'EXTRA_GEN_SNAPSHOT_OPTIONS': buildInfo.extraGenSnapshotOptions.join(','),
|
||||
if (buildInfo.extraFrontEndOptions?.isNotEmpty ?? false)
|
||||
'EXTRA_FRONT_END_OPTIONS': buildInfo.extraFrontEndOptions.join(','),
|
||||
if (buildInfo.dartDefines?.isNotEmpty ?? false)
|
||||
'DART_DEFINES': buildInfo.dartDefines.join(','),
|
||||
if (buildInfo.dartObfuscation != null)
|
||||
'DART_OBFUSCATION': buildInfo.dartObfuscation.toString(),
|
||||
if (buildInfo.splitDebugInfoPath != null)
|
||||
'SPLIT_DEBUG_INFO': buildInfo.splitDebugInfoPath,
|
||||
if (target != null)
|
||||
'FLUTTER_TARGET': target,
|
||||
...buildInfo.toEnvironmentConfig(),
|
||||
};
|
||||
if (globals.artifacts is LocalEngineArtifacts) {
|
||||
final LocalEngineArtifacts localEngineArtifacts = globals.artifacts as LocalEngineArtifacts;
|
||||
|
@ -87,7 +87,7 @@ void main() {
|
||||
setUpMockCoreProjectFiles();
|
||||
|
||||
expect(createTestCommandRunner(command).run(
|
||||
const <String>['build', 'linux']
|
||||
const <String>['build', 'linux', '--no-pub']
|
||||
), throwsToolExit(message: 'No Linux desktop project configured'));
|
||||
}, overrides: <Type, Generator>{
|
||||
Platform: () => linuxPlatform,
|
||||
@ -101,7 +101,7 @@ void main() {
|
||||
setUpMockProjectFilesForBuild();
|
||||
|
||||
expect(createTestCommandRunner(command).run(
|
||||
const <String>['build', 'linux']
|
||||
const <String>['build', 'linux', '--no-pub']
|
||||
), throwsToolExit());
|
||||
}, overrides: <Type, Generator>{
|
||||
Platform: () => notLinuxPlatform,
|
||||
@ -115,7 +115,7 @@ void main() {
|
||||
setUpMockProjectFilesForBuild(templateVersion: 1);
|
||||
|
||||
expect(createTestCommandRunner(command).run(
|
||||
const <String>['build', 'linux']
|
||||
const <String>['build', 'linux', '--no-pub']
|
||||
), throwsToolExit(message: 'flutter create .'));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
@ -129,7 +129,7 @@ void main() {
|
||||
setUpMockProjectFilesForBuild(templateVersion: 999);
|
||||
|
||||
expect(createTestCommandRunner(command).run(
|
||||
const <String>['build', 'linux']
|
||||
const <String>['build', 'linux', '--no-pub']
|
||||
), throwsToolExit(message: 'Upgrade Flutter'));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
@ -146,15 +146,13 @@ void main() {
|
||||
'-C',
|
||||
'/linux',
|
||||
'BUILD=release',
|
||||
], onRun: () {
|
||||
|
||||
})
|
||||
], onRun: () { })
|
||||
]);
|
||||
|
||||
setUpMockProjectFilesForBuild();
|
||||
|
||||
await createTestCommandRunner(command).run(
|
||||
const <String>['build', 'linux']
|
||||
const <String>['build', 'linux', '--no-pub']
|
||||
);
|
||||
expect(fileSystem.file('linux/flutter/ephemeral/generated_config.mk'), exists);
|
||||
}, overrides: <Type, Generator>{
|
||||
@ -179,7 +177,7 @@ void main() {
|
||||
]);
|
||||
|
||||
expect(createTestCommandRunner(command).run(
|
||||
const <String>['build', 'linux']
|
||||
const <String>['build', 'linux', '--no-pub']
|
||||
), throwsToolExit(message: "make not found. Run 'flutter doctor' for more information."));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
@ -201,7 +199,7 @@ void main() {
|
||||
]);
|
||||
|
||||
await createTestCommandRunner(command).run(
|
||||
const <String>['build', 'linux', '--debug']
|
||||
const <String>['build', 'linux', '--debug', '--no-pub']
|
||||
);
|
||||
expect(testLogger.statusText, isNot(contains('STDOUT STUFF')));
|
||||
expect(testLogger.traceText, contains('STDOUT STUFF'));
|
||||
@ -212,6 +210,36 @@ void main() {
|
||||
FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true),
|
||||
});
|
||||
|
||||
testUsingContext('Linux verbose build sets VERBOSE_SCRIPT_LOGGING', () async {
|
||||
final BuildCommand command = BuildCommand();
|
||||
setUpMockProjectFilesForBuild();
|
||||
processManager = FakeProcessManager.list(<FakeCommand>[
|
||||
const FakeCommand(
|
||||
command: <String>[
|
||||
'make',
|
||||
'-C',
|
||||
'/linux',
|
||||
'BUILD=debug',
|
||||
],
|
||||
environment: <String, String>{
|
||||
'VERBOSE_SCRIPT_LOGGING': 'true'
|
||||
},
|
||||
stdout: 'STDOUT STUFF',
|
||||
),
|
||||
]);
|
||||
|
||||
await createTestCommandRunner(command).run(
|
||||
const <String>['build', 'linux', '--debug', '-v', '--no-pub']
|
||||
);
|
||||
expect(testLogger.statusText, contains('STDOUT STUFF'));
|
||||
expect(testLogger.traceText, isNot(contains('STDOUT STUFF')));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => processManager,
|
||||
Platform: () => linuxPlatform,
|
||||
FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true),
|
||||
});
|
||||
|
||||
testUsingContext('Linux build --debug passes debug mode to make', () async {
|
||||
final BuildCommand command = BuildCommand();
|
||||
setUpMockProjectFilesForBuild();
|
||||
@ -226,7 +254,7 @@ void main() {
|
||||
|
||||
|
||||
await createTestCommandRunner(command).run(
|
||||
const <String>['build', 'linux', '--debug']
|
||||
const <String>['build', 'linux', '--debug', '--no-pub']
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
@ -248,7 +276,7 @@ void main() {
|
||||
]);
|
||||
|
||||
await createTestCommandRunner(command).run(
|
||||
const <String>['build', 'linux', '--profile']
|
||||
const <String>['build', 'linux', '--profile', '--no-pub']
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
@ -257,6 +285,64 @@ void main() {
|
||||
FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true),
|
||||
});
|
||||
|
||||
testUsingContext('Linux build configures Makefile exports', () async {
|
||||
final BuildCommand command = BuildCommand();
|
||||
setUpMockProjectFilesForBuild();
|
||||
processManager = FakeProcessManager.list(<FakeCommand>[
|
||||
const FakeCommand(command: <String>[
|
||||
'make',
|
||||
'-C',
|
||||
'/linux',
|
||||
'BUILD=release',
|
||||
]),
|
||||
]);
|
||||
fileSystem.file('lib/other.dart')
|
||||
.createSync(recursive: true);
|
||||
|
||||
await createTestCommandRunner(command).run(
|
||||
const <String>[
|
||||
'build',
|
||||
'linux',
|
||||
'--target=lib/other.dart',
|
||||
'--no-pub',
|
||||
'--track-widget-creation',
|
||||
'--split-debug-info=foo/',
|
||||
'--enable-experiment=non-nullable',
|
||||
'--obfuscate',
|
||||
'--dart-define=foo.bar=2',
|
||||
'--dart-define=fizz.far=3',
|
||||
'--tree-shake-icons',
|
||||
]
|
||||
);
|
||||
|
||||
final File makeConfig = fileSystem.currentDirectory
|
||||
.childDirectory('linux')
|
||||
.childDirectory('flutter')
|
||||
.childDirectory('ephemeral')
|
||||
.childFile('generated_config.mk');
|
||||
|
||||
expect(makeConfig, exists);
|
||||
|
||||
final List<String> configLines = makeConfig.readAsLinesSync();
|
||||
|
||||
expect(configLines, containsAll(<String>[
|
||||
'export DART_DEFINES=foo.bar=2,fizz.far=3',
|
||||
'export DART_OBFUSCATION=true',
|
||||
'export EXTRA_FRONT_END_OPTIONS=--enable-experiment=non-nullable',
|
||||
'export EXTRA_GEN_SNAPSHOT_OPTIONS=--enable-experiment=non-nullable',
|
||||
'export SPLIT_DEBUG_INFO=foo/',
|
||||
'export TRACK_WIDGET_CREATION=true',
|
||||
'export TREE_SHAKE_ICONS=true',
|
||||
'export FLUTTER_ROOT=$_kTestFlutterRoot',
|
||||
'export FLUTTER_TARGET=lib/other.dart',
|
||||
]));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => processManager,
|
||||
Platform: () => linuxPlatform,
|
||||
FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true),
|
||||
});
|
||||
|
||||
testUsingContext('linux can extract binary name from Makefile', () async {
|
||||
fileSystem.file('linux/Makefile')
|
||||
..createSync(recursive: true)
|
||||
@ -305,7 +391,7 @@ BINARY_NAME=fizz_bar
|
||||
testUsingContext('Refuses to build for Linux when feature is disabled', () {
|
||||
final CommandRunner<void> runner = createTestCommandRunner(BuildCommand());
|
||||
|
||||
expect(() => runner.run(<String>['build', 'linux']),
|
||||
expect(() => runner.run(<String>['build', 'linux', '--no-pub']),
|
||||
throwsToolExit());
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: false),
|
||||
@ -324,7 +410,7 @@ BINARY_NAME=fizz_bar
|
||||
]);
|
||||
|
||||
await createTestCommandRunner(command).run(
|
||||
const <String>['build', 'linux']
|
||||
const <String>['build', 'linux', '--no-pub']
|
||||
);
|
||||
expect(testLogger.statusText, contains('🚧'));
|
||||
}, overrides: <Type, Generator>{
|
||||
|
@ -93,4 +93,26 @@ void main() {
|
||||
expect(getIOSArchForName('x86_64'), DarwinArch.x86_64);
|
||||
expect(() => getIOSArchForName('bogus'), throwsException);
|
||||
});
|
||||
|
||||
test('toEnvironmentConfig encoding of standard values', () {
|
||||
const BuildInfo buildInfo = BuildInfo(BuildMode.debug, '',
|
||||
treeShakeIcons: true,
|
||||
trackWidgetCreation: true,
|
||||
dartDefines: <String>['foo=2', 'bar=2'],
|
||||
dartObfuscation: true,
|
||||
splitDebugInfoPath: 'foo/',
|
||||
extraFrontEndOptions: <String>['--enable-experiment=non-nullable', 'bar'],
|
||||
extraGenSnapshotOptions: <String>['--enable-experiment=non-nullable', 'fizz'],
|
||||
);
|
||||
|
||||
expect(buildInfo.toEnvironmentConfig(), <String, String>{
|
||||
'TREE_SHAKE_ICONS': 'true',
|
||||
'TRACK_WIDGET_CREATION': 'true',
|
||||
'DART_DEFINES': 'foo=2,bar=2',
|
||||
'DART_OBFUSCATION': 'true',
|
||||
'SPLIT_DEBUG_INFO': 'foo/',
|
||||
'EXTRA_FRONT_END_OPTIONS': '--enable-experiment=non-nullable,bar',
|
||||
'EXTRA_GEN_SNAPSHOT_OPTIONS': '--enable-experiment=non-nullable,fizz',
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user