Unverified Commit c4a2a3e9 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Migrate project.dart and all dependencies to null safety (#83817)

parent 2c645e4c
......@@ -12,6 +12,7 @@ import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_system/depfile.dart';
import 'package:flutter_tools/src/bundle.dart';
import 'package:flutter_tools/src/bundle_builder.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/context_runner.dart';
import 'package:flutter_tools/src/devfs.dart';
......
......@@ -2,16 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:meta/meta.dart';
import '../base/context.dart';
import '../build_info.dart';
import '../project.dart';
/// The builder in the current context.
AndroidBuilder get androidBuilder {
AndroidBuilder? get androidBuilder {
return context.get<AndroidBuilder>();
}
......@@ -19,25 +15,25 @@ abstract class AndroidBuilder {
const AndroidBuilder();
/// Builds an AAR artifact.
Future<void> buildAar({
@required FlutterProject project,
@required Set<AndroidBuildInfo> androidBuildInfo,
@required String target,
@required String outputDirectoryPath,
@required String buildNumber,
required FlutterProject project,
required Set<AndroidBuildInfo> androidBuildInfo,
required String target,
String? outputDirectoryPath,
required String buildNumber,
});
/// Builds an APK artifact.
Future<void> buildApk({
@required FlutterProject project,
@required AndroidBuildInfo androidBuildInfo,
@required String target,
required FlutterProject project,
required AndroidBuildInfo androidBuildInfo,
required String target,
});
/// Builds an App Bundle artifact.
Future<void> buildAab({
@required FlutterProject project,
@required AndroidBuildInfo androidBuildInfo,
@required String target,
required FlutterProject project,
required AndroidBuildInfo androidBuildInfo,
required String target,
bool validateDeferredComponents = true,
bool deferredComponentsEnabled = false,
});
......
......@@ -2,13 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:meta/meta.dart';
import '../base/error_handling_io.dart';
import '../base/file_system.dart';
import '../base/process.dart';
import '../globals.dart' as globals;
import '../globals_null_migrated.dart' as globals;
import '../project.dart';
import '../reporting/reporting.dart';
import 'android_studio.dart';
......@@ -18,8 +17,8 @@ typedef GradleErrorTest = bool Function(String);
/// A Gradle error handled by the tool.
class GradleHandledError {
const GradleHandledError({
@required this.test,
@required this.handler,
required this.test,
required this.handler,
this.eventLabel,
});
......@@ -29,16 +28,16 @@ class GradleHandledError {
/// The handler function.
final Future<GradleBuildStatus> Function({
@required String line,
@required FlutterProject project,
@required bool usesAndroidX,
@required bool shouldBuildPluginAsAar,
required String line,
required FlutterProject project,
required bool usesAndroidX,
required bool shouldBuildPluginAsAar,
}) handler;
/// The [BuildEvent] label is named gradle-[eventLabel].
/// If not empty, the build event is logged along with
/// additional metadata such as the attempt number.
final String eventLabel;
final String? eventLabel;
}
/// The status of the Gradle build.
......@@ -85,10 +84,10 @@ final GradleHandledError permissionDeniedErrorHandler = GradleHandledError(
'Permission denied',
]),
handler: ({
@required String line,
@required FlutterProject project,
@required bool usesAndroidX,
@required bool shouldBuildPluginAsAar,
required String line,
required FlutterProject project,
required bool usesAndroidX,
required bool shouldBuildPluginAsAar,
}) async {
globals.printStatus('${globals.logger.terminal.warningMark} Gradle does not have execution permission.', emphasis: true);
globals.printStatus(
......@@ -122,17 +121,17 @@ final GradleHandledError networkErrorHandler = GradleHandledError(
'Gateway Time-out'
]),
handler: ({
@required String line,
@required FlutterProject project,
@required bool usesAndroidX,
@required bool shouldBuildPluginAsAar,
required String line,
required FlutterProject project,
required bool usesAndroidX,
required bool shouldBuildPluginAsAar,
}) async {
globals.printError(
'${globals.logger.terminal.warningMark} Gradle threw an error while downloading artifacts from the network. '
'Retrying to download...'
);
try {
final String homeDir = globals.platform.environment['HOME'];
final String? homeDir = globals.platform.environment['HOME'];
if (homeDir != null) {
final Directory directory = globals.fs.directory(globals.fs.path.join(homeDir, '.gradle'));
ErrorHandlingFileSystem.deleteIfExists(directory, recursive: true);
......@@ -152,10 +151,10 @@ final GradleHandledError r8FailureHandler = GradleHandledError(
'com.android.tools.r8',
]),
handler: ({
@required String line,
@required FlutterProject project,
@required bool usesAndroidX,
@required bool shouldBuildPluginAsAar,
required String line,
required FlutterProject project,
required bool usesAndroidX,
required bool shouldBuildPluginAsAar,
}) async {
globals.printStatus('${globals.logger.terminal.warningMark} The shrinker may have failed to optimize the Java bytecode.', emphasis: true);
globals.printStatus('To disable the shrinker, pass the `--no-shrink` flag to this command.', indent: 4);
......@@ -191,10 +190,10 @@ final GradleHandledError androidXFailureHandler = GradleHandledError(
_androidXFailureRegex.hasMatch(line);
},
handler: ({
@required String line,
@required FlutterProject project,
@required bool usesAndroidX,
@required bool shouldBuildPluginAsAar,
required String line,
required FlutterProject project,
required bool usesAndroidX,
required bool shouldBuildPluginAsAar,
}) async {
final bool hasPlugins = project.flutterPluginsFile.existsSync();
if (!hasPlugins) {
......@@ -259,21 +258,21 @@ final GradleHandledError licenseNotAcceptedHandler = GradleHandledError(
'You have not accepted the license agreements of the following SDK components',
]),
handler: ({
@required String line,
@required FlutterProject project,
@required bool usesAndroidX,
@required bool shouldBuildPluginAsAar,
required String line,
required FlutterProject project,
required bool usesAndroidX,
required bool shouldBuildPluginAsAar,
}) async {
const String licenseNotAcceptedMatcher =
r'You have not accepted the license agreements of the following SDK components:\s*\[(.+)\]';
final RegExp licenseFailure = RegExp(licenseNotAcceptedMatcher, multiLine: true);
assert(licenseFailure != null);
final Match licenseMatch = licenseFailure.firstMatch(line);
final Match? licenseMatch = licenseFailure.firstMatch(line);
globals.printStatus(
'${globals.logger.terminal.warningMark} Unable to download needed Android SDK components, as the '
'following licenses have not been accepted:\n'
'${licenseMatch.group(1)}\n\n'
'${licenseMatch?.group(1)}\n\n'
'To resolve this, please run the following command in a Terminal:\n'
'flutter doctor --android-licenses'
);
......@@ -293,14 +292,14 @@ final GradleHandledError flavorUndefinedHandler = GradleHandledError(
return _undefinedTaskPattern.hasMatch(line);
},
handler: ({
@required String line,
@required FlutterProject project,
@required bool usesAndroidX,
@required bool shouldBuildPluginAsAar,
required String line,
required FlutterProject project,
required bool usesAndroidX,
required bool shouldBuildPluginAsAar,
}) async {
final RunResult tasksRunResult = await globals.processUtils.run(
<String>[
globals.gradleUtils.getExecutable(project),
globals.gradleUtils!.getExecutable(project),
'app:tasks' ,
'--all',
'--console=auto',
......@@ -309,15 +308,15 @@ final GradleHandledError flavorUndefinedHandler = GradleHandledError(
workingDirectory: project.android.hostAppGradleRoot.path,
environment: <String, String>{
if (javaPath != null)
'JAVA_HOME': javaPath,
'JAVA_HOME': javaPath!,
},
);
// Extract build types and product flavors.
final Set<String> variants = <String>{};
for (final String task in tasksRunResult.stdout.split('\n')) {
final Match match = _assembleTaskPattern.matchAsPrefix(task);
final Match? match = _assembleTaskPattern.matchAsPrefix(task);
if (match != null) {
final String variant = match.group(1).toLowerCase();
final String variant = match.group(1)!.toLowerCase();
if (!variant.endsWith('test')) {
variants.add(variant);
}
......@@ -366,32 +365,32 @@ final GradleHandledError minSdkVersion = GradleHandledError(
return _minSdkVersionPattern.hasMatch(line);
},
handler: ({
@required String line,
@required FlutterProject project,
@required bool usesAndroidX,
@required bool shouldBuildPluginAsAar,
required String line,
required FlutterProject project,
required bool usesAndroidX,
required bool shouldBuildPluginAsAar,
}) async {
final File gradleFile = project.directory
.childDirectory('android')
.childDirectory('app')
.childFile('build.gradle');
final Match minSdkVersionMatch = _minSdkVersionPattern.firstMatch(line);
assert(minSdkVersionMatch.groupCount == 3);
final Match? minSdkVersionMatch = _minSdkVersionPattern.firstMatch(line);
assert(minSdkVersionMatch?.groupCount == 3);
final String bold = globals.logger.terminal.bolden(
'Fix this issue by adding the following to the file ${gradleFile.path}:\n'
'android {\n'
' defaultConfig {\n'
' minSdkVersion ${minSdkVersionMatch.group(2)}\n'
' minSdkVersion ${minSdkVersionMatch?.group(2)}\n'
' }\n'
'}\n'
);
globals.printStatus(
'\n'
'The plugin ${minSdkVersionMatch.group(3)} requires a higher Android SDK version.\n'
'The plugin ${minSdkVersionMatch?.group(3)} requires a higher Android SDK version.\n'
'$bold\n'
"Note that your app won't be available to users running Android SDKs below ${minSdkVersionMatch.group(2)}.\n"
"Note that your app won't be available to users running Android SDKs below ${minSdkVersionMatch?.group(2)}.\n"
'Alternatively, try to find a version of this plugin that supports these lower versions of the Android SDK.'
);
return GradleBuildStatus.exit;
......@@ -407,10 +406,10 @@ final GradleHandledError transformInputIssue = GradleHandledError(
return line.contains('https://issuetracker.google.com/issues/158753935');
},
handler: ({
@required String line,
@required FlutterProject project,
@required bool usesAndroidX,
@required bool shouldBuildPluginAsAar,
required String line,
required FlutterProject project,
required bool usesAndroidX,
required bool shouldBuildPluginAsAar,
}) async {
final File gradleFile = project.directory
.childDirectory('android')
......@@ -441,10 +440,10 @@ final GradleHandledError lockFileDepMissing = GradleHandledError(
return line.contains('which is not part of the dependency lock state');
},
handler: ({
@required String line,
@required FlutterProject project,
@required bool usesAndroidX,
@required bool shouldBuildPluginAsAar,
required String line,
required FlutterProject project,
required bool usesAndroidX,
required bool shouldBuildPluginAsAar,
}) async {
final File gradleFile = project.directory
.childDirectory('android')
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:meta/meta.dart';
import '../base/common.dart';
......@@ -29,11 +27,11 @@ final RegExp _androidPluginRegExp = RegExp(r'com\.android\.tools\.build:gradle:(
/// or constructing a Gradle project.
class GradleUtils {
GradleUtils({
@required Platform platform,
@required Logger logger,
@required FileSystem fileSystem,
@required Cache cache,
@required OperatingSystemUtils operatingSystemUtils,
required Platform platform,
required Logger logger,
required FileSystem fileSystem,
required Cache cache,
required OperatingSystemUtils operatingSystemUtils,
}) : _platform = platform,
_logger = logger,
_cache = cache,
......@@ -120,22 +118,22 @@ String getGradleVersionForAndroidPlugin(Directory directory, Logger logger) {
logger.printTrace("$buildFile doesn't provide an AGP version, assuming AGP version: $_defaultGradleVersion");
return _defaultGradleVersion;
}
final String androidPluginVersion = pluginMatches.first.group(1);
final String? androidPluginVersion = pluginMatches.first.group(1);
logger.printTrace('$buildFile provides AGP version: $androidPluginVersion');
return getGradleVersionFor(androidPluginVersion);
return getGradleVersionFor(androidPluginVersion ?? 'unknown');
}
/// Returns true if [targetVersion] is within the range [min] and [max] inclusive.
bool _isWithinVersionRange(
String targetVersion, {
@required String min,
@required String max,
required String min,
required String max,
}) {
assert(min != null);
assert(max != null);
final Version parsedTargetVersion = Version.parse(targetVersion);
final Version minVersion = Version.parse(min);
final Version maxVersion = Version.parse(max);
final Version? parsedTargetVersion = Version.parse(targetVersion);
final Version? minVersion = Version.parse(min);
final Version? maxVersion = Version.parse(max);
return minVersion != null &&
maxVersion != null &&
parsedTargetVersion != null &&
......@@ -193,8 +191,8 @@ String getGradleVersionFor(String androidPluginVersion) {
/// If [requireAndroidSdk] is true (the default) and no Android SDK is found,
/// this will fail with a [ToolExit].
void updateLocalProperties({
@required FlutterProject project,
BuildInfo buildInfo,
required FlutterProject project,
BuildInfo? buildInfo,
bool requireAndroidSdk = true,
}) {
if (requireAndroidSdk && globals.androidSdk == null) {
......@@ -211,7 +209,7 @@ void updateLocalProperties({
changed = true;
}
void changeIfNecessary(String key, String value) {
void changeIfNecessary(String key, String? value) {
if (settings.values[key] == value) {
return;
}
......@@ -223,21 +221,21 @@ void updateLocalProperties({
changed = true;
}
final AndroidSdk androidSdk = globals.androidSdk;
final AndroidSdk? androidSdk = globals.androidSdk;
if (androidSdk != null) {
changeIfNecessary('sdk.dir', globals.fsUtils.escapePath(androidSdk.directory.path));
}
changeIfNecessary('flutter.sdk', globals.fsUtils.escapePath(Cache.flutterRoot));
changeIfNecessary('flutter.sdk', globals.fsUtils.escapePath(Cache.flutterRoot!));
if (buildInfo != null) {
changeIfNecessary('flutter.buildMode', buildInfo.modeName);
final String buildName = validatedBuildNameForPlatform(
final String? buildName = validatedBuildNameForPlatform(
TargetPlatform.android_arm,
buildInfo.buildName ?? project.manifest.buildName,
globals.logger,
);
changeIfNecessary('flutter.versionName', buildName);
final String buildNumber = validatedBuildNumberForPlatform(
final String? buildNumber = validatedBuildNumberForPlatform(
TargetPlatform.android_arm,
buildInfo.buildNumber ?? project.manifest.buildNumber,
globals.logger,
......@@ -255,7 +253,7 @@ void updateLocalProperties({
/// Writes the path to the Android SDK, if known.
void writeLocalProperties(File properties) {
final SettingsFile settings = SettingsFile();
final AndroidSdk androidSdk = globals.androidSdk;
final AndroidSdk? androidSdk = globals.androidSdk;
if (androidSdk != null) {
settings.values['sdk.dir'] = globals.fsUtils.escapePath(androidSdk.directory.path);
}
......
......@@ -2,35 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
import 'package:meta/meta.dart';
import 'package:pool/pool.dart';
import 'asset.dart';
import 'base/common.dart';
import 'base/config.dart';
import 'base/file_system.dart';
import 'base/logger.dart';
import 'build_info.dart';
import 'build_system/build_system.dart';
import 'build_system/depfile.dart';
import 'build_system/targets/common.dart';
import 'cache.dart';
import 'convert.dart';
import 'devfs.dart';
import 'globals_null_migrated.dart' as globals;
import 'project.dart';
String get defaultMainPath => globals.fs.path.join('lib', 'main.dart');
const String defaultAssetBasePath = '.';
const String defaultManifestPath = 'pubspec.yaml';
String get defaultDepfilePath => globals.fs.path.join(getBuildDirectory(), 'snapshot_blob.bin.d');
String getDefaultApplicationKernelPath({
@required bool trackWidgetCreation,
required bool trackWidgetCreation,
}) {
return getKernelPathForTransformerOptions(
globals.fs.path.join(getBuildDirectory(), 'app.dill'),
......@@ -39,15 +25,15 @@ String getDefaultApplicationKernelPath({
}
String getDefaultCachedKernelPath({
@required bool trackWidgetCreation,
@required List<String> dartDefines,
@required List<String> extraFrontEndOptions,
FileSystem fileSystem,
Config config,
required bool trackWidgetCreation,
required List<String> dartDefines,
List<String> extraFrontEndOptions = const <String>[],
FileSystem? fileSystem,
Config? config,
}) {
final StringBuffer buffer = StringBuffer();
buffer.writeAll(dartDefines);
buffer.writeAll(extraFrontEndOptions ?? <String>[]);
buffer.writeAll(extraFrontEndOptions);
String buildPrefix = '';
if (buffer.isNotEmpty) {
final String output = buffer.toString();
......@@ -65,7 +51,7 @@ String getDefaultCachedKernelPath({
String getKernelPathForTransformerOptions(
String path, {
@required bool trackWidgetCreation,
required bool trackWidgetCreation,
}) {
if (trackWidgetCreation) {
path += '.track.dill';
......@@ -74,151 +60,3 @@ String getKernelPathForTransformerOptions(
}
const String defaultPrivateKeyPath = 'privatekey.der';
/// Provides a `build` method that builds the bundle.
class BundleBuilder {
/// Builds the bundle for the given target platform.
///
/// The default `mainPath` is `lib/main.dart`.
/// The default `manifestPath` is `pubspec.yaml`
Future<void> build({
@required TargetPlatform platform,
@required BuildInfo buildInfo,
FlutterProject project,
String mainPath,
String manifestPath = defaultManifestPath,
String applicationKernelFilePath,
String depfilePath,
String assetDirPath,
@visibleForTesting BuildSystem buildSystem
}) async {
project ??= FlutterProject.current();
mainPath ??= defaultMainPath;
depfilePath ??= defaultDepfilePath;
assetDirPath ??= getAssetBuildDirectory();
buildSystem ??= globals.buildSystem;
// If the precompiled flag was not passed, force us into debug mode.
final Environment environment = Environment(
projectDir: project.directory,
outputDir: globals.fs.directory(assetDirPath),
buildDir: project.dartTool.childDirectory('flutter_build'),
cacheDir: globals.cache.getRoot(),
flutterRootDir: globals.fs.directory(Cache.flutterRoot),
engineVersion: globals.artifacts.isLocalEngine
? null
: globals.flutterVersion.engineRevision,
defines: <String, String>{
// used by the KernelSnapshot target
kTargetPlatform: getNameForTargetPlatform(platform),
kTargetFile: mainPath,
kDeferredComponents: 'false',
...buildInfo.toBuildSystemEnvironment(),
},
artifacts: globals.artifacts,
fileSystem: globals.fs,
logger: globals.logger,
processManager: globals.processManager,
platform: globals.platform,
generateDartPluginRegistry: true,
);
final Target target = buildInfo.mode == BuildMode.debug
? const CopyFlutterBundle()
: const ReleaseCopyFlutterBundle();
final BuildResult result = await buildSystem.build(target, environment);
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 bundle.');
}
if (depfilePath != null) {
final Depfile depfile = Depfile(result.inputFiles, result.outputFiles);
final File outputDepfile = globals.fs.file(depfilePath);
if (!outputDepfile.parent.existsSync()) {
outputDepfile.parent.createSync(recursive: true);
}
final DepfileService depfileService = DepfileService(
fileSystem: globals.fs,
logger: globals.logger,
);
depfileService.writeToFile(depfile, outputDepfile);
}
// Work around for flutter_tester placing kernel artifacts in odd places.
if (applicationKernelFilePath != null) {
final File outputDill = globals.fs.directory(assetDirPath).childFile('kernel_blob.bin');
if (outputDill.existsSync()) {
outputDill.copySync(applicationKernelFilePath);
}
}
return;
}
}
Future<AssetBundle> buildAssets({
String manifestPath,
String assetDirPath,
@required String packagesPath,
TargetPlatform targetPlatform,
}) async {
assetDirPath ??= getAssetBuildDirectory();
packagesPath ??= globals.fs.path.absolute(packagesPath);
// Build the asset bundle.
final AssetBundle assetBundle = AssetBundleFactory.instance.createBundle();
final int result = await assetBundle.build(
manifestPath: manifestPath,
assetDirPath: assetDirPath,
packagesPath: packagesPath,
targetPlatform: targetPlatform,
);
if (result != 0) {
return null;
}
return assetBundle;
}
Future<void> writeBundle(
Directory bundleDir,
Map<String, DevFSContent> assetEntries,
{ Logger loggerOverride }
) async {
loggerOverride ??= globals.logger;
if (bundleDir.existsSync()) {
try {
bundleDir.deleteSync(recursive: true);
} on FileSystemException catch (err) {
loggerOverride.printError(
'Failed to clean up asset directory ${bundleDir.path}: $err\n'
'To clean build artifacts, use the command "flutter clean".'
);
}
}
bundleDir.createSync(recursive: true);
// Limit number of open files to avoid running out of file descriptors.
final Pool pool = Pool(64);
await Future.wait<void>(
assetEntries.entries.map<Future<void>>((MapEntry<String, DevFSContent> entry) async {
final PoolResource resource = await pool.request();
try {
// This will result in strange looking files, for example files with `/`
// on Windows or files that end up getting URI encoded such as `#.ext`
// to `%23.ext`. However, we have to keep it this way since the
// platform channels in the framework will URI encode these values,
// and the native APIs will look for files this way.
final File file = globals.fs.file(globals.fs.path.join(bundleDir.path, entry.key));
file.parent.createSync(recursive: true);
await file.writeAsBytes(await entry.value.contentsAsBytes());
} finally {
resource.release();
}
}));
}
// 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.
// @dart = 2.8
import 'package:meta/meta.dart';
import 'package:pool/pool.dart';
import 'asset.dart' hide defaultManifestPath;
import 'base/common.dart';
import 'base/file_system.dart';
import 'base/logger.dart';
import 'build_info.dart';
import 'build_system/build_system.dart';
import 'build_system/depfile.dart';
import 'build_system/targets/common.dart';
import 'bundle.dart';
import 'cache.dart';
import 'devfs.dart';
import 'globals_null_migrated.dart' as globals;
import 'project.dart';
/// Provides a `build` method that builds the bundle.
class BundleBuilder {
/// Builds the bundle for the given target platform.
///
/// The default `mainPath` is `lib/main.dart`.
/// The default `manifestPath` is `pubspec.yaml`
Future<void> build({
@required TargetPlatform platform,
@required BuildInfo buildInfo,
FlutterProject project,
String mainPath,
String manifestPath = defaultManifestPath,
String applicationKernelFilePath,
String depfilePath,
String assetDirPath,
@visibleForTesting BuildSystem buildSystem
}) async {
project ??= FlutterProject.current();
mainPath ??= defaultMainPath;
depfilePath ??= defaultDepfilePath;
assetDirPath ??= getAssetBuildDirectory();
buildSystem ??= globals.buildSystem;
// If the precompiled flag was not passed, force us into debug mode.
final Environment environment = Environment(
projectDir: project.directory,
outputDir: globals.fs.directory(assetDirPath),
buildDir: project.dartTool.childDirectory('flutter_build'),
cacheDir: globals.cache.getRoot(),
flutterRootDir: globals.fs.directory(Cache.flutterRoot),
engineVersion: globals.artifacts.isLocalEngine
? null
: globals.flutterVersion.engineRevision,
defines: <String, String>{
// used by the KernelSnapshot target
kTargetPlatform: getNameForTargetPlatform(platform),
kTargetFile: mainPath,
kDeferredComponents: 'false',
...buildInfo.toBuildSystemEnvironment(),
},
artifacts: globals.artifacts,
fileSystem: globals.fs,
logger: globals.logger,
processManager: globals.processManager,
platform: globals.platform,
generateDartPluginRegistry: true,
);
final Target target = buildInfo.mode == BuildMode.debug
? const CopyFlutterBundle()
: const ReleaseCopyFlutterBundle();
final BuildResult result = await buildSystem.build(target, environment);
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 bundle.');
}
if (depfilePath != null) {
final Depfile depfile = Depfile(result.inputFiles, result.outputFiles);
final File outputDepfile = globals.fs.file(depfilePath);
if (!outputDepfile.parent.existsSync()) {
outputDepfile.parent.createSync(recursive: true);
}
final DepfileService depfileService = DepfileService(
fileSystem: globals.fs,
logger: globals.logger,
);
depfileService.writeToFile(depfile, outputDepfile);
}
// Work around for flutter_tester placing kernel artifacts in odd places.
if (applicationKernelFilePath != null) {
final File outputDill = globals.fs.directory(assetDirPath).childFile('kernel_blob.bin');
if (outputDill.existsSync()) {
outputDill.copySync(applicationKernelFilePath);
}
}
return;
}
}
Future<AssetBundle> buildAssets({
String manifestPath,
String assetDirPath,
@required String packagesPath,
TargetPlatform targetPlatform,
}) async {
assetDirPath ??= getAssetBuildDirectory();
packagesPath ??= globals.fs.path.absolute(packagesPath);
// Build the asset bundle.
final AssetBundle assetBundle = AssetBundleFactory.instance.createBundle();
final int result = await assetBundle.build(
manifestPath: manifestPath,
assetDirPath: assetDirPath,
packagesPath: packagesPath,
targetPlatform: targetPlatform,
);
if (result != 0) {
return null;
}
return assetBundle;
}
Future<void> writeBundle(
Directory bundleDir,
Map<String, DevFSContent> assetEntries,
{ Logger loggerOverride }
) async {
loggerOverride ??= globals.logger;
if (bundleDir.existsSync()) {
try {
bundleDir.deleteSync(recursive: true);
} on FileSystemException catch (err) {
loggerOverride.printError(
'Failed to clean up asset directory ${bundleDir.path}: $err\n'
'To clean build artifacts, use the command "flutter clean".'
);
}
}
bundleDir.createSync(recursive: true);
// Limit number of open files to avoid running out of file descriptors.
final Pool pool = Pool(64);
await Future.wait<void>(
assetEntries.entries.map<Future<void>>((MapEntry<String, DevFSContent> entry) async {
final PoolResource resource = await pool.request();
try {
// This will result in strange looking files, for example files with `/`
// on Windows or files that end up getting URI encoded such as `#.ext`
// to `%23.ext`. However, we have to keep it this way since the
// platform channels in the framework will URI encode these values,
// and the native APIs will look for files this way.
final File file = globals.fs.file(globals.fs.path.join(bundleDir.path, entry.key));
file.parent.createSync(recursive: true);
await file.writeAsBytes(await entry.value.contentsAsBytes());
} finally {
resource.release();
}
}));
}
......@@ -2,21 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'base/file_system.dart';
import 'project.dart';
/// Extracts the `BINARY_NAME` from a project's CMake file.
///
/// Returns `null` if it cannot be found.
String getCmakeExecutableName(CmakeBasedProject project) {
String? getCmakeExecutableName(CmakeBasedProject project) {
if (!project.cmakeFile.existsSync()) {
return null;
}
final RegExp nameSetPattern = RegExp(r'^\s*set\(BINARY_NAME\s*"(.*)"\s*\)\s*$');
for (final String line in project.cmakeFile.readAsLinesSync()) {
final RegExpMatch match = nameSetPattern.firstMatch(line);
final RegExpMatch? match = nameSetPattern.firstMatch(line);
if (match != null) {
return match.group(1);
}
......@@ -27,13 +25,13 @@ String getCmakeExecutableName(CmakeBasedProject project) {
/// Extracts the `PACKAGE_GUID` from a project's CMake file.
///
/// Returns `null` if it cannot be found.
String getCmakePackageGuid(File cmakeFile) {
String? getCmakePackageGuid(File cmakeFile) {
if (!cmakeFile.existsSync()) {
return null;
}
final RegExp nameSetPattern = RegExp(r'^\s*set\(PACKAGE_GUID\s*"(.*)"\s*\)\s*$');
for (final String line in cmakeFile.readAsLinesSync()) {
final RegExpMatch match = nameSetPattern.firstMatch(line);
final RegExpMatch? match = nameSetPattern.firstMatch(line);
if (match != null) {
return match.group(1);
}
......
......@@ -7,6 +7,7 @@
import '../base/common.dart';
import '../build_info.dart';
import '../bundle.dart';
import '../bundle_builder.dart';
import '../features.dart';
import '../globals_null_migrated.dart' as globals;
import '../project.dart';
......
......@@ -12,7 +12,7 @@ import '../asset.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../build_info.dart';
import '../bundle.dart';
import '../bundle_builder.dart';
import '../devfs.dart';
import '../device.dart';
import '../globals_null_migrated.dart' as globals;
......
......@@ -18,6 +18,7 @@ import '../base/process.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../bundle.dart';
import '../bundle_builder.dart';
import '../convert.dart';
import '../device.dart';
import '../device_port_forwarder.dart';
......
......@@ -13,7 +13,7 @@ import '../base/file_system.dart';
import '../base/logger.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../bundle.dart';
import '../bundle_builder.dart';
import '../convert.dart';
import '../devfs.dart';
import '../globals_null_migrated.dart' as globals;
......
......@@ -4,17 +4,13 @@
// @dart = 2.8
import 'android/gradle_utils.dart';
import 'base/context.dart';
import 'device.dart';
import 'doctor.dart';
import 'fuchsia/fuchsia_sdk.dart';
import 'globals_null_migrated.dart' as globals;
import 'ios/simulators.dart';
import 'macos/cocoapods.dart';
import 'macos/cocoapods_validator.dart';
import 'macos/xcdevice.dart';
import 'project.dart';
import 'reporting/crash_reporting.dart';
import 'runner/local_engine.dart';
......@@ -24,22 +20,10 @@ CrashReporter get crashReporter => context.get<CrashReporter>();
Doctor get doctor => context.get<Doctor>();
DeviceManager get deviceManager => context.get<DeviceManager>();
FlutterProjectFactory get projectFactory {
return context.get<FlutterProjectFactory>() ?? FlutterProjectFactory(
logger: globals.logger,
fileSystem: globals.fs,
);
}
CocoaPodsValidator get cocoapodsValidator => context.get<CocoaPodsValidator>();
LocalEngineLocator get localEngineLocator => context.get<LocalEngineLocator>();
CocoaPods get cocoaPods => context.get<CocoaPods>();
FuchsiaArtifacts get fuchsiaArtifacts => context.get<FuchsiaArtifacts>();
IOSSimulatorUtils get iosSimulatorUtils => context.get<IOSSimulatorUtils>();
XCDevice get xcdevice => context.get<XCDevice>();
/// Gradle utils in the current [AppContext].
GradleUtils get gradleUtils => context.get<GradleUtils>();
......@@ -6,6 +6,7 @@ import 'package:process/process.dart';
import 'android/android_sdk.dart';
import 'android/android_studio.dart';
import 'android/gradle_utils.dart';
import 'artifacts.dart';
import 'base/bot_detector.dart';
import 'base/config.dart';
......@@ -28,8 +29,10 @@ import 'cache.dart';
import 'ios/ios_workflow.dart';
import 'ios/plist_parser.dart';
import 'ios/xcodeproj.dart';
import 'macos/cocoapods.dart';
import 'macos/xcode.dart';
import 'persistent_tool_state.dart';
import 'project.dart';
import 'reporting/reporting.dart';
import 'version.dart';
......@@ -196,3 +199,15 @@ LocalFileSystem get localFileSystem => _instance ??= LocalFileSystem(
Signals.defaultExitSignals,
shutdownHooks,
);
/// Gradle utils in the current [AppContext].
GradleUtils? get gradleUtils => context.get<GradleUtils>();
CocoaPods? get cocoaPods => context.get<CocoaPods>();
FlutterProjectFactory get projectFactory {
return context.get<FlutterProjectFactory>() ?? FlutterProjectFactory(
logger: logger,
fileSystem: fs,
);
}
......@@ -2,10 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:meta/meta.dart';
import '../artifacts.dart';
import '../base/file_system.dart';
import '../build_info.dart';
......@@ -33,11 +29,11 @@ String flutterMacOSFrameworkDir(BuildMode mode, FileSystem fileSystem,
/// targetOverride: Optional parameter, if null or unspecified the default value
/// from xcode_backend.sh is used 'lib/main.dart'.
Future<void> updateGeneratedXcodeProperties({
@required FlutterProject project,
@required BuildInfo buildInfo,
String targetOverride,
required FlutterProject project,
required BuildInfo buildInfo,
String? targetOverride,
bool useMacOSConfig = false,
String buildDirOverride,
String? buildDirOverride,
}) async {
final List<String> xcodeBuildSettings = _xcodeBuildSettingsLines(
project: project,
......@@ -64,8 +60,8 @@ Future<void> updateGeneratedXcodeProperties({
/// for Xcode targets that need them.
/// See [XcodeBasedProject.generatedXcodePropertiesFile].
void _updateGeneratedXcodePropertiesFile({
@required FlutterProject project,
@required List<String> xcodeBuildSettings,
required FlutterProject project,
required List<String> xcodeBuildSettings,
bool useMacOSConfig = false,
}) {
final StringBuffer localsBuffer = StringBuffer();
......@@ -84,8 +80,8 @@ void _updateGeneratedXcodePropertiesFile({
/// as flags for Flutter tools.
/// See [XcodeBasedProject.generatedEnvironmentVariableExportScript].
void _updateGeneratedEnvironmentVariablesScript({
@required FlutterProject project,
@required List<String> xcodeBuildSettings,
required FlutterProject project,
required List<String> xcodeBuildSettings,
bool useMacOSConfig = false,
}) {
final StringBuffer localsBuffer = StringBuffer();
......@@ -107,21 +103,21 @@ void _updateGeneratedEnvironmentVariablesScript({
}
/// Build name parsed and validated from build info and manifest. Used for CFBundleShortVersionString.
String parsedBuildName({
@required FlutterManifest manifest,
BuildInfo buildInfo,
String? parsedBuildName({
required FlutterManifest manifest,
BuildInfo? buildInfo,
}) {
final String buildNameToParse = buildInfo?.buildName ?? manifest.buildName;
final String? buildNameToParse = buildInfo?.buildName ?? manifest.buildName;
return validatedBuildNameForPlatform(TargetPlatform.ios, buildNameToParse, globals.logger);
}
/// Build number parsed and validated from build info and manifest. Used for CFBundleVersion.
String parsedBuildNumber({
@required FlutterManifest manifest,
BuildInfo buildInfo,
String? parsedBuildNumber({
required FlutterManifest manifest,
BuildInfo? buildInfo,
}) {
String buildNumberToParse = buildInfo?.buildNumber ?? manifest.buildNumber;
final String buildNumber = validatedBuildNumberForPlatform(
String? buildNumberToParse = buildInfo?.buildNumber ?? manifest.buildNumber;
final String? buildNumber = validatedBuildNumberForPlatform(
TargetPlatform.ios,
buildNumberToParse,
globals.logger,
......@@ -141,15 +137,15 @@ String parsedBuildNumber({
/// List of lines of build settings. Example: 'FLUTTER_BUILD_DIR=build'
List<String> _xcodeBuildSettingsLines({
@required FlutterProject project,
@required BuildInfo buildInfo,
String targetOverride,
required FlutterProject project,
required BuildInfo buildInfo,
String? targetOverride,
bool useMacOSConfig = false,
String buildDirOverride,
String? buildDirOverride,
}) {
final List<String> xcodeBuildSettings = <String>[];
final String flutterRoot = globals.fs.path.normalize(Cache.flutterRoot);
final String flutterRoot = globals.fs.path.normalize(Cache.flutterRoot!);
xcodeBuildSettings.add('FLUTTER_ROOT=$flutterRoot');
// This holds because requiresProjectRoot is true for this command
......@@ -173,7 +169,7 @@ List<String> _xcodeBuildSettingsLines({
final String buildNumber = parsedBuildNumber(manifest: project.manifest, buildInfo: buildInfo) ?? '1';
xcodeBuildSettings.add('FLUTTER_BUILD_NUMBER=$buildNumber');
final Artifacts artifacts = globals.artifacts;
final Artifacts? artifacts = globals.artifacts;
if (artifacts is LocalEngineArtifacts) {
final LocalEngineArtifacts localEngineArtifacts = artifacts;
final String engineOutPath = localEngineArtifacts.engineOutPath;
......
......@@ -29,7 +29,7 @@ import '../base/net.dart';
import '../base/platform.dart';
import '../build_info.dart';
import '../build_system/targets/web.dart';
import '../bundle.dart';
import '../bundle_builder.dart';
import '../cache.dart';
import '../compile.dart';
import '../convert.dart';
......
......@@ -2,10 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:file/file.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart';
import '../base/common.dart';
......@@ -85,12 +82,12 @@ const Version cocoaPodsRecommendedVersion = Version.withText(1, 10, 0, '1.10.0')
/// installing iOS/macOS dependencies.
class CocoaPods {
CocoaPods({
@required FileSystem fileSystem,
@required ProcessManager processManager,
@required XcodeProjectInterpreter xcodeProjectInterpreter,
@required Logger logger,
@required Platform platform,
@required Usage usage,
required FileSystem fileSystem,
required ProcessManager processManager,
required XcodeProjectInterpreter xcodeProjectInterpreter,
required Logger logger,
required Platform platform,
required Usage usage,
}) : _fileSystem = fileSystem,
_processManager = processManager,
_xcodeProjectInterpreter = xcodeProjectInterpreter,
......@@ -112,33 +109,33 @@ class CocoaPods {
final Logger _logger;
final Usage _usage;
Future<String> _versionText;
Future<String?>? _versionText;
Future<bool> get isInstalled =>
_processUtils.exitsHappy(<String>['which', 'pod']);
Future<String> get cocoaPodsVersionText {
Future<String?> get cocoaPodsVersionText {
_versionText ??= _processUtils.run(
<String>['pod', '--version'],
environment: <String, String>{
'LANG': 'en_US.UTF-8',
},
).then<String>((RunResult result) {
).then<String?>((RunResult result) {
return result.exitCode == 0 ? result.stdout.trim() : null;
}, onError: (dynamic _) => null);
return _versionText;
return _versionText!;
}
Future<CocoaPodsStatus> get evaluateCocoaPodsInstallation async {
if (!(await isInstalled)) {
return CocoaPodsStatus.notInstalled;
}
final String versionText = await cocoaPodsVersionText;
final String? versionText = await cocoaPodsVersionText;
if (versionText == null) {
return CocoaPodsStatus.brokenInstall;
}
try {
final Version installedVersion = Version.parse(versionText);
final Version? installedVersion = Version.parse(versionText);
if (installedVersion == null) {
return CocoaPodsStatus.unknownVersion;
}
......@@ -155,8 +152,8 @@ class CocoaPods {
}
Future<bool> processPods({
@required XcodeBasedProject xcodeProject,
@required BuildMode buildMode,
required XcodeBasedProject xcodeProject,
required BuildMode buildMode,
bool dependenciesChanged = true,
}) async {
if (!xcodeProject.podfile.existsSync()) {
......@@ -253,7 +250,7 @@ class CocoaPods {
podfileTemplateName = isSwift ? 'Podfile-ios-swift' : 'Podfile-ios-objc';
}
final File podfileTemplate = _fileSystem.file(_fileSystem.path.join(
Cache.flutterRoot,
Cache.flutterRoot!,
'packages',
'flutter_tools',
'templates',
......@@ -391,7 +388,7 @@ class CocoaPods {
//
// Warn the user if they are still symlinking to the framework.
final Link flutterSymlink = _fileSystem.link(_fileSystem.path.join(
(xcodeProject as IosProject).symlinks.path,
xcodeProject.symlinks.path,
'flutter',
));
if (flutterSymlink.existsSync()) {
......
This diff is collapsed.
......@@ -18,6 +18,7 @@ import '../base/logger.dart';
import '../base/os.dart';
import '../build_info.dart';
import '../bundle.dart';
import '../bundle_builder.dart';
import '../desktop_device.dart';
import '../devfs.dart';
import '../device.dart';
......
......@@ -10,6 +10,7 @@ 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/bundle.dart';
import 'package:flutter_tools/src/bundle_builder.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/build_bundle.dart';
import 'package:flutter_tools/src/features.dart';
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/gradle.dart';
import 'package:flutter_tools/src/base/file_system.dart';
......@@ -15,7 +13,7 @@ import 'package:flutter_tools/src/reporting/reporting.dart';
import '../../src/common.dart';
void main() {
FileSystem fileSystem;
late FileSystem fileSystem;
setUp(() {
fileSystem = MemoryFileSystem.test();
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/gradle_utils.dart';
import 'package:flutter_tools/src/base/file_system.dart';
......@@ -17,9 +15,9 @@ import '../../src/fakes.dart';
void main() {
group('injectGradleWrapperIfNeeded', () {
MemoryFileSystem fileSystem;
Directory gradleWrapperDirectory;
GradleUtils gradleUtils;
late MemoryFileSystem fileSystem;
late Directory gradleWrapperDirectory;
late GradleUtils gradleUtils;
setUp(() {
fileSystem = MemoryFileSystem.test();
......
......@@ -2,13 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/platform_plugins.dart';
import '../src/common.dart';
void main() {
......
......@@ -11,7 +11,7 @@ import 'package:file/memory.dart';
import 'package:flutter_tools/src/asset.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/bundle.dart';
import 'package:flutter_tools/src/bundle_builder.dart';
import 'package:flutter_tools/src/devfs.dart';
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
......
......@@ -8,7 +8,7 @@ import 'package:file/memory.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/bundle.dart';
import 'package:flutter_tools/src/bundle_builder.dart';
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
import 'package:flutter_tools/src/project.dart';
......
......@@ -13,6 +13,7 @@ import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/bundle.dart';
import 'package:flutter_tools/src/bundle_builder.dart';
import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/custom_devices/custom_device.dart';
import 'package:flutter_tools/src/custom_devices/custom_device_config.dart';
......
......@@ -2,39 +2,35 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_tools/src/android/android_builder.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
import 'package:flutter_tools/src/project.dart';
import 'package:meta/meta.dart';
/// A fake implementation of [AndroidBuilder].
class FakeAndroidBuilder implements AndroidBuilder {
@override
Future<void> buildAar({
@required FlutterProject project,
@required Set<AndroidBuildInfo> androidBuildInfo,
@required String target,
@required String outputDirectoryPath,
@required String buildNumber,
required FlutterProject project,
required Set<AndroidBuildInfo> androidBuildInfo,
required String target,
String? outputDirectoryPath,
required String buildNumber,
}) async {}
@override
Future<void> buildApk({
@required FlutterProject project,
@required AndroidBuildInfo androidBuildInfo,
@required String target,
required FlutterProject project,
required AndroidBuildInfo androidBuildInfo,
required String target,
}) async {}
@override
Future<void> buildAab({
@required FlutterProject project,
@required AndroidBuildInfo androidBuildInfo,
@required String target,
required FlutterProject project,
required AndroidBuildInfo androidBuildInfo,
required String target,
bool validateDeferredComponents = true,
bool deferredComponentsEnabled = false,
}) async {}
......
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