// 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 'dart:async'; import 'dart:io'; import 'package:path/path.dart' as path; import '../base/file_system.dart' show copyFolderSync; import '../build_info.dart'; import '../cache.dart'; import '../globals.dart'; import '../version.dart'; void updateXcodeGeneratedProperties(String projectPath, BuildMode mode, String target) { StringBuffer localsBuffer = new StringBuffer(); localsBuffer.writeln('// This is a generated file; do not edit or check into version control.'); String flutterRoot = path.normalize(Cache.flutterRoot); localsBuffer.writeln('FLUTTER_ROOT=$flutterRoot'); // This holds because requiresProjectRoot is true for this command String applicationRoot = path.normalize(Directory.current.path); localsBuffer.writeln('FLUTTER_APPLICATION_PATH=$applicationRoot'); // Relative to FLUTTER_APPLICATION_PATH, which is [Directory.current]. localsBuffer.writeln('FLUTTER_TARGET=$target'); // The runtime mode for the current build. localsBuffer.writeln('FLUTTER_BUILD_MODE=${getModeName(mode)}'); String flutterFrameworkDir = path.normalize(tools.getEngineArtifactsDirectory(TargetPlatform.ios, mode).path); localsBuffer.writeln('FLUTTER_FRAMEWORK_DIR=$flutterFrameworkDir'); if (tools.isLocalEngine) localsBuffer.writeln('LOCAL_ENGINE=${tools.engineBuildPath}'); File localsFile = new File(path.join(projectPath, 'ios', '.generated', 'Flutter', 'Generated.xcconfig')); localsFile.createSync(recursive: true); localsFile.writeAsStringSync(localsBuffer.toString()); } bool xcodeProjectRequiresUpdate(BuildMode mode) { File revisionFile = new File(path.join(Directory.current.path, 'ios', '.generated', 'REVISION')); // If the revision stamp does not exist, the Xcode project definitely requires // an update if (!revisionFile.existsSync()) { printTrace("A revision stamp does not exist. The Xcode project has never been initialized."); return true; } if (revisionFile.readAsStringSync() != _getCurrentXcodeRevisionString(mode)) { printTrace("The revision stamp and the Flutter engine revision differ or the build mode has changed."); printTrace("Project needs to be updated."); return true; } printTrace("Xcode project is up to date."); return false; } Future setupXcodeProjectHarness(String flutterProjectPath, BuildMode mode, String target) async { // Step 1: Copy templates into user project directory String iosFilesPath = path.join(flutterProjectPath, 'ios'); String xcodeProjectPath = path.join(iosFilesPath, '.generated'); String templatesPath = path.join(Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'build-ios'); copyFolderSync(templatesPath, xcodeProjectPath); // Step 2: Populate the Generated.xcconfig with project specific paths updateXcodeGeneratedProperties(flutterProjectPath, mode, target); // Step 3: Write the REVISION file File revisionFile = new File(path.join(xcodeProjectPath, 'REVISION')); revisionFile.createSync(); revisionFile.writeAsStringSync(_getCurrentXcodeRevisionString(mode)); // Step 4: Tell the user the location of the generated project. printStatus('Xcode project created in $iosFilesPath/.'); return 0; } String _getCurrentXcodeRevisionString(BuildMode mode) => (new StringBuffer() ..write('${FlutterVersion.getVersion().frameworkRevision}') ..write('-${tools.isLocalEngine ? tools.engineBuildPath : getModeName(mode)}') ).toString();