From 39a13539e0994eb80313b8f7f3d381eb66bd15de Mon Sep 17 00:00:00 2001 From: Victoria Ashworth <15619084+vashworth@users.noreply.github.com> Date: Wed, 28 Feb 2024 14:09:54 -0600 Subject: [PATCH] Reland "Add FlutterMacOS.xcframework artifact (#143244)" (#144275) Reland https://github.com/flutter/flutter/pull/143244. It was reverted due to https://github.com/flutter/flutter/issues/144251, which is fixed by https://github.com/flutter/engine/pull/51023. --- dev/bots/test.dart | 9 +- dev/devicelab/lib/tasks/plugin_tests.dart | 6 + packages/flutter_tools/bin/podhelper.rb | 18 +- packages/flutter_tools/lib/src/artifacts.dart | 50 ++++- .../lib/src/build_system/targets/macos.dart | 6 +- packages/flutter_tools/lib/src/cache.dart | 8 - .../src/commands/build_macos_framework.dart | 55 ++++-- .../flutter_tools/lib/src/flutter_cache.dart | 6 +- .../test/general.shard/artifacts_test.dart | 186 ++++++++++++++++-- .../test/general.shard/cache_test.dart | 27 --- .../macos_content_validation_test.dart | 32 +++ 11 files changed, 321 insertions(+), 82 deletions(-) diff --git a/dev/bots/test.dart b/dev/bots/test.dart index a87a64cb1b9..ada45fcbc01 100644 --- a/dev/bots/test.dart +++ b/dev/bots/test.dart @@ -1728,9 +1728,9 @@ List binariesWithEntitlements(String flutterRoot) { /// cache. List binariesWithoutEntitlements(String flutterRoot) { return [ - 'artifacts/engine/darwin-x64-profile/FlutterMacOS.framework/Versions/A/FlutterMacOS', - 'artifacts/engine/darwin-x64-release/FlutterMacOS.framework/Versions/A/FlutterMacOS', - 'artifacts/engine/darwin-x64/FlutterMacOS.framework/Versions/A/FlutterMacOS', + 'artifacts/engine/darwin-x64-profile/FlutterMacOS.xcframework/macos-arm64_x86_64/FlutterMacOS.framework/Versions/A/FlutterMacOS', + 'artifacts/engine/darwin-x64-release/FlutterMacOS.xcframework/macos-arm64_x86_64/FlutterMacOS.framework/Versions/A/FlutterMacOS', + 'artifacts/engine/darwin-x64/FlutterMacOS.xcframework/macos-arm64_x86_64/FlutterMacOS.framework/Versions/A/FlutterMacOS', 'artifacts/engine/darwin-x64/font-subset', 'artifacts/engine/darwin-x64/impellerc', 'artifacts/engine/darwin-x64/libpath_ops.dylib', @@ -1764,6 +1764,9 @@ List signedXcframeworks(String flutterRoot) { 'artifacts/engine/ios-release/extension_safe/Flutter.xcframework', 'artifacts/engine/ios/Flutter.xcframework', 'artifacts/engine/ios/extension_safe/Flutter.xcframework', + 'artifacts/engine/darwin-x64-profile/FlutterMacOS.xcframework', + 'artifacts/engine/darwin-x64-release/FlutterMacOS.xcframework', + 'artifacts/engine/darwin-x64/FlutterMacOS.xcframework', ] .map((String relativePath) => path.join(flutterRoot, 'bin', 'cache', relativePath)).toList(); } diff --git a/dev/devicelab/lib/tasks/plugin_tests.dart b/dev/devicelab/lib/tasks/plugin_tests.dart index 21b9883906f..fe6cb4449bf 100644 --- a/dev/devicelab/lib/tasks/plugin_tests.dart +++ b/dev/devicelab/lib/tasks/plugin_tests.dart @@ -118,6 +118,12 @@ class PluginTest { // Currently this test is only implemented for macOS; it can be extended to // others as needed. if (buildTarget == 'macos') { + // When using a local engine, podhelper.rb will search for a "macos-" + // directory within the FlutterMacOS.xcframework, so create a dummy one. + Directory( + path.join(buildDir.path, 'FlutterMacOS.xcframework/macos-arm64_x86_64'), + ).createSync(recursive: true); + // Clean before regenerating the config to ensure that the pod steps run. await inDirectory(Directory(app.rootPath), () async { await evalFlutter('clean'); diff --git a/packages/flutter_tools/bin/podhelper.rb b/packages/flutter_tools/bin/podhelper.rb index 438c4baf7fe..3d64737ae69 100644 --- a/packages/flutter_tools/bin/podhelper.rb +++ b/packages/flutter_tools/bin/podhelper.rb @@ -137,8 +137,8 @@ def flutter_additional_macos_build_settings(target) # This podhelper script is at $FLUTTER_ROOT/packages/flutter_tools/bin. # Add search paths from $FLUTTER_ROOT/bin/cache/artifacts/engine. artifacts_dir = File.join('..', '..', '..', '..', 'bin', 'cache', 'artifacts', 'engine') - debug_framework_dir = File.expand_path(File.join(artifacts_dir, 'darwin-x64'), __FILE__) - release_framework_dir = File.expand_path(File.join(artifacts_dir, 'darwin-x64-release'), __FILE__) + debug_framework_dir = File.expand_path(File.join(artifacts_dir, 'darwin-x64', 'FlutterMacOS.xcframework'), __FILE__) + release_framework_dir = File.expand_path(File.join(artifacts_dir, 'darwin-x64-release', 'FlutterMacOS.xcframework'), __FILE__) application_path = File.dirname(defined_in_file.realpath) if respond_to?(:defined_in_file) # Find the local engine path, if any. local_engine = application_path.nil? ? @@ -156,9 +156,17 @@ def flutter_additional_macos_build_settings(target) # Skip other updates if it does not depend on Flutter (including transitive dependency) next unless depends_on_flutter(target, 'FlutterMacOS') - # Profile can't be derived from the CocoaPods build configuration. Use release framework (for linking only). - configuration_engine_dir = local_engine || (build_configuration.type == :debug ? debug_framework_dir : release_framework_dir) - build_configuration.build_settings['FRAMEWORK_SEARCH_PATHS'] = "\"#{configuration_engine_dir}\" $(inherited)" + if local_engine + configuration_engine_dir = File.expand_path(File.join(local_engine, 'FlutterMacOS.xcframework'), __FILE__) + else + # Profile can't be derived from the CocoaPods build configuration. Use release framework (for linking only). + configuration_engine_dir = (build_configuration.type == :debug ? debug_framework_dir : release_framework_dir) + end + Dir.new(configuration_engine_dir).each_child do |xcframework_file| + if xcframework_file.start_with?('macos-') # Could be macos-arm64_x86_64, macos-arm64, macos-x86_64 + build_configuration.build_settings['FRAMEWORK_SEARCH_PATHS'] = "\"#{configuration_engine_dir}/#{xcframework_file}\" $(inherited)" + end + end # When deleted, the deployment version will inherit from the higher version derived from the 'Runner' target. # If the pod only supports a higher version, do not delete to correctly produce an error. diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart index 1dba8e9b3b3..ba3703b86ef 100644 --- a/packages/flutter_tools/lib/src/artifacts.dart +++ b/packages/flutter_tools/lib/src/artifacts.dart @@ -25,6 +25,7 @@ enum Artifact { flutterXcframework, /// The framework directory of the macOS desktop. flutterMacOSFramework, + flutterMacOSXcframework, vmSnapshotData, isolateSnapshotData, icuData, @@ -184,6 +185,8 @@ String? _artifactToFileName(Artifact artifact, Platform hostPlatform, [ BuildMod return 'Flutter.xcframework'; case Artifact.flutterMacOSFramework: return 'FlutterMacOS.framework'; + case Artifact.flutterMacOSXcframework: + return 'FlutterMacOS.xcframework'; case Artifact.vmSnapshotData: return 'vm_isolate_snapshot.bin'; case Artifact.isolateSnapshotData: @@ -598,6 +601,10 @@ class CachedArtifacts implements Artifacts { final String engineDir = _getEngineArtifactsPath(platform, mode)!; return _fileSystem.path.join(engineDir, _artifactToFileName(artifact, _platform)); } + if (platform != null && artifact == Artifact.flutterMacOSFramework) { + final String engineDir = _getEngineArtifactsPath(platform, mode)!; + return _getMacOSEngineArtifactPath(engineDir, _fileSystem, _platform); + } return _getHostArtifactPath(artifact, platform ?? _currentHostPlatform(_platform, _operatingSystemUtils), mode); } @@ -617,6 +624,7 @@ class CachedArtifacts implements Artifacts { case Artifact.constFinder: case Artifact.flutterFramework: case Artifact.flutterMacOSFramework: + case Artifact.flutterMacOSXcframework: case Artifact.flutterPatchedSdkPath: case Artifact.flutterTester: case Artifact.flutterXcframework: @@ -657,6 +665,7 @@ class CachedArtifacts implements Artifacts { case Artifact.frontendServerSnapshotForEngineDartSdk: case Artifact.constFinder: case Artifact.flutterMacOSFramework: + case Artifact.flutterMacOSXcframework: case Artifact.flutterPatchedSdkPath: case Artifact.flutterTester: case Artifact.fontSubset: @@ -705,6 +714,7 @@ class CachedArtifacts implements Artifacts { case Artifact.constFinder: case Artifact.flutterFramework: case Artifact.flutterMacOSFramework: + case Artifact.flutterMacOSXcframework: case Artifact.flutterTester: case Artifact.flutterXcframework: case Artifact.fontSubset: @@ -771,6 +781,13 @@ class CachedArtifacts implements Artifacts { case Artifact.engineDartAotRuntime: return _fileSystem.path.join(_dartSdkPath(_cache), 'bin', _artifactToFileName(artifact, _platform)); case Artifact.flutterMacOSFramework: + String platformDirName = _enginePlatformDirectoryName(platform); + if (mode == BuildMode.profile || mode == BuildMode.release) { + platformDirName = '$platformDirName-${mode!.cliName}'; + } + final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path; + return _getMacOSEngineArtifactPath(_fileSystem.path.join(engineArtifactsPath, platformDirName), _fileSystem, _platform); + case Artifact.flutterMacOSXcframework: case Artifact.linuxDesktopPath: case Artifact.windowsDesktopPath: case Artifact.linuxHeaders: @@ -896,6 +913,33 @@ String _getIosEngineArtifactPath(String engineDirectory, .path; } +String _getMacOSEngineArtifactPath( + String engineDirectory, + FileSystem fileSystem, + Platform hostPlatform, +) { + final Directory xcframeworkDirectory = fileSystem + .directory(engineDirectory) + .childDirectory(_artifactToFileName(Artifact.flutterMacOSXcframework, hostPlatform)!); + + if (!xcframeworkDirectory.existsSync()) { + throwToolExit('No xcframework found at ${xcframeworkDirectory.path}. Try running "flutter precache --macos".'); + } + final Directory? flutterFrameworkSource = xcframeworkDirectory + .listSync() + .whereType() + .where((Directory platformDirectory) => + platformDirectory.basename.startsWith('macos-')) + .firstOrNull; + if (flutterFrameworkSource == null) { + throwToolExit('No macOS frameworks found in ${xcframeworkDirectory.path}'); + } + + return flutterFrameworkSource + .childDirectory(_artifactToFileName(Artifact.flutterMacOSFramework, hostPlatform)!) + .path; +} + /// Manages the artifacts of a locally built engine. class CachedLocalEngineArtifacts implements Artifacts { CachedLocalEngineArtifacts( @@ -1054,7 +1098,7 @@ class CachedLocalEngineArtifacts implements Artifacts { return _fileSystem.path.join(localEngineInfo.targetOutPath, 'gen', 'flutter', 'lib', 'snapshot', artifactFileName); case Artifact.icuData: case Artifact.flutterXcframework: - case Artifact.flutterMacOSFramework: + case Artifact.flutterMacOSXcframework: return _fileSystem.path.join(localEngineInfo.targetOutPath, artifactFileName); case Artifact.platformKernelDill: if (platform == TargetPlatform.fuchsia_x64 || platform == TargetPlatform.fuchsia_arm64) { @@ -1066,6 +1110,9 @@ class CachedLocalEngineArtifacts implements Artifacts { case Artifact.flutterFramework: return _getIosEngineArtifactPath( localEngineInfo.targetOutPath, environmentType, _fileSystem, _platform); + case Artifact.flutterMacOSFramework: + return _getMacOSEngineArtifactPath( + localEngineInfo.targetOutPath, _fileSystem, _platform); case Artifact.flutterPatchedSdkPath: // When using local engine always use [BuildMode.debug] regardless of // what was specified in [mode] argument because local engine will @@ -1246,6 +1293,7 @@ class CachedLocalWebSdkArtifacts implements Artifacts { case Artifact.flutterFramework: case Artifact.flutterXcframework: case Artifact.flutterMacOSFramework: + case Artifact.flutterMacOSXcframework: case Artifact.vmSnapshotData: case Artifact.isolateSnapshotData: case Artifact.icuData: diff --git a/packages/flutter_tools/lib/src/build_system/targets/macos.dart b/packages/flutter_tools/lib/src/build_system/targets/macos.dart index 7f69f52fa82..9996664a0a1 100644 --- a/packages/flutter_tools/lib/src/build_system/targets/macos.dart +++ b/packages/flutter_tools/lib/src/build_system/targets/macos.dart @@ -157,7 +157,7 @@ class ReleaseUnpackMacOS extends UnpackMacOS { @override List get inputs => [ ...super.inputs, - const Source.artifact(Artifact.flutterMacOSFramework, mode: BuildMode.release), + const Source.artifact(Artifact.flutterMacOSXcframework, mode: BuildMode.release), ]; } @@ -171,7 +171,7 @@ class ProfileUnpackMacOS extends UnpackMacOS { @override List get inputs => [ ...super.inputs, - const Source.artifact(Artifact.flutterMacOSFramework, mode: BuildMode.profile), + const Source.artifact(Artifact.flutterMacOSXcframework, mode: BuildMode.profile), ]; } @@ -185,7 +185,7 @@ class DebugUnpackMacOS extends UnpackMacOS { @override List get inputs => [ ...super.inputs, - const Source.artifact(Artifact.flutterMacOSFramework, mode: BuildMode.debug), + const Source.artifact(Artifact.flutterMacOSXcframework, mode: BuildMode.debug), ]; } diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart index 6abae46c8f8..c5296d8a8a2 100644 --- a/packages/flutter_tools/lib/src/cache.dart +++ b/packages/flutter_tools/lib/src/cache.dart @@ -944,14 +944,6 @@ abstract class EngineCachedArtifact extends CachedArtifact { await artifactUpdater.downloadZipArchive('Downloading $friendlyName tools...', Uri.parse(url + urlPath), dir); _makeFilesExecutable(dir, operatingSystemUtils); - - final File frameworkZip = fileSystem.file(fileSystem.path.join(dir.path, 'FlutterMacOS.framework.zip')); - if (frameworkZip.existsSync()) { - final Directory framework = fileSystem.directory(fileSystem.path.join(dir.path, 'FlutterMacOS.framework')); - ErrorHandlingFileSystem.deleteIfExists(framework, recursive: true); - framework.createSync(); - operatingSystemUtils.unzip(frameworkZip, framework); - } } final File licenseSource = cache.getLicenseFile(); diff --git a/packages/flutter_tools/lib/src/commands/build_macos_framework.dart b/packages/flutter_tools/lib/src/commands/build_macos_framework.dart index 7d6c1fee266..384d1df53cf 100644 --- a/packages/flutter_tools/lib/src/commands/build_macos_framework.dart +++ b/packages/flutter_tools/lib/src/commands/build_macos_framework.dart @@ -4,6 +4,7 @@ import 'package:meta/meta.dart'; +import '../artifacts.dart'; import '../base/common.dart'; import '../base/file_system.dart'; import '../base/io.dart'; @@ -83,13 +84,16 @@ class BuildMacOSFrameworkCommand extends BuildFrameworkCommand { if (boolArg('cocoapods')) { produceFlutterPodspec(buildInfo.mode, modeDirectory, force: boolArg('force')); + } else { + await _produceFlutterFramework(buildInfo, modeDirectory); } - // Build aot, create App.framework and copy FlutterMacOS.framework. Make XCFrameworks. - await _produceAppFramework(buildInfo, modeDirectory); + final Directory buildOutput = modeDirectory.childDirectory('macos'); + + // Build aot, create App.framework. Make XCFrameworks. + await _produceAppFramework(buildInfo, modeDirectory, buildOutput); // Build and copy plugins. - final Directory buildOutput = modeDirectory.childDirectory('macos'); await processPodsIfNeeded(project.macos, getMacOSBuildDirectory(), buildInfo.mode); if (boolArg('plugins') && hasPlugins(project)) { await _producePlugins(xcodeBuildConfiguration, buildOutput, modeDirectory); @@ -200,15 +204,15 @@ end Future _produceAppFramework( BuildInfo buildInfo, Directory outputBuildDirectory, + Directory macosBuildOutput, ) async { final Status status = globals.logger.startProgress( - ' ├─Building App.xcframework and FlutterMacOS.xcframework...', + ' ├─Building App.xcframework...', ); - try { final Environment environment = Environment( projectDir: globals.fs.currentDirectory, - outputDir: outputBuildDirectory, + outputDir: macosBuildOutput, buildDir: project.dartTool.childDirectory('flutter_build'), cacheDir: globals.cache.getRoot(), flutterRootDir: globals.fs.directory(Cache.flutterRoot), @@ -251,7 +255,7 @@ end status.stop(); } - final Directory appFramework = outputBuildDirectory.childDirectory('App.framework'); + final Directory appFramework = macosBuildOutput.childDirectory('App.framework'); await BuildFrameworkCommand.produceXCFramework( [appFramework], 'App', @@ -259,18 +263,37 @@ end globals.processManager, ); appFramework.deleteSync(recursive: true); - final Directory flutterFramework = outputBuildDirectory.childDirectory('FlutterMacOS.framework'); + } - // If FlutterMacOS.podspec was generated, do not generate XCFramework. - if (!boolArg('cocoapods')) { - await BuildFrameworkCommand.produceXCFramework( - [flutterFramework], - 'FlutterMacOS', - outputBuildDirectory, - globals.processManager, + Future _produceFlutterFramework( + BuildInfo buildInfo, + Directory modeDirectory, + ) async { + final Status status = globals.logger.startProgress( + ' ├─Copying FlutterMacOS.xcframework...', + ); + final String engineCacheFlutterFrameworkDirectory = globals.artifacts!.getArtifactPath( + Artifact.flutterMacOSXcframework, + platform: TargetPlatform.darwin, + mode: buildInfo.mode, + ); + final String flutterFrameworkFileName = globals.fs.path.basename( + engineCacheFlutterFrameworkDirectory, + ); + final Directory flutterFrameworkCopy = modeDirectory.childDirectory( + flutterFrameworkFileName, + ); + + try { + // Copy xcframework engine cache framework to mode directory. + copyDirectory( + globals.fs.directory(engineCacheFlutterFrameworkDirectory), + flutterFrameworkCopy, + followLinks: false, ); + } finally { + status.stop(); } - flutterFramework.deleteSync(recursive: true); } Future _producePlugins( diff --git a/packages/flutter_tools/lib/src/flutter_cache.dart b/packages/flutter_tools/lib/src/flutter_cache.dart index d19e7f98418..9b2c51be5f5 100644 --- a/packages/flutter_tools/lib/src/flutter_cache.dart +++ b/packages/flutter_tools/lib/src/flutter_cache.dart @@ -858,12 +858,12 @@ List> _getWindowsDesktopBinaryDirs(String arch) { } const List> _macOSDesktopBinaryDirs = >[ - ['darwin-x64', 'darwin-x64/FlutterMacOS.framework.zip'], + ['darwin-x64', 'darwin-x64/framework.zip'], ['darwin-x64', 'darwin-x64/gen_snapshot.zip'], - ['darwin-x64-profile', 'darwin-x64-profile/FlutterMacOS.framework.zip'], + ['darwin-x64-profile', 'darwin-x64-profile/framework.zip'], ['darwin-x64-profile', 'darwin-x64-profile/artifacts.zip'], ['darwin-x64-profile', 'darwin-x64-profile/gen_snapshot.zip'], - ['darwin-x64-release', 'darwin-x64-release/FlutterMacOS.framework.zip'], + ['darwin-x64-release', 'darwin-x64-release/framework.zip'], ['darwin-x64-release', 'darwin-x64-release/artifacts.zip'], ['darwin-x64-release', 'darwin-x64-release/gen_snapshot.zip'], ]; diff --git a/packages/flutter_tools/test/general.shard/artifacts_test.dart b/packages/flutter_tools/test/general.shard/artifacts_test.dart index b8312332629..dfbf34dd9ff 100644 --- a/packages/flutter_tools/test/general.shard/artifacts_test.dart +++ b/packages/flutter_tools/test/general.shard/artifacts_test.dart @@ -93,12 +93,6 @@ void main() { .childDirectory('Flutter.framework') .createSync(recursive: true); - // TODO(jmagman): Remove ios-arm64_armv7 checks when armv7 engine artifacts are removed. - fileSystem - .directory(xcframeworkPath) - .childDirectory('ios-arm64_armv7') - .childDirectory('Flutter.framework') - .createSync(recursive: true); expect( artifacts.getArtifactPath(Artifact.flutterFramework, platform: TargetPlatform.ios, @@ -118,16 +112,9 @@ void main() { 'ios-arm64', 'Flutter.framework', ); - final String expectedArmv7ReleaseFrameworkArtifact = fileSystem.path.join( - xcframeworkPath, - 'ios-arm64_armv7', - 'Flutter.framework', - ); - - // TODO(jmagman): Replace with expect(actualReleaseFrameworkArtifact, expectedArm64ReleaseFrameworkArtifact) when armv7 engine artifacts are removed. expect( actualReleaseFrameworkArtifact, - anyOf(expectedArm64ReleaseFrameworkArtifact, expectedArmv7ReleaseFrameworkArtifact), + expectedArm64ReleaseFrameworkArtifact, ); expect( artifacts.getArtifactPath(Artifact.flutterXcframework, platform: TargetPlatform.ios, mode: BuildMode.release), @@ -148,6 +135,87 @@ void main() { ); }); + testWithoutContext('getArtifactPath for FlutterMacOS.framework and FlutterMacOS.xcframework', () { + final String xcframeworkPath = fileSystem.path.join( + 'root', + 'bin', + 'cache', + 'artifacts', + 'engine', + 'darwin-x64-release', + 'FlutterMacOS.xcframework', + ); + final String xcframeworkPathWithUnsetPlatform = fileSystem.path.join( + 'root', + 'bin', + 'cache', + 'artifacts', + 'engine', + 'linux-x64-release', + 'FlutterMacOS.xcframework', + ); + expect( + artifacts.getArtifactPath( + Artifact.flutterMacOSXcframework, + platform: TargetPlatform.darwin, + mode: BuildMode.release, + ), + xcframeworkPath, + ); + expect( + artifacts.getArtifactPath( + Artifact.flutterMacOSXcframework, + mode: BuildMode.release, + ), + xcframeworkPathWithUnsetPlatform, + ); + expect( + () => artifacts.getArtifactPath( + Artifact.flutterMacOSFramework, + platform: TargetPlatform.darwin, + mode: BuildMode.release, + ), + throwsToolExit( + message: + 'No xcframework found at $xcframeworkPath.'), + ); + expect( + () => artifacts.getArtifactPath( + Artifact.flutterMacOSFramework, + mode: BuildMode.release, + ), + throwsToolExit( + message: + 'No xcframework found at $xcframeworkPathWithUnsetPlatform.'), + ); + fileSystem.directory(xcframeworkPath).createSync(recursive: true); + expect( + () => artifacts.getArtifactPath( + Artifact.flutterMacOSFramework, + platform: TargetPlatform.darwin, + mode: BuildMode.release, + ), + throwsToolExit(message: 'No macOS frameworks found in $xcframeworkPath'), + ); + fileSystem + .directory(xcframeworkPath) + .childDirectory('macos-arm64_x86_64') + .childDirectory('FlutterMacOS.framework') + .createSync(recursive: true); + expect( + artifacts.getArtifactPath( + Artifact.flutterMacOSFramework, + platform: TargetPlatform.darwin, + mode: BuildMode.release, + ), + fileSystem.path.join( + xcframeworkPath, + 'macos-arm64_x86_64', + 'FlutterMacOS.framework', + ), + ); + }); + testWithoutContext('Precompiled web AMD module system artifact paths are correct', () { expect( artifacts.getHostArtifact(HostArtifact.webPrecompiledAmdSdk).path, @@ -269,6 +337,92 @@ void main() { operatingSystemUtils: FakeOperatingSystemUtils()); }); + testWithoutContext('getArtifactPath for FlutterMacOS.framework and FlutterMacOS.xcframework', () { + final String xcframeworkPath = fileSystem.path.join( + '/out', + 'android_debug_unopt', + 'FlutterMacOS.xcframework', + ); + expect( + artifacts.getArtifactPath( + Artifact.flutterMacOSXcframework, + platform: TargetPlatform.darwin, + mode: BuildMode.release, + ), + xcframeworkPath, + ); + expect( + artifacts.getArtifactPath( + Artifact.flutterMacOSXcframework, + mode: BuildMode.release, + ), + xcframeworkPath, + ); + expect( + () => artifacts.getArtifactPath( + Artifact.flutterMacOSFramework, + platform: TargetPlatform.darwin, + mode: BuildMode.release, + ), + throwsToolExit( + message: + 'No xcframework found at /out/android_debug_unopt/FlutterMacOS.xcframework'), + ); + expect( + () => artifacts.getArtifactPath( + Artifact.flutterMacOSFramework, + mode: BuildMode.release, + ), + throwsToolExit( + message: + 'No xcframework found at /out/android_debug_unopt/FlutterMacOS.xcframework'), + ); + fileSystem.directory(xcframeworkPath).createSync(recursive: true); + expect( + () => artifacts.getArtifactPath( + Artifact.flutterMacOSFramework, + platform: TargetPlatform.darwin, + mode: BuildMode.release, + ), + throwsToolExit( + message: + 'No macOS frameworks found in /out/android_debug_unopt/FlutterMacOS.xcframework'), + ); + expect( + () => artifacts.getArtifactPath( + Artifact.flutterMacOSFramework, + mode: BuildMode.release, + ), + throwsToolExit( + message: + 'No macOS frameworks found in /out/android_debug_unopt/FlutterMacOS.xcframework'), + ); + + fileSystem + .directory(xcframeworkPath) + .childDirectory('macos-arm64_x86_64') + .childDirectory('FlutterMacOS.framework') + .createSync(recursive: true); + + expect( + artifacts.getArtifactPath( + Artifact.flutterMacOSFramework, + platform: TargetPlatform.darwin, + mode: BuildMode.release, + ), + fileSystem.path + .join(xcframeworkPath, 'macos-arm64_x86_64', 'FlutterMacOS.framework'), + ); + expect( + artifacts.getArtifactPath( + Artifact.flutterMacOSFramework, + mode: BuildMode.release, + ), + fileSystem.path + .join(xcframeworkPath, 'macos-arm64_x86_64', 'FlutterMacOS.framework'), + ); + }); + testWithoutContext('getArtifactPath', () { final String xcframeworkPath = artifacts.getArtifactPath( Artifact.flutterXcframework, @@ -311,7 +465,7 @@ void main() { .createSync(recursive: true); fileSystem .directory(xcframeworkPath) - .childDirectory('ios-arm64_armv7') + .childDirectory('ios-arm64') .childDirectory('Flutter.framework') .createSync(recursive: true); fileSystem @@ -339,7 +493,7 @@ void main() { environmentType: EnvironmentType.physical, ), fileSystem.path - .join(xcframeworkPath, 'ios-arm64_armv7', 'Flutter.framework'), + .join(xcframeworkPath, 'ios-arm64', 'Flutter.framework'), ); expect( artifacts.getArtifactPath( diff --git a/packages/flutter_tools/test/general.shard/cache_test.dart b/packages/flutter_tools/test/general.shard/cache_test.dart index 0ec69bca6a3..220e8fef69a 100644 --- a/packages/flutter_tools/test/general.shard/cache_test.dart +++ b/packages/flutter_tools/test/general.shard/cache_test.dart @@ -393,33 +393,6 @@ void main() { expect(operatingSystemUtils.chmods, >[['/.tmp_rand0/flutter_cache_test_artifact.rand0/bin_dir', 'a+r,a+x']]); }); - testWithoutContext('EngineCachedArtifact removes unzipped FlutterMacOS.framework before replacing', () async { - final OperatingSystemUtils operatingSystemUtils = FakeOperatingSystemUtils(); - final FileSystem fileSystem = MemoryFileSystem.test(); - final Directory artifactDir = fileSystem.systemTempDirectory.createTempSync('flutter_cache_test_artifact.'); - final Directory downloadDir = fileSystem.systemTempDirectory.createTempSync('flutter_cache_test_download.'); - final FakeSecondaryCache cache = FakeSecondaryCache() - ..artifactDirectory = artifactDir - ..downloadDir = downloadDir; - - final Directory binDir = artifactDir.childDirectory('bin_dir')..createSync(); - binDir.childFile('FlutterMacOS.framework.zip').createSync(); - final Directory unzippedFramework = binDir.childDirectory('FlutterMacOS.framework'); - final File staleFile = unzippedFramework.childFile('stale_file')..createSync(recursive: true); - artifactDir.childFile('unused_url_path').createSync(); - - final FakeCachedArtifact artifact = FakeCachedArtifact( - cache: cache, - binaryDirs: >[ - ['bin_dir', 'unused_url_path'], - ], - requiredArtifacts: DevelopmentArtifact.universal, - ); - await artifact.updateInner(FakeArtifactUpdater(), fileSystem, operatingSystemUtils); - expect(unzippedFramework, exists); - expect(staleFile, isNot(exists)); - }); - testWithoutContext('Try to remove without a parent', () async { final FileSystem fileSystem = MemoryFileSystem.test(); final Directory parent = fileSystem.directory('dir'); diff --git a/packages/flutter_tools/test/host_cross_arch.shard/macos_content_validation_test.dart b/packages/flutter_tools/test/host_cross_arch.shard/macos_content_validation_test.dart index 5bfa8ac987e..5568ad2f9a0 100644 --- a/packages/flutter_tools/test/host_cross_arch.shard/macos_content_validation_test.dart +++ b/packages/flutter_tools/test/host_cross_arch.shard/macos_content_validation_test.dart @@ -24,6 +24,38 @@ void main() { ]); }); + test('verify FlutterMacOS.xcframework artifact', () { + final String flutterRoot = getFlutterRoot(); + + final Directory xcframeworkArtifact = fileSystem.directory( + fileSystem.path.join( + flutterRoot, + 'bin', + 'cache', + 'artifacts', + 'engine', + 'darwin-x64', + 'FlutterMacOS.xcframework', + ), + ); + + final Directory tempDir = createResolvedTempDirectorySync('macos_content_validation.'); + + // Pre-cache iOS engine Flutter.xcframework artifacts. + final ProcessResult result = processManager.runSync( + [ + flutterBin, + ...getLocalEngineArguments(), + 'precache', + '--macos', + ], + workingDirectory: tempDir.path, + ); + + expect(result, const ProcessResultMatcher()); + expect(xcframeworkArtifact.existsSync(), isTrue); + }); + for (final String buildMode in ['Debug', 'Release']) { final String buildModeLower = buildMode.toLowerCase();