Commit b5f763b4 authored by Chris Bracken's avatar Chris Bracken Committed by GitHub

Support a configurable build directory (#5601)

This change adds a top-level getBuildDirectory func and funcs for
android, aot, asset, ios build products.

Developers may now add a "build-dir" mapping to their
~/.flutter_settings (JSON format) config file. Output directory is
relative to the main flutter application directory.

This change also changes the default build directory for iOS builds to a
subdirectory of the configured build directory, 'build/ios' by default.
parent 852a00a1
...@@ -65,7 +65,7 @@ BuildApp() { ...@@ -65,7 +65,7 @@ BuildApp() {
AssertExists ${target_path} AssertExists ${target_path}
local build_dir=${SYMROOT:-build} local build_dir=${FLUTTER_BUILD_DIR:-build}
local local_engine_flag="" local local_engine_flag=""
if [[ -n "$LOCAL_ENGINE" ]]; then if [[ -n "$LOCAL_ENGINE" ]]; then
local_engine_flag="--local-engine=$LOCAL_ENGINE" local_engine_flag="--local-engine=$LOCAL_ENGINE"
......
...@@ -83,7 +83,7 @@ class AndroidApk extends ApplicationPackage { ...@@ -83,7 +83,7 @@ class AndroidApk extends ApplicationPackage {
apkPath = gradleAppOut; apkPath = gradleAppOut;
} else { } else {
manifestPath = path.join('android', 'AndroidManifest.xml'); manifestPath = path.join('android', 'AndroidManifest.xml');
apkPath = path.join('build', 'app.apk'); apkPath = path.join(getAndroidBuildDirectory(), 'app.apk');
} }
if (!FileSystemEntity.isFileSync(manifestPath)) if (!FileSystemEntity.isFileSync(manifestPath))
...@@ -157,7 +157,7 @@ class IOSApp extends ApplicationPackage { ...@@ -157,7 +157,7 @@ class IOSApp extends ApplicationPackage {
String get deviceBundlePath => _buildAppPath('iphoneos'); String get deviceBundlePath => _buildAppPath('iphoneos');
String _buildAppPath(String type) { String _buildAppPath(String type) {
return path.join(appDirectory, 'build', 'Release-$type', kBundleName); return path.join(getIosBuildDirectory(), 'Release-$type', kBundleName);
} }
} }
......
...@@ -10,6 +10,7 @@ import 'package:json_schema/json_schema.dart'; ...@@ -10,6 +10,7 @@ import 'package:json_schema/json_schema.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'package:yaml/yaml.dart'; import 'package:yaml/yaml.dart';
import 'build_info.dart';
import 'cache.dart'; import 'cache.dart';
import 'dart/package_map.dart'; import 'dart/package_map.dart';
import 'globals.dart'; import 'globals.dart';
...@@ -48,7 +49,6 @@ class AssetBundle { ...@@ -48,7 +49,6 @@ class AssetBundle {
final Set<AssetBundleEntry> entries = new Set<AssetBundleEntry>(); final Set<AssetBundleEntry> entries = new Set<AssetBundleEntry>();
static const String defaultManifestPath = 'flutter.yaml'; static const String defaultManifestPath = 'flutter.yaml';
static const String defaultWorkingDirPath = 'build/flx';
static const String _kFontSetMaterial = 'material'; static const String _kFontSetMaterial = 'material';
static const String _kFontSetRoboto = 'roboto'; static const String _kFontSetRoboto = 'roboto';
...@@ -67,10 +67,11 @@ class AssetBundle { ...@@ -67,10 +67,11 @@ class AssetBundle {
Future<int> build({ Future<int> build({
String manifestPath: defaultManifestPath, String manifestPath: defaultManifestPath,
String workingDirPath: defaultWorkingDirPath, String workingDirPath,
bool includeRobotoFonts: true, bool includeRobotoFonts: true,
bool reportLicensedPackages: false bool reportLicensedPackages: false
}) async { }) async {
workingDirPath ??= getAssetBuildDirectory();
Object manifest = _loadFlutterYamlManifest(manifestPath); Object manifest = _loadFlutterYamlManifest(manifestPath);
if (manifest == null) { if (manifest == null) {
// No manifest file found for this application. // No manifest file found for this application.
...@@ -94,7 +95,7 @@ class AssetBundle { ...@@ -94,7 +95,7 @@ class AssetBundle {
packageMap, packageMap,
manifestDescriptor, manifestDescriptor,
assetBasePath, assetBasePath,
excludeDirs: <String>[workingDirPath, path.join(assetBasePath, 'build')] excludeDirs: <String>[workingDirPath, getBuildDirectory()]
); );
if (assetVariants == null) if (assetVariants == null)
......
...@@ -19,6 +19,8 @@ class Config { ...@@ -19,6 +19,8 @@ class Config {
static Config get instance => context[Config] ?? (context[Config] = new Config()); static Config get instance => context[Config] ?? (context[Config] = new Config());
File _configFile; File _configFile;
String get configPath => _configFile.path;
Map<String, dynamic> _values = <String, dynamic>{}; Map<String, dynamic> _values = <String, dynamic>{};
Iterable<String> get keys => _values.keys; Iterable<String> get keys => _values.keys;
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
import 'dart:io'; import 'dart:io';
import 'package:path/path.dart' as path;
import 'base/utils.dart'; import 'base/utils.dart';
import 'globals.dart'; import 'globals.dart';
...@@ -113,3 +115,34 @@ HostPlatform getCurrentHostPlatform() { ...@@ -113,3 +115,34 @@ HostPlatform getCurrentHostPlatform() {
return HostPlatform.linux_x64; return HostPlatform.linux_x64;
} }
/// Returns the top-level build output directory.
String getBuildDirectory() {
String buildDir = config.getValue('build-dir') ?? 'build';
if (path.isAbsolute(buildDir)) {
throw new Exception(
'build-dir config setting in ${config.configPath} must be relative');
}
return buildDir;
}
/// Returns the Android build output directory.
String getAndroidBuildDirectory() {
// TODO(cbracken) move to android subdir.
return getBuildDirectory();
}
/// Returns the AOT build output directory.
String getAotBuildDirectory() {
return path.join(getBuildDirectory(), 'aot');
}
/// Returns the asset build output directory.
String getAssetBuildDirectory() {
return path.join(getBuildDirectory(), 'flx');
}
/// Returns the iOS build output directory.
String getIosBuildDirectory() {
return path.join(getBuildDirectory(), 'ios');
}
...@@ -7,6 +7,7 @@ import 'dart:io'; ...@@ -7,6 +7,7 @@ import 'dart:io';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import '../build_info.dart';
import '../globals.dart'; import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
import '../base/utils.dart'; import '../base/utils.dart';
...@@ -66,7 +67,7 @@ class BuildCleanCommand extends FlutterCommand { ...@@ -66,7 +67,7 @@ class BuildCleanCommand extends FlutterCommand {
@override @override
Future<int> runInProject() async { Future<int> runInProject() async {
Directory buildDir = new Directory('build'); Directory buildDir = new Directory(getBuildDirectory());
printStatus("Deleting '${buildDir.path}${Platform.pathSeparator}'."); printStatus("Deleting '${buildDir.path}${Platform.pathSeparator}'.");
if (!buildDir.existsSync()) if (!buildDir.existsSync())
......
...@@ -16,8 +16,6 @@ import '../globals.dart'; ...@@ -16,8 +16,6 @@ import '../globals.dart';
import '../resident_runner.dart'; import '../resident_runner.dart';
import 'build.dart'; import 'build.dart';
const String _kDefaultAotOutputDir = 'build/aot';
// Files generated by the ahead-of-time snapshot builder. // Files generated by the ahead-of-time snapshot builder.
const List<String> kAotSnapshotFiles = const <String>[ const List<String> kAotSnapshotFiles = const <String>[
'snapshot_aot_instr', 'snapshot_aot_isolate', 'snapshot_aot_rodata', 'snapshot_aot_vmisolate', 'snapshot_aot_instr', 'snapshot_aot_isolate', 'snapshot_aot_rodata', 'snapshot_aot_vmisolate',
...@@ -29,7 +27,7 @@ class BuildAotCommand extends BuildSubCommand { ...@@ -29,7 +27,7 @@ class BuildAotCommand extends BuildSubCommand {
addBuildModeFlags(); addBuildModeFlags();
usesPubOption(); usesPubOption();
argParser argParser
..addOption('output-dir', defaultsTo: _kDefaultAotOutputDir) ..addOption('output-dir', defaultsTo: getAotBuildDirectory())
..addOption('target-platform', ..addOption('target-platform',
defaultsTo: 'android-arm', defaultsTo: 'android-arm',
allowed: <String>['android-arm', 'ios'] allowed: <String>['android-arm', 'ios']
...@@ -82,9 +80,10 @@ Future<String> buildAotSnapshot( ...@@ -82,9 +80,10 @@ Future<String> buildAotSnapshot(
String mainPath, String mainPath,
TargetPlatform platform, TargetPlatform platform,
BuildMode buildMode, { BuildMode buildMode, {
String outputPath: _kDefaultAotOutputDir, String outputPath,
bool interpreter: false bool interpreter: false
}) async { }) async {
outputPath ??= getAotBuildDirectory();
try { try {
return _buildAotSnapshot( return _buildAotSnapshot(
mainPath, mainPath,
...@@ -104,9 +103,10 @@ Future<String> _buildAotSnapshot( ...@@ -104,9 +103,10 @@ Future<String> _buildAotSnapshot(
String mainPath, String mainPath,
TargetPlatform platform, TargetPlatform platform,
BuildMode buildMode, { BuildMode buildMode, {
String outputPath: _kDefaultAotOutputDir, String outputPath,
bool interpreter: false bool interpreter: false
}) async { }) async {
outputPath ??= getAotBuildDirectory();
if (!isAotBuildMode(buildMode) && !interpreter) { if (!isAotBuildMode(buildMode) && !interpreter) {
printError('${toTitleCase(getModeName(buildMode))} mode does not support AOT compilation.'); printError('${toTitleCase(getModeName(buildMode))} mode does not support AOT compilation.');
return null; return null;
......
...@@ -26,7 +26,6 @@ import 'build.dart'; ...@@ -26,7 +26,6 @@ import 'build.dart';
export '../android/android_device.dart' show AndroidDevice; export '../android/android_device.dart' show AndroidDevice;
const String _kDefaultAndroidManifestPath = 'android/AndroidManifest.xml'; const String _kDefaultAndroidManifestPath = 'android/AndroidManifest.xml';
const String _kDefaultOutputPath = 'build/app.apk';
const String _kDefaultResourcesPath = 'android/res'; const String _kDefaultResourcesPath = 'android/res';
const String _kDefaultAssetsPath = 'android/assets'; const String _kDefaultAssetsPath = 'android/assets';
...@@ -39,6 +38,9 @@ const String _kDebugKeystoreKeyAlias = "chromiumdebugkey"; ...@@ -39,6 +38,9 @@ const String _kDebugKeystoreKeyAlias = "chromiumdebugkey";
// Password for the Chromium debug keystore // Password for the Chromium debug keystore
const String _kDebugKeystorePassword = "chromium"; const String _kDebugKeystorePassword = "chromium";
// Default APK output path.
String get _defaultOutputPath => path.join(getAndroidBuildDirectory(), 'app.apk');
/// Copies files into a new directory structure. /// Copies files into a new directory structure.
class _AssetBuilder { class _AssetBuilder {
final Directory outDir; final Directory outDir;
...@@ -174,7 +176,7 @@ class BuildApkCommand extends BuildSubCommand { ...@@ -174,7 +176,7 @@ class BuildApkCommand extends BuildSubCommand {
help: 'Resources directory path.'); help: 'Resources directory path.');
argParser.addOption('output-file', argParser.addOption('output-file',
abbr: 'o', abbr: 'o',
defaultsTo: _kDefaultOutputPath, defaultsTo: _defaultOutputPath,
help: 'Output APK file.'); help: 'Output APK file.');
argParser.addOption('flx', argParser.addOption('flx',
abbr: 'f', abbr: 'f',
...@@ -443,12 +445,14 @@ Future<int> buildAndroid( ...@@ -443,12 +445,14 @@ Future<int> buildAndroid(
bool force: false, bool force: false,
String manifest: _kDefaultAndroidManifestPath, String manifest: _kDefaultAndroidManifestPath,
String resources, String resources,
String outputFile: _kDefaultOutputPath, String outputFile,
String target, String target,
String flxPath, String flxPath,
String aotPath, String aotPath,
ApkKeystoreInfo keystore ApkKeystoreInfo keystore
}) async { }) async {
outputFile ??= _defaultOutputPath;
// Validate that we can find an android sdk. // Validate that we can find an android sdk.
if (androidSdk == null) { if (androidSdk == null) {
printError('No Android SDK found. Try setting the ANDROID_HOME environment variable.'); printError('No Android SDK found. Try setting the ANDROID_HOME environment variable.');
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'dart:async'; import 'dart:async';
import '../build_info.dart';
import '../flx.dart'; import '../flx.dart';
import '../globals.dart'; import '../globals.dart';
import 'build.dart'; import 'build.dart';
...@@ -20,7 +21,7 @@ class BuildFlxCommand extends BuildSubCommand { ...@@ -20,7 +21,7 @@ class BuildFlxCommand extends BuildSubCommand {
argParser.addOption('output-file', abbr: 'o', defaultsTo: defaultFlxOutputPath); argParser.addOption('output-file', abbr: 'o', defaultsTo: defaultFlxOutputPath);
argParser.addOption('snapshot', defaultsTo: defaultSnapshotPath); argParser.addOption('snapshot', defaultsTo: defaultSnapshotPath);
argParser.addOption('depfile', defaultsTo: defaultDepfilePath); argParser.addOption('depfile', defaultsTo: defaultDepfilePath);
argParser.addOption('working-dir', defaultsTo: defaultWorkingDirPath); argParser.addOption('working-dir', defaultsTo: getAssetBuildDirectory());
argParser.addFlag('include-roboto-fonts', defaultsTo: true); argParser.addFlag('include-roboto-fonts', defaultsTo: true);
argParser.addFlag('report-licensed-packages', help: 'Whether to report the names of all the packages that are included in the application\'s LICENSE file.', defaultsTo: false); argParser.addFlag('report-licensed-packages', help: 'Whether to report the names of all the packages that are included in the application\'s LICENSE file.', defaultsTo: false);
usesPubOption(); usesPubOption();
......
...@@ -15,7 +15,7 @@ import '../globals.dart'; ...@@ -15,7 +15,7 @@ import '../globals.dart';
import '../resident_runner.dart'; import '../resident_runner.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
const String _kDefaultBundlePath = 'build/app.flx'; String get _defaultBundlePath => path.join(getBuildDirectory(), 'app.flx');
class RunMojoCommand extends FlutterCommand { class RunMojoCommand extends FlutterCommand {
RunMojoCommand({ this.hidden: false }) { RunMojoCommand({ this.hidden: false }) {
...@@ -140,7 +140,7 @@ class RunMojoCommand extends FlutterCommand { ...@@ -140,7 +140,7 @@ class RunMojoCommand extends FlutterCommand {
String targetApp = argResults['app']; String targetApp = argResults['app'];
if (targetApp == null) { if (targetApp == null) {
targetApp = _kDefaultBundlePath; targetApp = _defaultBundlePath;
String mainPath = findMainDartFile(argResults['target']); String mainPath = findMainDartFile(argResults['target']);
......
...@@ -6,8 +6,11 @@ import 'dart:async'; ...@@ -6,8 +6,11 @@ import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:path/path.dart' as path;
import '../base/common.dart'; import '../base/common.dart';
import '../base/utils.dart'; import '../base/utils.dart';
import '../build_info.dart';
import '../cache.dart'; import '../cache.dart';
import '../globals.dart'; import '../globals.dart';
import '../vmservice.dart'; import '../vmservice.dart';
...@@ -153,7 +156,8 @@ class Tracing { ...@@ -153,7 +156,8 @@ class Tracing {
/// Download the startup trace information from the given observatory client and /// Download the startup trace information from the given observatory client and
/// store it to build/start_up_info.json. /// store it to build/start_up_info.json.
Future<Null> downloadStartupTrace(VMService observatory) async { Future<Null> downloadStartupTrace(VMService observatory) async {
File traceInfoFile = new File('build/start_up_info.json'); String traceInfoFilePath = path.join(getBuildDirectory(), 'start_up_info.json');
File traceInfoFile = new File(traceInfoFilePath);
// Delete old startup data, if any. // Delete old startup data, if any.
if (await traceInfoFile.exists()) if (await traceInfoFile.exists())
......
...@@ -9,6 +9,7 @@ import 'dart:io'; ...@@ -9,6 +9,7 @@ import 'dart:io';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'base/logger.dart'; import 'base/logger.dart';
import 'build_info.dart';
import 'dart/package_map.dart'; import 'dart/package_map.dart';
import 'asset.dart'; import 'asset.dart';
import 'globals.dart'; import 'globals.dart';
...@@ -335,9 +336,10 @@ class DevFS { ...@@ -335,9 +336,10 @@ class DevFS {
status = logger.startProgress('Scanning asset files...'); status = logger.startProgress('Scanning asset files...');
// Synchronize asset bundle. // Synchronize asset bundle.
for (AssetBundleEntry entry in bundle.entries) { for (AssetBundleEntry entry in bundle.entries) {
// We write the assets into 'build/flx' so that they are in the // We write the assets into the AssetBundle working dir so that they
// same location in DevFS and the iOS simulator. // are in the same location in DevFS and the iOS simulator.
final String devicePath = path.join('build/flx', entry.archivePath); final String devicePath =
path.join(getAssetBuildDirectory(), entry.archivePath);
_scanBundleEntry(devicePath, entry, bundleDirty); _scanBundleEntry(devicePath, entry, bundleDirty);
} }
status.stop(showElapsedTime: true); status.stop(showElapsedTime: true);
...@@ -457,7 +459,7 @@ class DevFS { ...@@ -457,7 +459,7 @@ class DevFS {
bool _shouldIgnore(String devicePath) { bool _shouldIgnore(String devicePath) {
List<String> ignoredPrefixes = <String>['android/', List<String> ignoredPrefixes = <String>['android/',
'build/', getBuildDirectory(),
'ios/', 'ios/',
'.pub/']; '.pub/'];
for (String ignoredPrefix in ignoredPrefixes) { for (String ignoredPrefix in ignoredPrefixes) {
......
...@@ -11,6 +11,7 @@ import 'asset.dart'; ...@@ -11,6 +11,7 @@ import 'asset.dart';
import 'base/file_system.dart' show ensureDirectoryExists; import 'base/file_system.dart' show ensureDirectoryExists;
import 'base/process.dart'; import 'base/process.dart';
import 'dart/package_map.dart'; import 'dart/package_map.dart';
import 'build_info.dart';
import 'globals.dart'; import 'globals.dart';
import 'toolchain.dart'; import 'toolchain.dart';
import 'zip.dart'; import 'zip.dart';
...@@ -18,11 +19,10 @@ import 'zip.dart'; ...@@ -18,11 +19,10 @@ import 'zip.dart';
const String defaultMainPath = 'lib/main.dart'; const String defaultMainPath = 'lib/main.dart';
const String defaultAssetBasePath = '.'; const String defaultAssetBasePath = '.';
const String defaultManifestPath = 'flutter.yaml'; const String defaultManifestPath = 'flutter.yaml';
const String defaultFlxOutputPath = 'build/app.flx'; String get defaultFlxOutputPath => path.join(getBuildDirectory(), 'app.flx');
const String defaultSnapshotPath = 'build/snapshot_blob.bin'; String get defaultSnapshotPath => path.join(getBuildDirectory(), 'snapshot_blob.bin');
const String defaultDepfilePath = 'build/snapshot_blob.bin.d'; String get defaultDepfilePath => path.join(getBuildDirectory(), 'snapshot_blob.bin.d');
const String defaultPrivateKeyPath = 'privatekey.der'; const String defaultPrivateKeyPath = 'privatekey.der';
const String defaultWorkingDirPath = 'build/flx';
const String _kSnapshotKey = 'snapshot_blob.bin'; const String _kSnapshotKey = 'snapshot_blob.bin';
...@@ -47,7 +47,7 @@ Future<int> createSnapshot({ ...@@ -47,7 +47,7 @@ Future<int> createSnapshot({
return runCommandAndStreamOutput(args); return runCommandAndStreamOutput(args);
} }
/// Build the flx in the build/ directory and return `localBundlePath` on success. /// Build the flx in the build directory and return `localBundlePath` on success.
/// ///
/// Return `null` on failure. /// Return `null` on failure.
Future<String> buildFlx({ Future<String> buildFlx({
...@@ -56,30 +56,32 @@ Future<String> buildFlx({ ...@@ -56,30 +56,32 @@ Future<String> buildFlx({
bool includeRobotoFonts: true bool includeRobotoFonts: true
}) async { }) async {
int result; int result;
String localBundlePath = path.join('build', 'app.flx');
String localSnapshotPath = path.join('build', 'snapshot_blob.bin');
result = await build( result = await build(
snapshotPath: localSnapshotPath, snapshotPath: defaultSnapshotPath,
outputPath: localBundlePath, outputPath: defaultFlxOutputPath,
mainPath: mainPath, mainPath: mainPath,
precompiledSnapshot: precompiledSnapshot, precompiledSnapshot: precompiledSnapshot,
includeRobotoFonts: includeRobotoFonts includeRobotoFonts: includeRobotoFonts
); );
return result == 0 ? localBundlePath : null; return result == 0 ? defaultFlxOutputPath : null;
} }
Future<int> build({ Future<int> build({
String mainPath: defaultMainPath, String mainPath: defaultMainPath,
String manifestPath: defaultManifestPath, String manifestPath: defaultManifestPath,
String outputPath: defaultFlxOutputPath, String outputPath,
String snapshotPath: defaultSnapshotPath, String snapshotPath,
String depfilePath: defaultDepfilePath, String depfilePath,
String privateKeyPath: defaultPrivateKeyPath, String privateKeyPath: defaultPrivateKeyPath,
String workingDirPath: defaultWorkingDirPath, String workingDirPath,
bool precompiledSnapshot: false, bool precompiledSnapshot: false,
bool includeRobotoFonts: true, bool includeRobotoFonts: true,
bool reportLicensedPackages: false bool reportLicensedPackages: false
}) async { }) async {
outputPath ??= defaultFlxOutputPath;
snapshotPath ??= defaultSnapshotPath;
depfilePath ??= defaultDepfilePath;
workingDirPath ??= getAssetBuildDirectory();
File snapshotFile; File snapshotFile;
if (!precompiledSnapshot) { if (!precompiledSnapshot) {
...@@ -114,12 +116,14 @@ Future<int> build({ ...@@ -114,12 +116,14 @@ Future<int> build({
Future<int> assemble({ Future<int> assemble({
String manifestPath, String manifestPath,
File snapshotFile, File snapshotFile,
String outputPath: defaultFlxOutputPath, String outputPath,
String privateKeyPath: defaultPrivateKeyPath, String privateKeyPath: defaultPrivateKeyPath,
String workingDirPath: defaultWorkingDirPath, String workingDirPath,
bool includeRobotoFonts: true, bool includeRobotoFonts: true,
bool reportLicensedPackages: false bool reportLicensedPackages: false
}) async { }) async {
outputPath ??= defaultFlxOutputPath;
workingDirPath ??= getAssetBuildDirectory();
printTrace('Building $outputPath'); printTrace('Building $outputPath');
// Build the asset bundle. // Build the asset bundle.
......
...@@ -13,6 +13,7 @@ import 'asset.dart'; ...@@ -13,6 +13,7 @@ import 'asset.dart';
import 'base/logger.dart'; import 'base/logger.dart';
import 'base/process.dart'; import 'base/process.dart';
import 'base/utils.dart'; import 'base/utils.dart';
import 'build_info.dart';
import 'cache.dart'; import 'cache.dart';
import 'commands/build_apk.dart'; import 'commands/build_apk.dart';
import 'commands/install.dart'; import 'commands/install.dart';
...@@ -380,7 +381,7 @@ class HotRunner extends ResidentRunner { ...@@ -380,7 +381,7 @@ class HotRunner extends ResidentRunner {
String devicePackagesPath = String devicePackagesPath =
_devFS.baseUri.resolve('.packages').toFilePath(); _devFS.baseUri.resolve('.packages').toFilePath();
String deviceAssetsDirectoryPath = String deviceAssetsDirectoryPath =
_devFS.baseUri.resolve('build/flx').toFilePath(); _devFS.baseUri.resolve(getAssetBuildDirectory()).toFilePath();
await _launchInView(deviceEntryPath, await _launchInView(deviceEntryPath,
devicePackagesPath, devicePackagesPath,
deviceAssetsDirectoryPath); deviceAssetsDirectoryPath);
......
...@@ -28,6 +28,11 @@ void updateXcodeGeneratedProperties(String projectPath, BuildMode mode, String t ...@@ -28,6 +28,11 @@ void updateXcodeGeneratedProperties(String projectPath, BuildMode mode, String t
// The runtime mode for the current build. // The runtime mode for the current build.
localsBuffer.writeln('FLUTTER_BUILD_MODE=${getModeName(mode)}'); localsBuffer.writeln('FLUTTER_BUILD_MODE=${getModeName(mode)}');
// The build outputs directory, relative to FLUTTER_APPLICATION_PATH.
localsBuffer.writeln('FLUTTER_BUILD_DIR=${getBuildDirectory()}');
localsBuffer.writeln('SYMROOT=\${SOURCE_ROOT}/../${getIosBuildDirectory()}');
String flutterFrameworkDir = path.normalize(tools.getEngineArtifactsDirectory(TargetPlatform.ios, mode).path); String flutterFrameworkDir = path.normalize(tools.getEngineArtifactsDirectory(TargetPlatform.ios, mode).path);
localsBuffer.writeln('FLUTTER_FRAMEWORK_DIR=$flutterFrameworkDir'); localsBuffer.writeln('FLUTTER_FRAMEWORK_DIR=$flutterFrameworkDir');
......
...@@ -476,7 +476,7 @@ class IOSSimulator extends Device { ...@@ -476,7 +476,7 @@ class IOSSimulator extends Device {
// Prepare launch arguments. // Prepare launch arguments.
List<String> args = <String>[ List<String> args = <String>[
"--flx=${path.absolute(path.join('build', 'app.flx'))}", "--flx=${path.absolute(path.join(getBuildDirectory(), 'app.flx'))}",
"--dart-main=${path.absolute(mainPath)}", "--dart-main=${path.absolute(mainPath)}",
"--packages=${path.absolute('.packages')}", "--packages=${path.absolute('.packages')}",
]; ];
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'dart:io'; import 'dart:io';
import 'package:flutter_tools/src/asset.dart'; import 'package:flutter_tools/src/asset.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/devfs.dart'; import 'package:flutter_tools/src/devfs.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'package:test/test.dart'; import 'package:test/test.dart';
...@@ -59,17 +60,20 @@ void main() { ...@@ -59,17 +60,20 @@ void main() {
}); });
testUsingContext('add file in an asset bundle', () async { testUsingContext('add file in an asset bundle', () async {
await devFS.update(bundle: assetBundle, bundleDirty: true); await devFS.update(bundle: assetBundle, bundleDirty: true);
expect(devFSOperations.contains('writeFile test build/flx/a.txt'), isTrue); expect(devFSOperations.contains(
'writeFile test ${getAssetBuildDirectory()}/a.txt'), isTrue);
}); });
testUsingContext('add a file to the asset bundle', () async { testUsingContext('add a file to the asset bundle', () async {
assetBundle.entries.add(new AssetBundleEntry.fromString('b.txt', '')); assetBundle.entries.add(new AssetBundleEntry.fromString('b.txt', ''));
await devFS.update(bundle: assetBundle, bundleDirty: true); await devFS.update(bundle: assetBundle, bundleDirty: true);
expect(devFSOperations.contains('writeFile test build/flx/b.txt'), isTrue); expect(devFSOperations.contains(
'writeFile test ${getAssetBuildDirectory()}/b.txt'), isTrue);
}); });
testUsingContext('delete a file from the asset bundle', () async { testUsingContext('delete a file from the asset bundle', () async {
assetBundle.entries.clear(); assetBundle.entries.clear();
await devFS.update(bundle: assetBundle, bundleDirty: true); await devFS.update(bundle: assetBundle, bundleDirty: true);
expect(devFSOperations.contains('deleteFile test build/flx/b.txt'), isTrue); expect(devFSOperations.contains(
'deleteFile test ${getAssetBuildDirectory()}/b.txt'), isTrue);
}); });
testUsingContext('delete dev file system', () async { testUsingContext('delete dev file system', () async {
await devFS.destroy(); await devFS.destroy();
......
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