Unverified Commit 9184f4d6 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Build iOS frameworks with relative output path (#47369)

parent beb86d2c
......@@ -45,19 +45,20 @@ Future<void> main() async {
// This builds all build modes' frameworks by default
section('Build frameworks');
const String outputDirectoryName = 'flutter-frameworks';
await inDirectory(projectDir, () async {
await flutter(
'build',
options: <String>['ios-framework'],
options: <String>[
'ios-framework',
'--xcframework',
'--output=$outputDirectoryName'
],
);
});
final String outputPath = path.join(
projectDir.path,
'build',
'ios',
'framework',
);
final String outputPath = path.join(projectDir.path, outputDirectoryName);
section('Check debug build has Dart snapshot as asset');
......@@ -157,6 +158,22 @@ Future<void> main() async {
'Flutter.framework',
'Flutter',
));
checkFileExists(path.join(
outputPath,
mode,
'Flutter.xcframework',
'ios-armv7_arm64',
'Flutter.framework',
'Flutter',
));
checkFileExists(path.join(
outputPath,
mode,
'Flutter.xcframework',
'ios-x86_64-simulator',
'Flutter.framework',
'Flutter',
));
}
section("Check all modes' engine header");
......@@ -177,6 +194,22 @@ Future<void> main() async {
'device_info.framework',
'device_info',
));
checkFileExists(path.join(
outputPath,
mode,
'device_info.xcframework',
'ios-armv7_arm64',
'device_info.framework',
'device_info',
));
checkFileExists(path.join(
outputPath,
mode,
'device_info.xcframework',
'ios-x86_64-simulator',
'device_info.framework',
'device_info',
));
}
section("Check all modes' have generated plugin registrant");
......@@ -189,6 +222,24 @@ Future<void> main() async {
'Headers',
'GeneratedPluginRegistrant.h',
));
checkFileExists(path.join(
outputPath,
mode,
'FlutterPluginRegistrant.xcframework',
'ios-armv7_arm64',
'FlutterPluginRegistrant.framework',
'Headers',
'GeneratedPluginRegistrant.h',
));
checkFileExists(path.join(
outputPath,
mode,
'FlutterPluginRegistrant.xcframework',
'ios-x86_64-simulator',
'FlutterPluginRegistrant.framework',
'Headers',
'GeneratedPluginRegistrant.h',
));
}
return TaskResult.success(null);
......
......@@ -146,7 +146,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
throwToolExit("Module's iOS folder missing");
}
final Directory outputDirectory = fs.directory(fs.path.normalize(outputArgument));
final Directory outputDirectory = fs.directory(fs.path.absolute(fs.path.normalize(outputArgument)));
aotBuilder ??= AotBuilder();
bundleBuilder ??= BundleBuilder();
......@@ -175,6 +175,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
}
final Status status = logger.startProgress(' └─Moving to ${fs.path.relative(modeDirectory.path)}', timeout: timeoutConfiguration.slowOperation);
try {
// Delete the intermediaries since they would have been copied into our
// output frameworks.
if (iPhoneBuildOutput.existsSync()) {
......@@ -183,8 +184,10 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
if (simulatorBuildOutput.existsSync()) {
simulatorBuildOutput.deleteSync(recursive: true);
}
} finally {
status.stop();
}
}
printStatus('Frameworks written to ${outputDirectory.path}.');
......@@ -192,7 +195,8 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
}
Future<void> _produceFlutterFramework(Directory outputDirectory, BuildMode mode, Directory iPhoneBuildOutput, Directory simulatorBuildOutput, Directory modeDirectory) async {
final Status status = logger.startProgress(' ├─Populating Flutter.framework...', timeout: timeoutConfiguration.fastOperation);
final Status status = logger.startProgress(' ├─Populating Flutter.framework...', timeout: timeoutConfiguration.slowOperation);
try {
final String engineCacheFlutterFrameworkDirectory = artifacts.getArtifactPath(Artifact.flutterFramework, platform: TargetPlatform.ios, mode: mode);
// Copy universal engine cache framework to mode directory.
......@@ -210,12 +214,16 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
// Create iOS framework.
List<String> lipoCommand = <String>['xcrun', 'lipo', fatFlutterFrameworkBinary.path, '-remove', 'x86_64', '-output', armFlutterFrameworkBinary.path];
await processUtils.run(
RunResult lipoResult = processUtils.runSync(
lipoCommand,
workingDirectory: outputDirectory.path,
allowReentrantFlutter: false,
);
if (lipoResult.exitCode != 0) {
throwToolExit('Unable to create ARM engine framework: ${lipoResult.stderr}');
}
// Create simulator framework.
final Directory simulatorFlutterFrameworkDirectory = simulatorBuildOutput.childDirectory(flutterFrameworkFileName);
final File simulatorFlutterFrameworkBinary = simulatorFlutterFrameworkDirectory.childFile('Flutter');
......@@ -223,12 +231,16 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
lipoCommand = <String>['xcrun', 'lipo', fatFlutterFrameworkBinary.path, '-thin', 'x86_64', '-output', simulatorFlutterFrameworkBinary.path];
await processUtils.run(
lipoResult = processUtils.runSync(
lipoCommand,
workingDirectory: outputDirectory.path,
allowReentrantFlutter: false,
);
if (lipoResult.exitCode != 0) {
throwToolExit('Unable to create simulator engine framework: ${lipoResult.stderr}');
}
// Create XCFramework from iOS and simulator frameworks.
final List<String> xcframeworkCommand = <String>[
'xcrun',
......@@ -241,18 +253,24 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
.path
];
await processUtils.run(
final RunResult xcframeworkResult = processUtils.runSync(
xcframeworkCommand,
workingDirectory: outputDirectory.path,
allowReentrantFlutter: false,
);
if (xcframeworkResult.exitCode != 0) {
throwToolExit('Unable to create engine XCFramework: ${xcframeworkResult.stderr}');
}
}
if (!boolArg('universal')) {
fatFlutterFrameworkCopy.deleteSync(recursive: true);
}
} finally {
status.stop();
}
}
Future<void> _produceAppFramework(BuildMode mode, Directory iPhoneBuildOutput, Directory simulatorBuildOutput, Directory modeDirectory) async {
const String appFrameworkName = 'App.framework';
......@@ -261,8 +279,11 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
if (mode == BuildMode.debug) {
final Status status = logger.startProgress(' ├─Add placeholder App.framework for debug...', timeout: timeoutConfiguration.fastOperation);
try {
await _produceStubAppFrameworkIfNeeded(mode, iPhoneBuildOutput, simulatorBuildOutput, destinationAppFrameworkDirectory);
} finally {
status.stop();
}
} else {
await _produceAotAppFrameworkIfNeeded(mode, iPhoneBuildOutput, destinationAppFrameworkDirectory);
}
......@@ -273,6 +294,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
destinationInfoPlist.writeAsBytesSync(sourceInfoPlist.readAsBytesSync());
final Status status = logger.startProgress(' ├─Assembling Flutter resources for App.framework...', timeout: timeoutConfiguration.slowOperation);
try {
await bundleBuilder.build(
platform: TargetPlatform.ios,
buildMode: mode,
......@@ -281,8 +303,10 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
assetDirPath: destinationAppFrameworkDirectory.childDirectory('flutter_assets').path,
precompiledSnapshot: mode != BuildMode.debug,
);
} finally {
status.stop();
}
}
Future<void> _produceStubAppFrameworkIfNeeded(BuildMode mode, Directory iPhoneBuildOutput, Directory simulatorBuildOutput, Directory destinationAppFrameworkDirectory) async {
if (mode != BuildMode.debug) {
......@@ -309,10 +333,14 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
destinationAppFrameworkDirectory.childFile(binaryName).path
];
await processUtils.run(
final RunResult lipoResult = processUtils.runSync(
lipoCommand,
allowReentrantFlutter: false,
);
if (lipoResult.exitCode != 0) {
throwToolExit('Unable to create compiled dart universal framework: ${lipoResult.stderr}');
}
}
Future<void> _produceAotAppFrameworkIfNeeded(BuildMode mode, Directory iPhoneBuildOutput, Directory destinationAppFrameworkDirectory) async {
......@@ -320,6 +348,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
return;
}
final Status status = logger.startProgress(' ├─Building Dart AOT for App.framework...', timeout: timeoutConfiguration.slowOperation);
try {
await aotBuilder.build(
platform: TargetPlatform.ios,
outputPath: iPhoneBuildOutput.path,
......@@ -335,8 +364,10 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
const String appFrameworkName = 'App.framework';
copyDirectorySync(iPhoneBuildOutput.childDirectory(appFrameworkName), destinationAppFrameworkDirectory);
} finally {
status.stop();
}
}
Future<void> _producePlugins(
String xcodeBuildConfiguration,
......@@ -346,6 +377,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
Directory outputDirectory,
) async {
final Status status = logger.startProgress(' ├─Building plugins...', timeout: timeoutConfiguration.slowOperation);
try {
List<String> pluginsBuildCommand = <String>[
'xcrun',
'xcodebuild',
......@@ -358,12 +390,16 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
'ONLY_ACTIVE_ARCH=NO' // No device targeted, so build all valid architectures.
];
await processUtils.run(
RunResult buildPluginsResult = processUtils.runSync(
pluginsBuildCommand,
workingDirectory: _project.ios.hostAppRoot.childDirectory('Pods').path,
allowReentrantFlutter: false,
);
if (buildPluginsResult.exitCode != 0) {
throwToolExit('Unable to build plugin frameworks: ${buildPluginsResult.stderr}');
}
pluginsBuildCommand = <String>[
'xcrun',
'xcodebuild',
......@@ -377,12 +413,16 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
'ONLY_ACTIVE_ARCH=NO' // No device targeted, so build all valid architectures.
];
await processUtils.run(
buildPluginsResult = processUtils.runSync(
pluginsBuildCommand,
workingDirectory: _project.ios.hostAppRoot.childDirectory('Pods').path,
allowReentrantFlutter: false,
);
if (buildPluginsResult.exitCode != 0) {
throwToolExit('Unable to build plugin frameworks for simulator: ${buildPluginsResult.stderr}');
}
final Directory iPhoneBuildConfiguration = iPhoneBuildOutput.childDirectory('$xcodeBuildConfiguration-iphoneos');
final Directory simulatorBuildConfiguration = simulatorBuildOutput.childDirectory('$xcodeBuildConfiguration-iphonesimulator');
......@@ -403,11 +443,15 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
modeDirectory.childDirectory(podFrameworkName).childFile(binaryName).path
];
await processUtils.run(
final RunResult pluginsLipoResult = processUtils.runSync(
lipoCommand,
workingDirectory: outputDirectory.path,
allowReentrantFlutter: false,
);
if (pluginsLipoResult.exitCode != 0) {
throwToolExit('Unable to create universal $binaryName.framework: ${buildPluginsResult.stderr}');
}
}
if (boolArg('xcframework')) {
......@@ -423,15 +467,21 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
modeDirectory.childFile('$binaryName.xcframework').path
];
await processUtils.run(
final RunResult xcframeworkResult = processUtils.runSync(
xcframeworkCommand,
workingDirectory: outputDirectory.path,
allowReentrantFlutter: false,
);
if (xcframeworkResult.exitCode != 0) {
throwToolExit('Unable to create $binaryName.xcframework: ${xcframeworkResult.stderr}');
}
}
}
}
}
} finally {
status.stop();
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment