Commit 2099d378 authored by Todd Volkert's avatar Todd Volkert Committed by GitHub

Pull iOS build templates from flutter tools vs engine artifacts (#4526)

parent c9bcf107
...@@ -64,3 +64,26 @@ void ensureDirectoryExists(String filePath) { ...@@ -64,3 +64,26 @@ void ensureDirectoryExists(String filePath) {
return; return;
syncFs.directory(dirPath).create(recursive: true); syncFs.directory(dirPath).create(recursive: true);
} }
/// Recursively copies a folder from `srcPath` to `destPath`
void copyFolderSync(String srcPath, String destPath) {
dart_io.Directory srcDir = new dart_io.Directory(srcPath);
if (!srcDir.existsSync())
throw new Exception('Source directory "${srcDir.path}" does not exist, nothing to copy');
dart_io.Directory destDir = new dart_io.Directory(destPath);
if (!destDir.existsSync())
destDir.createSync(recursive: true);
srcDir.listSync().forEach((dart_io.FileSystemEntity entity) {
String newPath = path.join(destDir.path, path.basename(entity.path));
if (entity is dart_io.File) {
dart_io.File newFile = new dart_io.File(newPath);
newFile.writeAsBytesSync(entity.readAsBytesSync());
} else if (entity is dart_io.Directory) {
copyFolderSync(entity.path, newPath);
} else {
throw new Exception('${entity.path} is neither File nor Directory');
}
});
}
...@@ -12,7 +12,6 @@ import '../application_package.dart'; ...@@ -12,7 +12,6 @@ import '../application_package.dart';
import '../base/context.dart'; import '../base/context.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../cache.dart';
import '../flx.dart' as flx; import '../flx.dart' as flx;
import '../globals.dart'; import '../globals.dart';
import '../services.dart'; import '../services.dart';
...@@ -114,12 +113,9 @@ Future<XcodeBuildResult> buildXcodeProject({ ...@@ -114,12 +113,9 @@ Future<XcodeBuildResult> buildXcodeProject({
return new XcodeBuildResult(false); return new XcodeBuildResult(false);
} }
} else { } else {
updateXcodeGeneratedProperties(flutterProjectPath, mode, target); updateXcodeGeneratedProperties(flutterProjectPath, mode, target);
} }
if (!_validateEngineRevision(app))
return new XcodeBuildResult(false);
if (!_checkXcodeVersion()) if (!_checkXcodeVersion())
return new XcodeBuildResult(false); return new XcodeBuildResult(false);
...@@ -200,31 +196,6 @@ bool _checkXcodeVersion() { ...@@ -200,31 +196,6 @@ bool _checkXcodeVersion() {
return true; return true;
} }
bool _validateEngineRevision(ApplicationPackage app) {
String skyRevision = Cache.engineRevision;
String iosRevision = _getIOSEngineRevision(app);
if (iosRevision != skyRevision) {
printError("Error: incompatible sky_engine revision.");
printStatus('sky_engine revision: $skyRevision, iOS engine revision: $iosRevision');
return false;
} else {
printTrace('sky_engine revision: $skyRevision, iOS engine revision: $iosRevision');
return true;
}
}
String _getIOSEngineRevision(ApplicationPackage app) {
File revisionFile = new File(path.join(app.rootPath, 'REVISION'));
if (revisionFile.existsSync()) {
// The format is 'REVISION-mode'. We only need the revision.
String revisionStamp = revisionFile.readAsStringSync().trim();
return revisionStamp.split('-')[0];
} else {
return null;
}
}
Future<Null> _addServicesToBundle(Directory bundle) async { Future<Null> _addServicesToBundle(Directory bundle) async {
List<Map<String, String>> services = <Map<String, String>>[]; List<Map<String, String>> services = <Map<String, String>>[];
printTrace("Trying to resolve native pub services."); printTrace("Trying to resolve native pub services.");
......
...@@ -7,52 +7,11 @@ import 'dart:io'; ...@@ -7,52 +7,11 @@ import 'dart:io';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import '../base/process.dart'; import '../base/file_system.dart' show copyFolderSync;
import '../build_info.dart'; import '../build_info.dart';
import '../cache.dart'; import '../cache.dart';
import '../globals.dart'; import '../globals.dart';
import '../version.dart';
bool _inflateXcodeArchive(String directory, List<int> archiveBytes) {
printStatus('Unzipping Xcode project to local directory...');
// We cannot use ArchiveFile because this archive contains files that are exectuable
// and there is currently no provision to modify file permissions during
// or after creation. See https://github.com/dart-lang/sdk/issues/15078.
// So we depend on the platform to unzip the archive for us.
Directory tempDir = Directory.systemTemp.createTempSync('flutter_xcode');
File tempFile = new File(path.join(tempDir.path, 'FlutterXcode.zip'))..createSync();
tempFile.writeAsBytesSync(archiveBytes);
try {
Directory dir = new Directory(directory);
// Remove the old generated project if one is present
if (dir.existsSync())
dir.deleteSync(recursive: true);
// Create the directory so unzip can write to it
dir.createSync(recursive: true);
// Unzip the Xcode project into the new empty directory
runCheckedSync(<String>['/usr/bin/unzip', tempFile.path, '-d', dir.path]);
} catch (error) {
printTrace('$error');
return false;
}
// Cleanup the temp directory after unzipping
tempDir.deleteSync(recursive: true);
// Verify that we have an Xcode project
Directory flutterProj = new Directory(path.join(directory, 'FlutterApplication.xcodeproj'));
if (!flutterProj.existsSync()) {
printError("${flutterProj.path} does not exist");
return false;
}
return true;
}
void updateXcodeGeneratedProperties(String projectPath, BuildMode mode, String target) { void updateXcodeGeneratedProperties(String projectPath, BuildMode mode, String target) {
StringBuffer localsBuffer = new StringBuffer(); StringBuffer localsBuffer = new StringBuffer();
...@@ -93,7 +52,7 @@ bool xcodeProjectRequiresUpdate(BuildMode mode) { ...@@ -93,7 +52,7 @@ bool xcodeProjectRequiresUpdate(BuildMode mode) {
return true; return true;
} }
if (revisionFile.readAsStringSync() != '${Cache.engineRevision}-${getModeName(mode)}') { if (revisionFile.readAsStringSync() != _getCurrentXcodeRevisionString(mode)) {
printTrace("The revision stamp and the Flutter engine revision differ or the build mode has changed."); printTrace("The revision stamp and the Flutter engine revision differ or the build mode has changed.");
printTrace("Project needs to be updated."); printTrace("Project needs to be updated.");
return true; return true;
...@@ -104,36 +63,27 @@ bool xcodeProjectRequiresUpdate(BuildMode mode) { ...@@ -104,36 +63,27 @@ bool xcodeProjectRequiresUpdate(BuildMode mode) {
} }
Future<int> setupXcodeProjectHarness(String flutterProjectPath, BuildMode mode, String target) async { Future<int> setupXcodeProjectHarness(String flutterProjectPath, BuildMode mode, String target) async {
// Step 1: Fetch the archive from the cloud // Step 1: Copy templates into user project directory
String iosFilesPath = path.join(flutterProjectPath, 'ios'); String iosFilesPath = path.join(flutterProjectPath, 'ios');
String xcodeprojPath = path.join(iosFilesPath, '.generated'); String xcodeProjectPath = path.join(iosFilesPath, '.generated');
String templatesPath = path.join(Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'build-ios');
copyFolderSync(templatesPath, xcodeProjectPath);
Directory toolDir = tools.getEngineArtifactsDirectory(TargetPlatform.ios, mode); // Step 2: Populate the Generated.xcconfig with project specific paths
File archiveFile = new File(path.join(toolDir.path, 'FlutterXcode.zip'));
List<int> archiveBytes = archiveFile.readAsBytesSync();
if (archiveBytes.isEmpty) {
printError('Error: No archive bytes received.');
return 1;
}
// Step 2: Inflate the archive into the user project directory
bool result = _inflateXcodeArchive(xcodeprojPath, archiveBytes);
if (!result) {
printError('Could not inflate the Xcode project archive.');
return 1;
}
// Step 3: Populate the Generated.xcconfig with project specific paths
updateXcodeGeneratedProperties(flutterProjectPath, mode, target); updateXcodeGeneratedProperties(flutterProjectPath, mode, target);
// Step 4: Write the REVISION file // Step 3: Write the REVISION file
File revisionFile = new File(path.join(xcodeprojPath, 'REVISION')); File revisionFile = new File(path.join(xcodeProjectPath, 'REVISION'));
revisionFile.createSync(); revisionFile.createSync();
revisionFile.writeAsStringSync('${Cache.engineRevision}-${getModeName(mode)}'); revisionFile.writeAsStringSync(_getCurrentXcodeRevisionString(mode));
// Step 5: Tell the user the location of the generated project. // Step 4: Tell the user the location of the generated project.
printStatus('Xcode project created in $iosFilesPath/.'); printStatus('Xcode project created in $iosFilesPath/.');
return 0; return 0;
} }
String _getCurrentXcodeRevisionString(BuildMode mode) => (new StringBuffer()
..write('${FlutterVersion.getVersion().frameworkRevision}')
..write('-${tools.isLocalEngine ? tools.engineBuildPath : getModeName(mode)}')
).toString();
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:FlutterApplication.xcodeproj">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9E07CF991BE8280A00BCD8DE"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:FlutterApplication.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9E07CF991BE8280A00BCD8DE"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:FlutterApplication.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9E07CF991BE8280A00BCD8DE"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:FlutterApplication.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "--no-redirect-to-syslog"
isEnabled = "YES">
</CommandLineArgument>
<CommandLineArgument
argument = "--observatory-port=8181"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9E07CF991BE8280A00BCD8DE"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:FlutterApplication.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9E07CF851BE7F4D200BCD8DE"
BuildableName = "FlutterApplication.framework"
BlueprintName = "FlutterApplication"
ReferencedContainer = "container:FlutterApplication.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9E07CF851BE7F4D200BCD8DE"
BuildableName = "FlutterApplication.framework"
BlueprintName = "FlutterApplication"
ReferencedContainer = "container:FlutterApplication.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9E07CF851BE7F4D200BCD8DE"
BuildableName = "FlutterApplication.framework"
BlueprintName = "FlutterApplication"
ReferencedContainer = "container:FlutterApplication.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>9E07CF991BE8280A00BCD8DE</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
// Copyright 2016 The Chromium 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 <UIKit/UIKit.h>
#import <Flutter/Flutter.h>
int main(int argc, const char* argv[]) {
FlutterInit(argc, argv);
return UIApplicationMain(argc, (char**)argv, nil,
NSStringFromClass([FlutterAppDelegate class]));
}
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