Revert "AOT support for Linux Desktop I: switch Linux builds to assemble (#41612)" (#42030)
This reverts commit 3024053c8295ad01dba952fe6ca007679296c2a4.
diff --git a/packages/flutter_tools/bin/tool_backend.dart b/packages/flutter_tools/bin/tool_backend.dart
index 64253a5..cb3c533 100644
--- a/packages/flutter_tools/bin/tool_backend.dart
+++ b/packages/flutter_tools/bin/tool_backend.dart
@@ -17,6 +17,7 @@
final String flutterEngine = Platform.environment['FLUTTER_ENGINE'];
final String localEngine = Platform.environment['LOCAL_ENGINE'];
final String flutterRoot = Platform.environment['FLUTTER_ROOT'];
+
Directory.current = projectDirectory;
if (localEngine != null && !localEngine.contains(buildMode)) {
@@ -32,34 +33,22 @@
''');
exit(1);
}
- final String flutterExecutable = path.join(
- flutterRoot, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter');
- if (targetPlatform == 'linux-x64') {
- // TODO(jonahwilliams): currently all builds are debug builds. Remove the
- // hardcoded mode when profile and release support is added.
- final ProcessResult unpackResult = await Process.run(
- flutterExecutable,
- <String>[
- '--suppress-analytics',
- '--verbose',
- if (flutterEngine != null) '--local-engine-src-path=$flutterEngine',
- if (localEngine != null) '--local-engine=$localEngine',
- 'assemble',
- '-dTargetPlatform=$targetPlatform',
- '-dBuildMode=debug',
- '-dTargetFile=$flutterTarget',
- '--output=build',
- 'debug_bundle_linux_assets',
- ]);
- if (unpackResult.exitCode != 0) {
- stderr.write(unpackResult.stderr);
+ String cacheDirectory;
+ switch (targetPlatform) {
+ case 'linux-x64':
+ cacheDirectory = 'linux/flutter/ephemeral';
+ break;
+ case 'windows-x64':
+ cacheDirectory = 'windows/flutter/ephemeral';
+ break;
+ default:
+ stderr.write('Unsupported target platform $targetPlatform');
exit(1);
- }
- return;
}
- const String cacheDirectory = 'windows/flutter/ephemeral';
+ final String flutterExecutable = path.join(
+ flutterRoot, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter');
final ProcessResult unpackResult = await Process.run(
flutterExecutable,
<String>[
diff --git a/packages/flutter_tools/lib/src/build_system/targets/linux.dart b/packages/flutter_tools/lib/src/build_system/targets/linux.dart
index 4821163..b57ab3b 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/linux.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/linux.dart
@@ -2,25 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'package:pool/pool.dart';
-
import '../../artifacts.dart';
-import '../../asset.dart';
import '../../base/file_system.dart';
import '../../build_info.dart';
-import '../../devfs.dart';
import '../../globals.dart';
import '../build_system.dart';
-import '../exceptions.dart';
-import 'assets.dart';
-import 'dart.dart';
/// Copies the Linux desktop embedding files to the copy directory.
-class UnpackLinuxDebug extends Target {
- const UnpackLinuxDebug();
+class UnpackLinux extends Target {
+ const UnpackLinux();
@override
- String get name => 'unpack_linux_debug';
+ String get name => 'unpack_linux';
@override
List<Source> get inputs => const <Source>[
@@ -30,12 +23,12 @@
@override
List<Source> get outputs => const <Source>[
- Source.pattern('{PROJECT_DIR}/linux/flutter/ephemeral/libflutter_linux_glfw.so'),
- Source.pattern('{PROJECT_DIR}/linux/flutter/ephemeral/flutter_export.h'),
- Source.pattern('{PROJECT_DIR}/linux/flutter/ephemeral/flutter_messenger.h'),
- Source.pattern('{PROJECT_DIR}/linux/flutter/ephemeral/flutter_plugin_registrar.h'),
- Source.pattern('{PROJECT_DIR}/linux/flutter/ephemeral/flutter_glfw.h'),
- Source.pattern('{PROJECT_DIR}/linux/flutter/ephemeral/icudtl.dat'),
+ Source.pattern('{PROJECT_DIR}/linux/flutter/libflutter_linux_glfw.so'),
+ Source.pattern('{PROJECT_DIR}/linux/flutter/flutter_export.h'),
+ Source.pattern('{PROJECT_DIR}/linux/flutter/flutter_messenger.h'),
+ Source.pattern('{PROJECT_DIR}/linux/flutter/flutter_plugin_registrar.h'),
+ Source.pattern('{PROJECT_DIR}/linux/flutter/flutter_glfw.h'),
+ Source.pattern('{PROJECT_DIR}/linux/flutter/icudtl.dat'),
];
@override
@@ -51,7 +44,6 @@
environment.projectDir.path,
'linux',
'flutter',
- 'ephemeral',
fs.path.relative(input.path, from: basePath),
);
final File destinationFile = fs.file(outputPath);
@@ -62,72 +54,3 @@
}
}
}
-
-/// Creates a debug bundle for the Linux desktop target.
-class DebugBundleLinuxAssets extends Target {
- const DebugBundleLinuxAssets();
-
- @override
- String get name => 'debug_bundle_linux_assets';
-
- @override
- List<Target> get dependencies => const <Target>[
- KernelSnapshot(),
- UnpackLinuxDebug(),
- ];
-
- @override
- List<Source> get inputs => const <Source>[
- Source.pattern('{BUILD_DIR}/app.dill'),
- Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/linux.dart'),
- Source.behavior(AssetOutputBehavior('flutter_assets')),
- ];
-
- @override
- List<Source> get outputs => const <Source>[
- Source.behavior(AssetOutputBehavior('flutter_assets')),
- Source.pattern('{OUTPUT_DIR}/flutter_assets/kernel_blob.bin'),
- Source.pattern('{OUTPUT_DIR}/flutter_assets/AssetManifest.json'),
- Source.pattern('{OUTPUT_DIR}/flutter_assets/FontManifest.json'),
- Source.pattern('{OUTPUT_DIR}/flutter_assets/LICENSE'),
- ];
-
- @override
- Future<void> build(Environment environment) async {
- if (environment.defines[kBuildMode] == null) {
- throw MissingDefineException(kBuildMode, 'debug_bundle_linux_assets');
- }
- final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
- final Directory outputDirectory = environment.outputDir
- .childDirectory('flutter_assets');
- if (!outputDirectory.existsSync()) {
- outputDirectory.createSync();
- }
-
- // Only copy the kernel blob in debug mode.
- if (buildMode == BuildMode.debug) {
- environment.buildDir.childFile('app.dill')
- .copySync(outputDirectory.childFile('kernel_blob.bin').path);
- }
-
- final AssetBundle assetBundle = AssetBundleFactory.instance.createBundle();
- await assetBundle.build();
- final Pool pool = Pool(kMaxOpenFiles);
- await Future.wait<void>(
- assetBundle.entries.entries.map<Future<void>>((MapEntry<String, DevFSContent> entry) async {
- final PoolResource resource = await pool.request();
- try {
- final File file = fs.file(fs.path.join(outputDirectory.path, entry.key));
- file.parent.createSync(recursive: true);
- final DevFSContent content = entry.value;
- if (content is DevFSFileContent && content.file is File) {
- await (content.file as File).copy(file.path);
- } else {
- await file.writeAsBytes(await entry.value.contentsAsBytes());
- }
- } finally {
- resource.release();
- }
- }));
- }
-}
diff --git a/packages/flutter_tools/lib/src/commands/assemble.dart b/packages/flutter_tools/lib/src/commands/assemble.dart
index ee1e72d..c8048cb 100644
--- a/packages/flutter_tools/lib/src/commands/assemble.dart
+++ b/packages/flutter_tools/lib/src/commands/assemble.dart
@@ -20,6 +20,7 @@
/// All currently implemented targets.
const List<Target> _kDefaultTargets = <Target>[
+ UnpackLinux(),
UnpackWindows(),
CopyAssets(),
KernelSnapshot(),
@@ -31,7 +32,6 @@
DebugMacOSBundleFlutterAssets(),
ProfileMacOSBundleFlutterAssets(),
ReleaseMacOSBundleFlutterAssets(),
- DebugBundleLinuxAssets(),
WebReleaseBundle(),
];
@@ -77,7 +77,7 @@
final Target result = _kDefaultTargets
.firstWhere((Target target) => target.name == name, orElse: () => null);
if (result == null) {
- throwToolExit('No target named "$name" defined.');
+ throwToolExit('No target named "{target.name} defined."');
}
return result;
}
diff --git a/packages/flutter_tools/lib/src/commands/unpack.dart b/packages/flutter_tools/lib/src/commands/unpack.dart
index 5fd57c0..6dfdc10 100644
--- a/packages/flutter_tools/lib/src/commands/unpack.dart
+++ b/packages/flutter_tools/lib/src/commands/unpack.dart
@@ -5,6 +5,7 @@
import '../artifacts.dart';
import '../base/common.dart';
import '../base/file_system.dart';
+import '../base/process.dart';
import '../build_info.dart';
import '../cache.dart';
import '../globals.dart';
@@ -12,12 +13,26 @@
/// The directory in the Flutter cache for each platform's artifacts.
const Map<TargetPlatform, String> flutterArtifactPlatformDirectory = <TargetPlatform, String>{
+ TargetPlatform.linux_x64: 'linux-x64',
+ TargetPlatform.darwin_x64: 'darwin-x64',
TargetPlatform.windows_x64: 'windows-x64',
};
// TODO(jonahwilliams): this should come from a configuration in each build
// directory.
const Map<TargetPlatform, List<String>> artifactFilesByPlatform = <TargetPlatform, List<String>>{
+ TargetPlatform.linux_x64: <String>[
+ 'libflutter_linux_glfw.so',
+ 'flutter_export.h',
+ 'flutter_messenger.h',
+ 'flutter_plugin_registrar.h',
+ 'flutter_glfw.h',
+ 'icudtl.dat',
+ 'cpp_client_wrapper_glfw/',
+ ],
+ TargetPlatform.darwin_x64: <String>[
+ 'FlutterMacOS.framework',
+ ],
TargetPlatform.windows_x64: <String>[
'flutter_windows.dll',
'flutter_windows.dll.exp',
@@ -37,7 +52,7 @@
UnpackCommand() {
argParser.addOption(
'target-platform',
- allowed: <String>['windows-x64'],
+ allowed: <String>['darwin-x64', 'linux-x64', 'windows-x64'],
);
argParser.addOption('cache-dir',
help: 'Location to output platform specific artifacts.');
@@ -59,9 +74,15 @@
};
final TargetPlatform targetPlatform = getTargetPlatformForName(argResults['target-platform']);
switch (targetPlatform) {
+ case TargetPlatform.darwin_x64:
+ result.add(DevelopmentArtifact.macOS);
+ break;
case TargetPlatform.windows_x64:
result.add(DevelopmentArtifact.windows);
break;
+ case TargetPlatform.linux_x64:
+ result.add(DevelopmentArtifact.linux);
+ break;
default:
}
return result;
@@ -113,9 +134,15 @@
bool copyCachedArtifacts(String targetDirectory) {
String cacheStamp;
switch (platform) {
+ case TargetPlatform.linux_x64:
+ cacheStamp = 'linux-sdk';
+ break;
case TargetPlatform.windows_x64:
cacheStamp = 'windows-sdk';
break;
+ case TargetPlatform.darwin_x64:
+ cacheStamp = 'macos-sdk';
+ break;
default:
throwToolExit('Unsupported target platform: $platform');
}
@@ -181,17 +208,27 @@
try {
fs.directory(targetDirectory).createSync(recursive: true);
- for (final String entityName in artifactFiles) {
- final String sourcePath = fs.path.join(sourceDirectory, entityName);
- final String targetPath = fs.path.join(targetDirectory, entityName);
- if (entityName.endsWith('/')) {
- copyDirectorySync(
- fs.directory(sourcePath),
- fs.directory(targetPath),
- );
- } else {
- fs.file(sourcePath)
- .copySync(fs.path.join(targetDirectory, entityName));
+
+ // On macOS, delete the existing framework if any before copying in the
+ // new one, since it's a directory. On the other platforms, where files
+ // are just individual files, this isn't necessary since copying over
+ // existing files will do the right thing.
+ if (platform == TargetPlatform.darwin_x64) {
+ _copyMacOSFramework(
+ fs.path.join(sourceDirectory, artifactFiles[0]), targetDirectory);
+ } else {
+ for (final String entityName in artifactFiles) {
+ final String sourcePath = fs.path.join(sourceDirectory, entityName);
+ final String targetPath = fs.path.join(targetDirectory, entityName);
+ if (entityName.endsWith('/')) {
+ copyDirectorySync(
+ fs.directory(sourcePath),
+ fs.directory(targetPath),
+ );
+ } else {
+ fs.file(sourcePath)
+ .copySync(fs.path.join(targetDirectory, entityName));
+ }
}
}
@@ -233,6 +270,43 @@
_lastCopiedHashFile(directory).writeAsStringSync(hash);
}
+ /// Copies the framework at [frameworkPath] to [targetDirectory]
+ /// by invoking 'cp -R'.
+ ///
+ /// The shelling out is done to avoid complications with preserving special
+ /// files (e.g., symbolic links) in the framework structure.
+ ///
+ /// Removes any previous version of the framework that already exists in the
+ /// target directory.
+ void _copyMacOSFramework(String frameworkPath, String targetDirectory) {
+ _deleteFrameworkIfPresent(
+ fs.path.join(targetDirectory, fs.path.basename(frameworkPath)));
+
+ final RunResult result = processUtils
+ .runSync(<String>['cp', '-R', frameworkPath, targetDirectory]);
+ if (result.exitCode != 0) {
+ throw Exception(
+ 'Failed to copy framework (exit ${result.exitCode}:\n'
+ '${result.stdout}\n---\n${result.stderr}',
+ );
+ }
+ }
+
+ /// Recursively deletes the framework at [frameworkPath], if it exists.
+ void _deleteFrameworkIfPresent(String frameworkPath) {
+ // Ensure that the path is a framework, to minimize the potential for
+ // catastrophic deletion bugs with bad arguments.
+ if (fs.path.extension(frameworkPath) != '.framework') {
+ throw Exception(
+ 'Attempted to delete a non-framework directory: $frameworkPath');
+ }
+
+ final Directory directory = fs.directory(frameworkPath);
+ if (directory.existsSync()) {
+ directory.deleteSync(recursive: true);
+ }
+ }
+
/// Returns the engine hash from [file] as a String, or null.
///
/// If the file is missing, or cannot be read, returns null.
diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/linux_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/linux_test.dart
index d707235..6f6bcbf 100644
--- a/packages/flutter_tools/test/general.shard/build_system/targets/linux_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/targets/linux_test.dart
@@ -5,7 +5,6 @@
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/build_system/build_system.dart';
-import 'package:flutter_tools/src/build_system/targets/dart.dart';
import 'package:flutter_tools/src/build_system/targets/linux.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:mockito/mockito.dart';
@@ -29,15 +28,11 @@
when(mockPlatform.isWindows).thenReturn(false);
when(mockPlatform.isMacOS).thenReturn(false);
when(mockPlatform.isLinux).thenReturn(true);
- when(mockPlatform.environment).thenReturn(Map<String, String>.unmodifiable(<String, String>{}));
testbed = Testbed(setup: () {
Cache.flutterRoot = '';
environment = Environment(
outputDir: fs.currentDirectory,
projectDir: fs.currentDirectory,
- defines: <String, String>{
- kBuildMode: 'debug',
- }
);
fs.file('bin/cache/artifacts/engine/linux-x64/libflutter_linux_glfw.so').createSync(recursive: true);
fs.file('bin/cache/artifacts/engine/linux-x64/flutter_export.h').createSync();
@@ -54,51 +49,36 @@
});
test('Copies files to correct cache directory', () => testbed.run(() async {
- final BuildResult result = await buildSystem.build(const UnpackLinuxDebug(), environment);
+ final BuildResult result = await buildSystem.build(const UnpackLinux(), environment);
expect(result.hasException, false);
- expect(fs.file('linux/flutter/ephemeral/libflutter_linux_glfw.so').existsSync(), true);
- expect(fs.file('linux/flutter/ephemeral/flutter_export.h').existsSync(), true);
- expect(fs.file('linux/flutter/ephemeral/flutter_messenger.h').existsSync(), true);
- expect(fs.file('linux/flutter/ephemeral/flutter_plugin_registrar.h').existsSync(), true);
- expect(fs.file('linux/flutter/ephemeral/flutter_glfw.h').existsSync(), true);
- expect(fs.file('linux/flutter/ephemeral/icudtl.dat').existsSync(), true);
- expect(fs.file('linux/flutter/ephemeral/cpp_client_wrapper_glfw/foo').existsSync(), true);
+ expect(fs.file('linux/flutter/libflutter_linux_glfw.so').existsSync(), true);
+ expect(fs.file('linux/flutter/flutter_export.h').existsSync(), true);
+ expect(fs.file('linux/flutter/flutter_messenger.h').existsSync(), true);
+ expect(fs.file('linux/flutter/flutter_plugin_registrar.h').existsSync(), true);
+ expect(fs.file('linux/flutter/flutter_glfw.h').existsSync(), true);
+ expect(fs.file('linux/flutter/icudtl.dat').existsSync(), true);
+ expect(fs.file('linux/flutter/cpp_client_wrapper_glfw/foo').existsSync(), true);
}));
test('Does not re-copy files unecessarily', () => testbed.run(() async {
- await buildSystem.build(const UnpackLinuxDebug(), environment);
+ await buildSystem.build(const UnpackLinux(), environment);
// Set a date in the far distant past to deal with the limited resolution
// of the windows filesystem.
final DateTime theDistantPast = DateTime(1991, 8, 23);
- fs.file('linux/flutter/ephemeral/libflutter_linux_glfw.so').setLastModifiedSync(theDistantPast);
- await buildSystem.build(const UnpackLinuxDebug(), environment);
+ fs.file('linux/flutter/libflutter_linux_glfw.so').setLastModifiedSync(theDistantPast);
+ await buildSystem.build(const UnpackLinux(), environment);
- expect(fs.file('linux/flutter/ephemeral/libflutter_linux_glfw.so').statSync().modified, equals(theDistantPast));
+ expect(fs.file('linux/flutter/libflutter_linux_glfw.so').statSync().modified, equals(theDistantPast));
}));
test('Detects changes in input cache files', () => testbed.run(() async {
- await buildSystem.build(const UnpackLinuxDebug(), environment);
+ await buildSystem.build(const UnpackLinux(), environment);
fs.file('bin/cache/artifacts/engine/linux-x64/libflutter_linux_glfw.so').writeAsStringSync('asd'); // modify cache.
- await buildSystem.build(const UnpackLinuxDebug(), environment);
+ await buildSystem.build(const UnpackLinux(), environment);
- expect(fs.file('linux/flutter/ephemeral/libflutter_linux_glfw.so').readAsStringSync(), 'asd');
- }));
-
- test('Copies artifacts to out directory', () => testbed.run(() async {
- environment.buildDir.createSync(recursive: true);
-
- // Create input files.
- environment.buildDir.childFile('app.dill').createSync();
-
- await const DebugBundleLinuxAssets().build(environment);
- final Directory output = environment.outputDir
- .childDirectory('flutter_assets');
-
- expect(output.childFile('kernel_blob.bin').existsSync(), true);
- expect(output.childFile('FontManifest.json').existsSync(), false);
- expect(output.childFile('AssetManifest.json').existsSync(), true);
+ expect(fs.file('linux/flutter/libflutter_linux_glfw.so').readAsStringSync(), 'asd');
}));
}