Revert "[flutter_tools] Reland migrate xcode_backend.sh to flutter assemble (#50200)" (#50228)
This reverts commit 868b0e6d976370cb4bcfe6a7e060b847731d99c3.
diff --git a/packages/flutter_tools/bin/xcode_backend.sh b/packages/flutter_tools/bin/xcode_backend.sh
index 5181c0b..0022992 100755
--- a/packages/flutter_tools/bin/xcode_backend.sh
+++ b/packages/flutter_tools/bin/xcode_backend.sh
@@ -51,10 +51,6 @@
derived_dir="${project_path}/.ios/Flutter"
fi
- RunCommand mkdir -p -- "$derived_dir"
- AssertExists "$derived_dir"
- RunCommand rm -rf -- "${derived_dir}/App.framework"
-
# Default value of assets_path is flutter_assets
local assets_path="flutter_assets"
# The value of assets_path can set by add FLTAssetsPath to AppFrameworkInfo.plist
@@ -100,6 +96,15 @@
fi
local framework_path="${FLUTTER_ROOT}/bin/cache/artifacts/engine/${artifact_variant}"
+
+ AssertExists "${framework_path}"
+ AssertExists "${project_path}"
+
+ RunCommand mkdir -p -- "$derived_dir"
+ AssertExists "$derived_dir"
+
+ RunCommand rm -rf -- "${derived_dir}/App.framework"
+
local flutter_engine_flag=""
local local_engine_flag=""
local flutter_framework="${framework_path}/Flutter.framework"
@@ -129,10 +134,9 @@
local bitcode_flag=""
if [[ $ENABLE_BITCODE == "YES" ]]; then
- bitcode_flag="true"
+ bitcode_flag="--bitcode"
fi
- # TODO(jonahwilliams): move engine copying to build system.
if [[ -e "${project_path}/.ios" ]]; then
RunCommand rm -rf -- "${derived_dir}/engine"
mkdir "${derived_dir}/engine"
@@ -146,29 +150,102 @@
RunCommand pushd "${project_path}" > /dev/null
+ AssertExists "${target_path}"
+
local verbose_flag=""
if [[ -n "$VERBOSE_SCRIPT_LOGGING" ]]; then
verbose_flag="--verbose"
fi
+ local build_dir="${FLUTTER_BUILD_DIR:-build}"
+
local track_widget_creation_flag=""
if [[ -n "$TRACK_WIDGET_CREATION" ]]; then
- track_widget_creation_flag="true"
+ track_widget_creation_flag="--track-widget-creation"
fi
- RunCommand "${FLUTTER_ROOT}/bin/flutter" --suppress-analytics \
- ${verbose_flag} \
- ${flutter_engine_flag} \
- ${local_engine_flag} \
- assemble \
- --output="${derived_dir}/" \
- -dTargetPlatform=ios \
- -dTargetFile="${target_path}" \
- -dBuildMode=${build_mode} \
- -dIosArchs="${ARCHS}" \
- -dTrackWidgetCreation="${track_widget_creation_flag}" \
- -dEnableBitcode="${bitcode_flag}" \
- "${build_mode}_ios_bundle_flutter_assets"
+ if [[ "${build_mode}" != "debug" ]]; then
+ StreamOutput " ├─Building Dart code..."
+ # Transform ARCHS to comma-separated list of target architectures.
+ local archs="${ARCHS// /,}"
+ if [[ $archs =~ .*i386.* || $archs =~ .*x86_64.* ]]; then
+ EchoError "========================================================================"
+ EchoError "ERROR: Flutter does not support running in profile or release mode on"
+ EchoError "the Simulator (this build was: '$build_mode')."
+ EchoError "You can ensure Flutter runs in Debug mode with your host app in release"
+ EchoError "mode by setting FLUTTER_BUILD_MODE=debug in the .xcconfig associated"
+ EchoError "with the ${CONFIGURATION} build configuration."
+ EchoError "========================================================================"
+ exit -1
+ fi
+
+ RunCommand "${FLUTTER_ROOT}/bin/flutter" --suppress-analytics \
+ ${verbose_flag} \
+ build aot \
+ --output-dir="${build_dir}/aot" \
+ --target-platform=ios \
+ --target="${target_path}" \
+ --${build_mode} \
+ --ios-arch="${archs}" \
+ ${flutter_engine_flag} \
+ ${local_engine_flag} \
+ ${bitcode_flag}
+
+ if [[ $? -ne 0 ]]; then
+ EchoError "Failed to build ${project_path}."
+ exit -1
+ fi
+ StreamOutput "done"
+
+ local app_framework="${build_dir}/aot/App.framework"
+
+ RunCommand cp -r -- "${app_framework}" "${derived_dir}"
+
+ else
+ RunCommand mkdir -p -- "${derived_dir}/App.framework"
+
+ # Build stub for all requested architectures.
+ local arch_flags=""
+ read -r -a archs <<< "$ARCHS"
+ for arch in "${archs[@]}"; do
+ arch_flags="${arch_flags}-arch $arch "
+ done
+
+ RunCommand eval "$(echo "static const int Moo = 88;" | xcrun clang -x c \
+ ${arch_flags} \
+ -fembed-bitcode-marker \
+ -dynamiclib \
+ -Xlinker -rpath -Xlinker '@executable_path/Frameworks' \
+ -Xlinker -rpath -Xlinker '@loader_path/Frameworks' \
+ -install_name '@rpath/App.framework/App' \
+ -o "${derived_dir}/App.framework/App" -)"
+ fi
+
+ local plistPath="${project_path}/ios/Flutter/AppFrameworkInfo.plist"
+ if [[ -e "${project_path}/.ios" ]]; then
+ plistPath="${project_path}/.ios/Flutter/AppFrameworkInfo.plist"
+ fi
+
+ RunCommand cp -- "$plistPath" "${derived_dir}/App.framework/Info.plist"
+
+ local precompilation_flag=""
+ if [[ "$CURRENT_ARCH" != "x86_64" ]] && [[ "$build_mode" != "debug" ]]; then
+ precompilation_flag="--precompiled"
+ fi
+
+ StreamOutput " ├─Assembling Flutter resources..."
+ RunCommand "${FLUTTER_ROOT}/bin/flutter" \
+ ${verbose_flag} \
+ build bundle \
+ --target-platform=ios \
+ --target="${target_path}" \
+ --${build_mode} \
+ --depfile="${build_dir}/snapshot_blob.bin.d" \
+ --asset-dir="${derived_dir}/App.framework/${assets_path}" \
+ ${precompilation_flag} \
+ ${flutter_engine_flag} \
+ ${local_engine_flag} \
+ ${track_widget_creation_flag}
if [[ $? -ne 0 ]]; then
EchoError "Failed to package ${project_path}."
diff --git a/packages/flutter_tools/lib/src/aot.dart b/packages/flutter_tools/lib/src/aot.dart
index 24d3b84..7465654 100644
--- a/packages/flutter_tools/lib/src/aot.dart
+++ b/packages/flutter_tools/lib/src/aot.dart
@@ -12,9 +12,14 @@
import 'base/logger.dart';
import 'base/process.dart';
import 'build_info.dart';
+import 'build_system/build_system.dart';
+import 'build_system/targets/dart.dart';
+import 'build_system/targets/ios.dart';
+import 'cache.dart';
import 'dart/package_map.dart';
import 'globals.dart' as globals;
import 'ios/bitcode.dart';
+import 'project.dart';
/// Builds AOT snapshots given a platform, build mode and a path to a Dart
/// library.
@@ -37,6 +42,21 @@
throwToolExit('No AOT build platform specified');
}
+ if (_canUseAssemble(platform)
+ && extraGenSnapshotOptions?.isEmpty != false
+ && extraFrontEndOptions?.isEmpty != false) {
+ await _buildWithAssemble(
+ targetFile: mainDartFile,
+ outputDir: outputPath,
+ targetPlatform: platform,
+ buildMode: buildMode,
+ quiet: quiet,
+ iosArchs: iosBuildArchs ?? defaultIOSArchs,
+ bitcode: bitcode ?? kBitcodeEnabledDefault,
+ );
+ return;
+ }
+
if (bitcode) {
if (platform != TargetPlatform.ios) {
throwToolExit('Bitcode is only supported on iOS (TargetPlatform is $platform).');
@@ -154,4 +174,81 @@
}
return;
}
+
+ bool _canUseAssemble(TargetPlatform targetPlatform) {
+ switch (targetPlatform) {
+ case TargetPlatform.ios:
+ return true;
+ case TargetPlatform.android_arm:
+ case TargetPlatform.android_arm64:
+ case TargetPlatform.android_x86:
+ case TargetPlatform.darwin_x64:
+ case TargetPlatform.android_x64:
+ case TargetPlatform.linux_x64:
+ case TargetPlatform.windows_x64:
+ case TargetPlatform.fuchsia_arm64:
+ case TargetPlatform.fuchsia_x64:
+ case TargetPlatform.tester:
+ case TargetPlatform.web_javascript:
+ default:
+ return false;
+ }
+ }
+
+ Future<void> _buildWithAssemble({
+ TargetPlatform targetPlatform,
+ BuildMode buildMode,
+ String targetFile,
+ String outputDir,
+ bool quiet,
+ Iterable<DarwinArch> iosArchs,
+ bool bitcode,
+ }) async {
+ Status status;
+ if (!quiet) {
+ final String typeName = globals.artifacts.getEngineType(targetPlatform, buildMode);
+ status = globals.logger.startProgress(
+ 'Building AOT snapshot in ${getFriendlyModeName(buildMode)} mode ($typeName)...',
+ timeout: timeoutConfiguration.slowOperation,
+ );
+ }
+ final FlutterProject flutterProject = FlutterProject.current();
+ final Target target = buildMode == BuildMode.profile
+ ? const AotAssemblyProfile()
+ : const AotAssemblyRelease();
+
+ final BuildResult result = await buildSystem.build(target, Environment(
+ projectDir: flutterProject.directory,
+ cacheDir: globals.cache.getRoot(),
+ flutterRootDir: globals.fs.directory(Cache.flutterRoot),
+ outputDir: globals.fs.directory(outputDir),
+ buildDir: flutterProject.directory
+ .childDirectory('.dart_tool')
+ .childDirectory('flutter_build'),
+ defines: <String, String>{
+ kBuildMode: getNameForBuildMode(buildMode),
+ kTargetPlatform: getNameForTargetPlatform(targetPlatform),
+ kTargetFile: targetFile,
+ kIosArchs: iosArchs.map(getNameForDarwinArch).join(','),
+ kBitcodeFlag: bitcode.toString()
+ }
+ ));
+ status?.stop();
+ if (!result.success) {
+ for (final ExceptionMeasurement measurement in result.exceptions.values) {
+ globals.printError('Target ${measurement.target} failed: ${measurement.exception}',
+ stackTrace: measurement.fatal
+ ? measurement.stackTrace
+ : null,
+ );
+ }
+ throwToolExit('Failed to build aot.');
+ }
+ final String builtMessage = 'Built to $outputDir${globals.fs.path.separator}.';
+ if (quiet) {
+ globals.printTrace(builtMessage);
+ } else {
+ globals.printStatus(builtMessage);
+ }
+ }
}
diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart
index 3888954..545a869 100644
--- a/packages/flutter_tools/lib/src/build_info.dart
+++ b/packages/flutter_tools/lib/src/build_info.dart
@@ -385,8 +385,6 @@
return DarwinArch.armv7;
case 'arm64':
return DarwinArch.arm64;
- case 'x86_64':
- return DarwinArch.x86_64;
}
assert(false);
return null;
diff --git a/packages/flutter_tools/lib/src/build_system/targets/ios.dart b/packages/flutter_tools/lib/src/build_system/targets/ios.dart
index 144196f..9b1ede5 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/ios.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/ios.dart
@@ -11,11 +11,8 @@
import '../../build_info.dart';
import '../../globals.dart' as globals;
import '../../macos/xcode.dart';
-import '../../project.dart';
import '../build_system.dart';
-import '../depfile.dart';
import '../exceptions.dart';
-import 'assets.dart';
import 'dart.dart';
/// Supports compiling a dart kernel file to an assembly file.
@@ -28,7 +25,7 @@
@override
Future<void> build(Environment environment) async {
final AOTSnapshotter snapshotter = AOTSnapshotter(reportTimings: false);
- final String buildOutputPath = environment.buildDir.path;
+ final String buildOutputPath = environment.outputDir.path;
if (environment.defines[kBuildMode] == null) {
throw MissingDefineException(kBuildMode, 'aot_assembly');
}
@@ -38,11 +35,8 @@
final bool bitcode = environment.defines[kBitcodeFlag] == 'true';
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
final TargetPlatform targetPlatform = getTargetPlatformForName(environment.defines[kTargetPlatform]);
- final List<DarwinArch> iosArchs = environment.defines[kIosArchs]
- ?.split(' ')
- ?.map(getIOSArchForName)
- ?.toList()
- ?? <DarwinArch>[DarwinArch.arm64];
+ final List<DarwinArch> iosArchs = environment.defines[kIosArchs]?.split(',')?.map(getIOSArchForName)?.toList()
+ ?? <DarwinArch>[DarwinArch.arm64];
if (targetPlatform != TargetPlatform.ios) {
throw Exception('aot_assembly is only supported for iOS applications');
}
@@ -66,7 +60,7 @@
if (results.any((int result) => result != 0)) {
throw Exception('AOT snapshotter exited with code ${results.join()}');
}
- final String resultPath = globals.fs.path.join(environment.buildDir.path, 'App.framework', 'App');
+ final String resultPath = globals.fs.path.join(environment.outputDir.path, 'App.framework', 'App');
globals.fs.directory(resultPath).parent.createSync(recursive: true);
final ProcessResult result = await globals.processManager.run(<String>[
'lipo',
@@ -151,202 +145,6 @@
];
}
-/// Create a trivial App.framework file for debug iOS builds.
-class DebugUniveralFramework extends Target {
- const DebugUniveralFramework();
-
- @override
- String get name => 'debug_universal_framework';
-
- @override
- List<Target> get dependencies => const <Target>[
- KernelSnapshot(),
- ];
-
- @override
- List<Source> get inputs => const <Source>[
- Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/ios.dart'),
- ];
-
- @override
- List<Source> get outputs => const <Source>[
- Source.pattern('{BUILD_DIR}/App')
- ];
-
- @override
- Future<void> build(Environment environment) async {
- // Generate a trivial App.framework.
- final File iphoneFile = environment.buildDir.childFile('iphone_framework');
- final File simulatorFile = environment.buildDir.childFile('simulator_framework');
- final File lipoOutputFile = environment.buildDir.childFile('App');
- final RunResult iphoneResult = await createStubAppFramework(
- iphoneFile,
- SdkType.iPhone,
- );
- final RunResult simulatorResult = await createStubAppFramework(
- simulatorFile,
- SdkType.iPhoneSimulator,
- );
- if (iphoneResult.exitCode != 0 || simulatorResult.exitCode != 0) {
- throw Exception('Failed to create App.framework.');
- }
- final List<String> lipoCommand = <String>[
- 'xcrun',
- 'lipo',
- '-create',
- iphoneFile.path,
- simulatorFile.path,
- '-output',
- lipoOutputFile.path
- ];
- final RunResult lipoResult = await processUtils.run(
- lipoCommand,
- );
-
- if (lipoResult.exitCode != 0) {
- throw Exception('Failed to create App.framework.');
- }
- }
-}
-
-/// The base class for all iOS bundle targets.
-///
-/// This is responsible for setting up the basic App.framework structure, including:
-/// * Copying the app.dill/kernel_blob.bin from the build directory to assets (debug)
-/// * Copying the precompiled isolate/vm data from the engine (debug)
-/// * Copying the flutter assets to App.framework/flutter_assets
-/// * Copying either the stub or real App assembly file to App.framework/App
-abstract class IosAssetBundle extends Target {
- const IosAssetBundle();
-
- @override
- List<Target> get dependencies => const <Target>[
- KernelSnapshot(),
- ];
-
- @override
- List<Source> get inputs => const <Source>[
- Source.pattern('{BUILD_DIR}/App'),
- Source.pattern('{PROJECT_DIR}/pubspec.yaml'),
- ];
-
- @override
- List<Source> get outputs => const <Source>[
- Source.pattern('{OUTPUT_DIR}/App.framework/App'),
- Source.pattern('{OUTPUT_DIR}/App.framework/Info.plist')
- ];
-
- @override
- List<String> get depfiles => <String>[
- 'flutter_assets.d',
- ];
-
- @override
- Future<void> build(Environment environment) async {
- if (environment.defines[kBuildMode] == null) {
- throw MissingDefineException(kBuildMode, name);
- }
- final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
- final Directory frameworkDirectory = environment.outputDir.childDirectory('App.framework');
- final Directory assetDirectory = frameworkDirectory.childDirectory('flutter_assets');
- frameworkDirectory.createSync(recursive: true);
- assetDirectory.createSync();
-
- // Only copy the prebuilt runtimes and kernel blob in debug mode.
- if (buildMode == BuildMode.debug) {
- // Copy the App.framework to the output directory.
- environment.buildDir.childFile('App')
- .copySync(frameworkDirectory.childFile('App').path);
-
- final String vmSnapshotData = globals.artifacts.getArtifactPath(Artifact.vmSnapshotData, mode: BuildMode.debug);
- final String isolateSnapshotData = globals.artifacts.getArtifactPath(Artifact.isolateSnapshotData, mode: BuildMode.debug);
- environment.buildDir.childFile('app.dill')
- .copySync(assetDirectory.childFile('kernel_blob.bin').path);
- globals.fs.file(vmSnapshotData)
- .copySync(assetDirectory.childFile('vm_snapshot_data').path);
- globals.fs.file(isolateSnapshotData)
- .copySync(assetDirectory.childFile('isolate_snapshot_data').path);
- } else {
- environment.buildDir.childDirectory('App.framework').childFile('App')
- .copySync(frameworkDirectory.childFile('App').path);
- }
-
- // Copy the assets.
- final Depfile assetDepfile = await copyAssets(environment, assetDirectory);
- assetDepfile.writeToFile(environment.buildDir.childFile('flutter_assets.d'));
-
-
- // Copy the plist from either the project or module.
- // TODO(jonahwilliams): add plist to inputs
- final FlutterProject flutterProject = FlutterProject.fromDirectory(environment.projectDir);
- final Directory plistRoot = flutterProject.isModule
- ? flutterProject.ios.ephemeralDirectory
- : environment.projectDir.childDirectory('ios');
- plistRoot
- .childDirectory('Flutter')
- .childFile('AppFrameworkInfo.plist')
- .copySync(environment.outputDir
- .childDirectory('App.framework')
- .childFile('Info.plist').path);
- }
-}
-
-/// Build a debug iOS application bundle.
-class DebugIosApplicationBundle extends IosAssetBundle {
- const DebugIosApplicationBundle();
-
- @override
- String get name => 'debug_ios_bundle_flutter_assets';
-
- @override
- List<Source> get inputs => <Source>[
- const Source.artifact(Artifact.vmSnapshotData, mode: BuildMode.debug),
- const Source.artifact(Artifact.isolateSnapshotData, mode: BuildMode.debug),
- const Source.pattern('{BUILD_DIR}/app.dill'),
- ...super.inputs,
- ];
-
- @override
- List<Source> get outputs => <Source>[
- const Source.pattern('{OUTPUT_DIR}/App.framework/flutter_assets/vm_snapshot_data'),
- const Source.pattern('{OUTPUT_DIR}/App.framework/flutter_assets/isolate_snapshot_data'),
- const Source.pattern('{OUTPUT_DIR}/App.framework/flutter_assets/kernel_blob.bin'),
- ...super.outputs,
- ];
-
- @override
- List<Target> get dependencies => <Target>[
- const DebugUniveralFramework(),
- ...super.dependencies,
- ];
-}
-
-/// Build a profile iOS application bundle.
-class ProfileIosApplicationBundle extends IosAssetBundle {
- const ProfileIosApplicationBundle();
-
- @override
- String get name => 'profile_ios_bundle_flutter_assets';
-
- @override
- List<Target> get dependencies => const <Target>[
- AotAssemblyProfile(),
- ];
-}
-
-/// Build a release iOS application bundle.
-class ReleaseIosApplicationBundle extends IosAssetBundle {
- const ReleaseIosApplicationBundle();
-
- @override
- String get name => 'release_ios_bundle_flutter_assets';
-
- @override
- List<Target> get dependencies => const <Target>[
- AotAssemblyRelease(),
- ];
-}
-
/// Create an App.framework for debug iOS targets.
///
/// This framework needs to exist for the Xcode project to link/bundle,
diff --git a/packages/flutter_tools/lib/src/commands/assemble.dart b/packages/flutter_tools/lib/src/commands/assemble.dart
index 6a8ca21..4d89483 100644
--- a/packages/flutter_tools/lib/src/commands/assemble.dart
+++ b/packages/flutter_tools/lib/src/commands/assemble.dart
@@ -50,9 +50,6 @@
androidArmReleaseBundle,
androidArm64ReleaseBundle,
androidx64ReleaseBundle,
- DebugIosApplicationBundle(),
- ProfileIosApplicationBundle(),
- ReleaseIosApplicationBundle(),
];
/// Assemble provides a low level API to interact with the flutter tool build
diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart
index 590887d..baa0699 100644
--- a/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart
@@ -315,7 +315,7 @@
}));
test('aot_assembly_profile will lipo binaries together when multiple archs are requested', () => testbed.run(() async {
- iosEnvironment.defines[kIosArchs] ='armv7 arm64';
+ iosEnvironment.defines[kIosArchs] ='armv7,arm64';
when(mockProcessManager.run(any)).thenAnswer((Invocation invocation) async {
globals.fs.file(globals.fs.path.join(iosEnvironment.buildDir.path, 'App.framework', 'App'))
.createSync(recursive: true);
@@ -360,7 +360,7 @@
}));
test('aot_assembly_profile with bitcode sends correct argument to snapshotter (mutli arch)', () => testbed.run(() async {
- iosEnvironment.defines[kIosArchs] = 'armv7 arm64';
+ iosEnvironment.defines[kIosArchs] = 'armv7,arm64';
iosEnvironment.defines[kBitcodeFlag] = 'true';
final FakeProcessResult fakeProcessResult = FakeProcessResult(
@@ -377,8 +377,9 @@
when(mockXcode.cc(any)).thenAnswer((_) => Future<RunResult>.value(fakeRunResult));
when(mockXcode.clang(any)).thenAnswer((_) => Future<RunResult>.value(fakeRunResult));
- await const AotAssemblyProfile().build(iosEnvironment);
+ final BuildResult result = await buildSystem.build(const AotAssemblyProfile(), iosEnvironment);
+ expect(result.success, true);
verify(mockXcode.cc(argThat(contains('-fembed-bitcode')))).called(2);
verify(mockXcode.clang(argThat(contains('-fembed-bitcode')))).called(2);
}, overrides: <Type, Generator>{
@@ -387,7 +388,7 @@
}));
test('aot_assembly_profile will lipo binaries together when multiple archs are requested', () => testbed.run(() async {
- iosEnvironment.defines[kIosArchs] = 'armv7 arm64';
+ iosEnvironment.defines[kIosArchs] = 'armv7,arm64';
when(mockProcessManager.run(any)).thenAnswer((Invocation invocation) async {
globals.fs.file(globals.fs.path.join(iosEnvironment.buildDir.path, 'App.framework', 'App'))
.createSync(recursive: true);
diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart
deleted file mode 100644
index 2582b5c..0000000
--- a/packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2014 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'package:file_testing/file_testing.dart';
-import 'package:flutter_tools/src/artifacts.dart';
-import 'package:flutter_tools/src/base/file_system.dart';
-import 'package:flutter_tools/src/build_info.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/ios.dart';
-import 'package:flutter_tools/src/globals.dart' as globals;
-import 'package:mockito/mockito.dart';
-
-import '../../../src/common.dart';
-import '../../../src/fake_process_manager.dart';
-import '../../../src/testbed.dart';
-
-const List<String> _kSharedConfig = <String>[
- '-dynamiclib',
- '-fembed-bitcode-marker',
- '-Xlinker',
- '-rpath',
- '-Xlinker',
- '@executable_path/Frameworks',
- '-Xlinker',
- '-rpath',
- '-Xlinker',
- '@loader_path/Frameworks',
- '-install_name',
- '@rpath/App.framework/App',
- '-isysroot',
-];
-
-void main() {
- Testbed testbed;
- Environment environment;
- ProcessManager processManager;
-
- setUp(() {
- testbed = Testbed(setup: () {
- environment = Environment.test(globals.fs.currentDirectory, defines: <String, String>{
- kTargetPlatform: 'ios',
- });
- });
- });
-
- test('DebugUniveralFramework creates expected binary', () => testbed.run(() async {
- processManager = FakeProcessManager.list(<FakeCommand>[
- // Create iphone stub.
- const FakeCommand(command: <String>['xcrun', '--sdk', 'iphoneos', '--show-sdk-path']),
- FakeCommand(command: <String>[
- 'xcrun',
- 'clang',
- '-x',
- 'c',
- // iphone gets both arm arches
- '-arch',
- 'armv7',
- '-arch',
- 'arm64',
- globals.fs.path.absolute(globals.fs.path.join('.tmp_rand0', 'flutter_tools_stub_source.rand0', 'debug_app.cc')),
- ..._kSharedConfig,
- '',
- '-o',
- environment.buildDir.childFile('iphone_framework').path
- ]),
- // Create simulator stub.
- const FakeCommand(command: <String>['xcrun', '--sdk', 'iphonesimulator', '--show-sdk-path']),
- FakeCommand(command: <String>[
- 'xcrun',
- 'clang',
- '-x',
- 'c',
- // Simulator only as x86_64 arch
- '-arch',
- 'x86_64',
- globals.fs.path.absolute(globals.fs.path.join('.tmp_rand0', 'flutter_tools_stub_source.rand0', 'debug_app.cc')),
- ..._kSharedConfig,
- '',
- '-o',
- environment.buildDir.childFile('simulator_framework').path
- ]),
- // Lipo stubs together.
- FakeCommand(command: <String>[
- 'xcrun',
- 'lipo',
- '-create',
- environment.buildDir.childFile('iphone_framework').path,
- environment.buildDir.childFile('simulator_framework').path,
- '-output',
- environment.buildDir.childFile('App').path,
- ]),
- ]);
-
- await const DebugUniveralFramework().build(environment);
- }, overrides: <Type, Generator>{
- ProcessManager: () => processManager,
- }));
-
- test('DebugIosApplicationBundle', () => testbed.run(() async {
- environment.defines[kBuildMode] = 'debug';
- // Precompiled dart data
- when(globals.artifacts.getArtifactPath(Artifact.vmSnapshotData, mode: BuildMode.debug))
- .thenReturn('vm_snapshot_data');
- when(globals.artifacts.getArtifactPath(Artifact.isolateSnapshotData, mode: BuildMode.debug))
- .thenReturn('isolate_snapshot_data');
- globals.fs.file('vm_snapshot_data').createSync();
- globals.fs.file('isolate_snapshot_data').createSync();
- // Project info
- globals.fs.file('pubspec.yaml').writeAsStringSync('name: hello');
- globals.fs.file('.packages').writeAsStringSync('\n');
- // Plist file
- globals.fs.file(globals.fs.path.join('ios', 'Flutter', 'AppFrameworkInfo.plist'))
- ..createSync(recursive: true);
- // App kernel
- environment.buildDir.childFile('app.dill').createSync(recursive: true);
- // Stub framework
- environment.buildDir.childFile('App').createSync();
-
- await const DebugIosApplicationBundle().build(environment);
-
- final Directory frameworkDirectory = environment.outputDir.childDirectory('App.framework');
- expect(frameworkDirectory.childFile('App'), exists);
- expect(frameworkDirectory.childFile('Info.plist'), exists);
-
- final Directory assetDirectory = frameworkDirectory.childDirectory('flutter_assets');
- expect(assetDirectory.childFile('kernel_blob.bin'), exists);
- expect(assetDirectory.childFile('AssetManifest.json'), exists);
- expect(assetDirectory.childFile('vm_snapshot_data'), exists);
- expect(assetDirectory.childFile('isolate_snapshot_data'), exists);
- }, overrides: <Type, Generator>{
- Artifacts: () => MockArtifacts(),
- }));
-
- test('ReleaseIosApplicationBundle', () => testbed.run(() async {
- environment.defines[kBuildMode] = 'release';
-
- // Project info
- globals.fs.file('pubspec.yaml').writeAsStringSync('name: hello');
- globals.fs.file('.packages').writeAsStringSync('\n');
- // Plist file
- globals.fs.file(globals.fs.path.join('ios', 'Flutter', 'AppFrameworkInfo.plist'))
- ..createSync(recursive: true);
-
- // Real framework
- environment.buildDir
- .childDirectory('App.framework')
- .childFile('App')
- .createSync(recursive: true);
-
- await const ReleaseIosApplicationBundle().build(environment);
-
- final Directory frameworkDirectory = environment.outputDir.childDirectory('App.framework');
- expect(frameworkDirectory.childFile('App'), exists);
- expect(frameworkDirectory.childFile('Info.plist'), exists);
-
- final Directory assetDirectory = frameworkDirectory.childDirectory('flutter_assets');
- expect(assetDirectory.childFile('kernel_blob.bin'), isNot(exists));
- expect(assetDirectory.childFile('AssetManifest.json'), exists);
- expect(assetDirectory.childFile('vm_snapshot_data'), isNot(exists));
- expect(assetDirectory.childFile('isolate_snapshot_data'), isNot(exists));
- }));
-}
-
-class MockArtifacts extends Mock implements Artifacts {}