mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Migrate project.dart and all dependencies to null safety (#83817)
This commit is contained in:
parent
2c645e4ccf
commit
c4a2a3e92d
@ -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,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:crypto/crypto.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:process/process.dart';
|
||||
@ -126,7 +124,7 @@ void createSettingsAarGradle(Directory androidDirectory, Logger logger) {
|
||||
final String newSettingsRelativeFile = fileSystem.path.relative(newSettingsFile.path);
|
||||
final Status status = logger.startProgress('✏️ Creating `$newSettingsRelativeFile`...');
|
||||
|
||||
final String flutterRoot = fileSystem.path.absolute(Cache.flutterRoot);
|
||||
final String flutterRoot = fileSystem.path.absolute(Cache.flutterRoot!);
|
||||
final File legacySettingsDotGradleFiles = fileSystem.file(fileSystem.path.join(flutterRoot, 'packages','flutter_tools',
|
||||
'gradle', 'settings.gradle.legacy_versions'));
|
||||
assert(legacySettingsDotGradleFiles.existsSync());
|
||||
@ -161,13 +159,13 @@ void createSettingsAarGradle(Directory androidDirectory, Logger logger) {
|
||||
/// An implementation of the [AndroidBuilder] that delegates to gradle.
|
||||
class AndroidGradleBuilder implements AndroidBuilder {
|
||||
AndroidGradleBuilder({
|
||||
@required Logger logger,
|
||||
@required ProcessManager processManager,
|
||||
@required FileSystem fileSystem,
|
||||
@required Artifacts artifacts,
|
||||
@required Usage usage,
|
||||
@required GradleUtils gradleUtils,
|
||||
@required Platform platform,
|
||||
required Logger logger,
|
||||
required ProcessManager processManager,
|
||||
required FileSystem fileSystem,
|
||||
required Artifacts artifacts,
|
||||
required Usage usage,
|
||||
required GradleUtils gradleUtils,
|
||||
required Platform platform,
|
||||
}) : _logger = logger,
|
||||
_fileSystem = fileSystem,
|
||||
_artifacts = artifacts,
|
||||
@ -187,11 +185,11 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
/// Builds the AAR and POM files for the current Flutter module or plugin.
|
||||
@override
|
||||
Future<void> buildAar({
|
||||
@required FlutterProject project,
|
||||
@required Set<AndroidBuildInfo> androidBuildInfo,
|
||||
@required String target,
|
||||
String outputDirectoryPath,
|
||||
@required String buildNumber,
|
||||
required FlutterProject project,
|
||||
required Set<AndroidBuildInfo> androidBuildInfo,
|
||||
required String target,
|
||||
String? outputDirectoryPath,
|
||||
required String buildNumber,
|
||||
}) async {
|
||||
Directory outputDirectory =
|
||||
_fileSystem.directory(outputDirectoryPath ?? project.android.buildDirectory);
|
||||
@ -224,9 +222,9 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
/// Builds the APK.
|
||||
@override
|
||||
Future<void> buildApk({
|
||||
@required FlutterProject project,
|
||||
@required AndroidBuildInfo androidBuildInfo,
|
||||
@required String target,
|
||||
required FlutterProject project,
|
||||
required AndroidBuildInfo androidBuildInfo,
|
||||
required String target,
|
||||
}) async {
|
||||
await buildGradleApp(
|
||||
project: project,
|
||||
@ -240,9 +238,9 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
/// Builds the App Bundle.
|
||||
@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 {
|
||||
@ -269,11 +267,11 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
/// * [retries] is the max number of build retries in case one of the [GradleHandledError] handler
|
||||
/// returns [GradleBuildStatus.retry] or [GradleBuildStatus.retryWithAarPlugins].
|
||||
Future<void> buildGradleApp({
|
||||
@required FlutterProject project,
|
||||
@required AndroidBuildInfo androidBuildInfo,
|
||||
@required String target,
|
||||
@required bool isBuildingBundle,
|
||||
@required List<GradleHandledError> localGradleErrors,
|
||||
required FlutterProject project,
|
||||
required AndroidBuildInfo androidBuildInfo,
|
||||
required String target,
|
||||
required bool isBuildingBundle,
|
||||
required List<GradleHandledError> localGradleErrors,
|
||||
bool shouldBuildPluginAsAar = false,
|
||||
bool validateDeferredComponents = true,
|
||||
bool deferredComponentsEnabled = false,
|
||||
@ -361,7 +359,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
if (target != null) {
|
||||
command.add('-Ptarget=$target');
|
||||
}
|
||||
final List<DeferredComponent> deferredComponents = project.manifest.deferredComponents;
|
||||
final List<DeferredComponent>? deferredComponents = project.manifest.deferredComponents;
|
||||
if (deferredComponents != null) {
|
||||
if (deferredComponentsEnabled) {
|
||||
command.add('-Pdeferred-components=true');
|
||||
@ -406,9 +404,9 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
}
|
||||
command.add(assembleTask);
|
||||
|
||||
GradleHandledError detectedGradleError;
|
||||
String detectedGradleErrorLine;
|
||||
String consumeLog(String line) {
|
||||
GradleHandledError? detectedGradleError;
|
||||
String? detectedGradleErrorLine;
|
||||
String? consumeLog(String line) {
|
||||
// This message was removed from first-party plugins,
|
||||
// but older plugin versions still display this message.
|
||||
if (androidXPluginWarningRegex.hasMatch(line)) {
|
||||
@ -441,7 +439,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
allowReentrantFlutter: true,
|
||||
environment: <String, String>{
|
||||
if (javaPath != null)
|
||||
'JAVA_HOME': javaPath,
|
||||
'JAVA_HOME': javaPath!,
|
||||
},
|
||||
mapFunction: consumeLog,
|
||||
);
|
||||
@ -466,15 +464,15 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
exitCode: exitCode,
|
||||
);
|
||||
} else {
|
||||
final GradleBuildStatus status = await detectedGradleError.handler(
|
||||
line: detectedGradleErrorLine,
|
||||
final GradleBuildStatus status = await detectedGradleError!.handler(
|
||||
line: detectedGradleErrorLine!,
|
||||
project: project,
|
||||
usesAndroidX: usesAndroidX,
|
||||
shouldBuildPluginAsAar: shouldBuildPluginAsAar,
|
||||
);
|
||||
|
||||
if (retries >= 1) {
|
||||
final String successEventLabel = 'gradle-${detectedGradleError.eventLabel}-success';
|
||||
final String successEventLabel = 'gradle-${detectedGradleError!.eventLabel}-success';
|
||||
switch (status) {
|
||||
case GradleBuildStatus.retry:
|
||||
await buildGradleApp(
|
||||
@ -504,7 +502,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
// noop.
|
||||
}
|
||||
}
|
||||
BuildEvent('gradle-${detectedGradleError.eventLabel}-failure', type: 'gradle', flutterUsage: _usage).send();
|
||||
BuildEvent('gradle-${detectedGradleError?.eventLabel}-failure', type: 'gradle', flutterUsage: _usage).send();
|
||||
throwToolExit(
|
||||
'Gradle task $assembleTask failed with exit code $exitCode',
|
||||
exitCode: exitCode,
|
||||
@ -580,7 +578,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
.childFile('snapshot.$archName.json');
|
||||
final File precompilerTrace = _fileSystem.directory(buildInfo.codeSizeDirectory)
|
||||
.childFile('trace.$archName.json');
|
||||
final Map<String, Object> output = await sizeAnalyzer.analyzeZipSizeAndAotSnapshot(
|
||||
final Map<String, Object?> output = await sizeAnalyzer.analyzeZipSizeAndAotSnapshot(
|
||||
zipFile: zipFile,
|
||||
aotSnapshot: aotSnapshot,
|
||||
precompilerTrace: precompilerTrace,
|
||||
@ -616,11 +614,11 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
/// * [outputDir] is the destination of the artifacts,
|
||||
/// * [buildNumber] is the build number of the output aar,
|
||||
Future<void> buildGradleAar({
|
||||
@required FlutterProject project,
|
||||
@required AndroidBuildInfo androidBuildInfo,
|
||||
@required String target,
|
||||
@required Directory outputDirectory,
|
||||
@required String buildNumber,
|
||||
required FlutterProject project,
|
||||
required AndroidBuildInfo androidBuildInfo,
|
||||
required String target,
|
||||
required Directory outputDirectory,
|
||||
required String buildNumber,
|
||||
}) async {
|
||||
assert(project != null);
|
||||
assert(target != null);
|
||||
@ -638,7 +636,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
"Running Gradle task '$aarTask'...",
|
||||
);
|
||||
|
||||
final String flutterRoot = _fileSystem.path.absolute(Cache.flutterRoot);
|
||||
final String flutterRoot = _fileSystem.path.absolute(Cache.flutterRoot!);
|
||||
final String initScript = _fileSystem.path.join(
|
||||
flutterRoot,
|
||||
'packages',
|
||||
@ -721,7 +719,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
allowReentrantFlutter: true,
|
||||
environment: <String, String>{
|
||||
if (javaPath != null)
|
||||
'JAVA_HOME': javaPath,
|
||||
'JAVA_HOME': javaPath!,
|
||||
},
|
||||
);
|
||||
} finally {
|
||||
@ -757,7 +755,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
Future<void> buildPluginsAsAar(
|
||||
FlutterProject flutterProject,
|
||||
AndroidBuildInfo androidBuildInfo, {
|
||||
@required Directory buildDirectory,
|
||||
required Directory buildDirectory,
|
||||
}) async {
|
||||
final File flutterPluginFile = flutterProject.flutterPluginsFile;
|
||||
if (!flutterPluginFile.existsSync()) {
|
||||
@ -806,12 +804,12 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
|
||||
/// Prints how to consume the AAR from a host app.
|
||||
void printHowToConsumeAar({
|
||||
@required Set<String> buildModes,
|
||||
String androidPackage = 'unknown',
|
||||
@required Directory repoDirectory,
|
||||
@required Logger logger,
|
||||
@required FileSystem fileSystem,
|
||||
String buildNumber,
|
||||
required Set<String> buildModes,
|
||||
String? androidPackage = 'unknown',
|
||||
required Directory repoDirectory,
|
||||
required Logger logger,
|
||||
required FileSystem fileSystem,
|
||||
String? buildNumber,
|
||||
}) {
|
||||
assert(buildModes != null && buildModes.isNotEmpty);
|
||||
assert(repoDirectory != null);
|
||||
@ -919,7 +917,7 @@ Iterable<String> findApkFilesModule(
|
||||
if (apkFile.existsSync()) {
|
||||
return <File>[apkFile];
|
||||
}
|
||||
final String flavor = buildInfo.flavor;
|
||||
final String? flavor = buildInfo.flavor;
|
||||
if (flavor != null) {
|
||||
// Android Studio Gradle plugin v3 adds flavor to path.
|
||||
apkFile = apkDirectory
|
||||
@ -954,7 +952,7 @@ Iterable<String> listApkPaths(
|
||||
final String buildType = camelCase(androidBuildInfo.buildInfo.modeName);
|
||||
final List<String> apkPartialName = <String>[
|
||||
if (androidBuildInfo.buildInfo.flavor?.isNotEmpty ?? false)
|
||||
androidBuildInfo.buildInfo.lowerCasedFlavor,
|
||||
androidBuildInfo.buildInfo.lowerCasedFlavor!,
|
||||
'$buildType.apk',
|
||||
];
|
||||
if (androidBuildInfo.splitPerAbi) {
|
||||
@ -1013,15 +1011,14 @@ File findBundleFile(FlutterProject project, BuildInfo buildInfo, Logger logger,
|
||||
logger: logger,
|
||||
usage: usage,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Throws a [ToolExit] exception and logs the event.
|
||||
void _exitWithExpectedFileNotFound({
|
||||
@required FlutterProject project,
|
||||
@required String fileExtension,
|
||||
@required Logger logger,
|
||||
@required Usage usage,
|
||||
Never _exitWithExpectedFileNotFound({
|
||||
required FlutterProject project,
|
||||
required String fileExtension,
|
||||
required Logger logger,
|
||||
required Usage usage,
|
||||
}) {
|
||||
assert(project != null);
|
||||
assert(fileExtension != null);
|
||||
@ -1090,9 +1087,9 @@ String _getLocalArtifactVersion(String pomPath, FileSystem fileSystem) {
|
||||
/// This method generates symlinks in the temp directory to the engine artifacts
|
||||
/// following the convention specified on https://maven.apache.org/pom.html#Repositories
|
||||
Directory _getLocalEngineRepo({
|
||||
@required String engineOutPath,
|
||||
@required AndroidBuildInfo androidBuildInfo,
|
||||
@required FileSystem fileSystem,
|
||||
required String engineOutPath,
|
||||
required AndroidBuildInfo androidBuildInfo,
|
||||
required FileSystem fileSystem,
|
||||
}) {
|
||||
assert(engineOutPath != null);
|
||||
assert(androidBuildInfo != null);
|
||||
|
@ -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();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
171
packages/flutter_tools/lib/src/bundle_builder.dart
Normal file
171
packages/flutter_tools/lib/src/bundle_builder.dart
Normal file
@ -0,0 +1,171 @@
|
||||
// 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';
|
||||
|
@ -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 'package:package_config/package_config.dart';
|
||||
import 'package:path/path.dart' as path; // flutter_ignore: package_path_import
|
||||
@ -22,25 +20,25 @@ import 'convert.dart';
|
||||
import 'dart/language_version.dart';
|
||||
import 'dart/package_map.dart';
|
||||
import 'features.dart';
|
||||
import 'globals.dart' as globals;
|
||||
import 'globals_null_migrated.dart' as globals;
|
||||
import 'platform_plugins.dart';
|
||||
import 'plugins.dart';
|
||||
import 'project.dart';
|
||||
|
||||
void _renderTemplateToFile(String template, dynamic context, File file, TemplateRenderer templateRenderer) {
|
||||
void _renderTemplateToFile(String template, Object? context, File file, TemplateRenderer templateRenderer) {
|
||||
final String renderedTemplate = templateRenderer
|
||||
.renderString(template, context, htmlEscapeValues: false);
|
||||
file.createSync(recursive: true);
|
||||
file.writeAsStringSync(renderedTemplate);
|
||||
}
|
||||
|
||||
Plugin _pluginFromPackage(String name, Uri packageRoot, Set<String> appDependencies, {FileSystem fileSystem}) {
|
||||
Plugin? _pluginFromPackage(String name, Uri packageRoot, Set<String> appDependencies, {FileSystem? fileSystem}) {
|
||||
final FileSystem fs = fileSystem ?? globals.fs;
|
||||
final File pubspecFile = fs.file(packageRoot.resolve('pubspec.yaml'));
|
||||
if (!pubspecFile.existsSync()) {
|
||||
return null;
|
||||
}
|
||||
dynamic pubspec;
|
||||
Object? pubspec;
|
||||
|
||||
try {
|
||||
pubspec = loadYaml(pubspecFile.readAsStringSync());
|
||||
@ -48,20 +46,20 @@ Plugin _pluginFromPackage(String name, Uri packageRoot, Set<String> appDependenc
|
||||
globals.printTrace('Failed to parse plugin manifest for $name: $err');
|
||||
// Do nothing, potentially not a plugin.
|
||||
}
|
||||
if (pubspec == null) {
|
||||
if (pubspec == null || pubspec is! YamlMap) {
|
||||
return null;
|
||||
}
|
||||
final dynamic flutterConfig = pubspec['flutter'];
|
||||
if (flutterConfig == null || !(flutterConfig.containsKey('plugin') as bool)) {
|
||||
final Object? flutterConfig = pubspec['flutter'];
|
||||
if (flutterConfig == null || flutterConfig is! YamlMap || !flutterConfig.containsKey('plugin')) {
|
||||
return null;
|
||||
}
|
||||
final String packageRootPath = fs.path.fromUri(packageRoot);
|
||||
final YamlMap dependencies = pubspec['dependencies'] as YamlMap;
|
||||
final YamlMap? dependencies = pubspec['dependencies'] as YamlMap?;
|
||||
globals.printTrace('Found plugin $name at $packageRootPath');
|
||||
return Plugin.fromYaml(
|
||||
name,
|
||||
packageRootPath,
|
||||
flutterConfig['plugin'] as YamlMap,
|
||||
flutterConfig['plugin'] as YamlMap?,
|
||||
dependencies == null ? <String>[] : <String>[...dependencies.keys.cast<String>()],
|
||||
fileSystem: fs,
|
||||
appDependencies: appDependencies,
|
||||
@ -82,7 +80,7 @@ Future<List<Plugin>> findPlugins(FlutterProject project, { bool throwOnError = t
|
||||
);
|
||||
for (final Package package in packageConfig.packages) {
|
||||
final Uri packageRoot = package.packageUriRoot.resolve('..');
|
||||
final Plugin plugin = _pluginFromPackage(
|
||||
final Plugin? plugin = _pluginFromPackage(
|
||||
package.name,
|
||||
packageRoot,
|
||||
project.manifest.dependencies,
|
||||
@ -102,15 +100,15 @@ const String _kFlutterPluginsPathKey = 'path';
|
||||
const String _kFlutterPluginsDependenciesKey = 'dependencies';
|
||||
|
||||
/// Filters [plugins] to those supported by [platformKey].
|
||||
List<Map<String, dynamic>> _filterPluginsByPlatform(List<Plugin> plugins, String platformKey) {
|
||||
List<Map<String, Object>> _filterPluginsByPlatform(List<Plugin> plugins, String platformKey) {
|
||||
final Iterable<Plugin> platformPlugins = plugins.where((Plugin p) {
|
||||
return p.platforms.containsKey(platformKey);
|
||||
});
|
||||
|
||||
final Set<String> pluginNames = platformPlugins.map((Plugin plugin) => plugin.name).toSet();
|
||||
final List<Map<String, dynamic>> pluginInfo = <Map<String, dynamic>>[];
|
||||
final List<Map<String, Object>> pluginInfo = <Map<String, Object>>[];
|
||||
for (final Plugin plugin in platformPlugins) {
|
||||
pluginInfo.add(<String, dynamic>{
|
||||
pluginInfo.add(<String, Object>{
|
||||
_kFlutterPluginsNameKey: plugin.name,
|
||||
_kFlutterPluginsPathKey: globals.fsUtils.escapePath(plugin.path),
|
||||
_kFlutterPluginsDependenciesKey: <String>[...plugin.dependencies.where(pluginNames.contains)],
|
||||
@ -179,7 +177,7 @@ bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) {
|
||||
final String windowsKey = project.windows.pluginConfigKey;
|
||||
final String webKey = project.web.pluginConfigKey;
|
||||
|
||||
final Map<String, dynamic> pluginsMap = <String, dynamic>{};
|
||||
final Map<String, Object> pluginsMap = <String, Object>{};
|
||||
pluginsMap[iosKey] = _filterPluginsByPlatform(plugins, iosKey);
|
||||
pluginsMap[androidKey] = _filterPluginsByPlatform(plugins, androidKey);
|
||||
pluginsMap[macosKey] = _filterPluginsByPlatform(plugins, macosKey);
|
||||
@ -187,7 +185,7 @@ bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) {
|
||||
pluginsMap[windowsKey] = _filterPluginsByPlatform(plugins, windowsKey);
|
||||
pluginsMap[webKey] = _filterPluginsByPlatform(plugins, webKey);
|
||||
|
||||
final Map<String, dynamic> result = <String, dynamic> {};
|
||||
final Map<String, Object> result = <String, Object> {};
|
||||
|
||||
result['info'] = 'This is a generated file; do not edit or check into version control.';
|
||||
result[_kFlutterPluginsPluginListKey] = pluginsMap;
|
||||
@ -200,7 +198,7 @@ bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) {
|
||||
|
||||
// Only notify if the plugins list has changed. [date_created] will always be different,
|
||||
// [version] is not relevant for this check.
|
||||
final String oldPluginsFileStringContent = _readFileContent(pluginsFile);
|
||||
final String? oldPluginsFileStringContent = _readFileContent(pluginsFile);
|
||||
bool pluginsChanged = true;
|
||||
if (oldPluginsFileStringContent != null) {
|
||||
pluginsChanged = oldPluginsFileStringContent.contains(pluginsMap.toString());
|
||||
@ -211,12 +209,12 @@ bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) {
|
||||
return pluginsChanged;
|
||||
}
|
||||
|
||||
List<dynamic> _createPluginLegacyDependencyGraph(List<Plugin> plugins) {
|
||||
final List<dynamic> directAppDependencies = <dynamic>[];
|
||||
List<Object?> _createPluginLegacyDependencyGraph(List<Plugin> plugins) {
|
||||
final List<Object> directAppDependencies = <Object>[];
|
||||
|
||||
final Set<String> pluginNames = plugins.map((Plugin plugin) => plugin.name).toSet();
|
||||
for (final Plugin plugin in plugins) {
|
||||
directAppDependencies.add(<String, dynamic>{
|
||||
directAppDependencies.add(<String, Object>{
|
||||
'name': plugin.name,
|
||||
// Extract the plugin dependencies which happen to be plugins.
|
||||
'dependencies': <String>[...plugin.dependencies.where(pluginNames.contains)],
|
||||
@ -245,7 +243,7 @@ bool _writeFlutterPluginsListLegacy(FlutterProject project, List<Plugin> plugins
|
||||
for (final Plugin plugin in plugins) {
|
||||
flutterPluginsBuffer.write('${plugin.name}=${globals.fsUtils.escapePath(plugin.path)}\n');
|
||||
}
|
||||
final String oldPluginFileContent = _readFileContent(pluginsFile);
|
||||
final String? oldPluginFileContent = _readFileContent(pluginsFile);
|
||||
final String pluginFileContent = flutterPluginsBuffer.toString();
|
||||
pluginsFile.writeAsStringSync(pluginFileContent, flush: true);
|
||||
|
||||
@ -253,7 +251,7 @@ bool _writeFlutterPluginsListLegacy(FlutterProject project, List<Plugin> plugins
|
||||
}
|
||||
|
||||
/// Returns the contents of [File] or [null] if that file does not exist.
|
||||
String _readFileContent(File file) {
|
||||
String? _readFileContent(File file) {
|
||||
return file.existsSync() ? file.readAsStringSync() : null;
|
||||
}
|
||||
|
||||
@ -335,10 +333,10 @@ public final class GeneratedPluginRegistrant {
|
||||
}
|
||||
''';
|
||||
|
||||
List<Map<String, dynamic>> _extractPlatformMaps(List<Plugin> plugins, String type) {
|
||||
final List<Map<String, dynamic>> pluginConfigs = <Map<String, dynamic>>[];
|
||||
List<Map<String, Object?>> _extractPlatformMaps(List<Plugin> plugins, String type) {
|
||||
final List<Map<String, Object?>> pluginConfigs = <Map<String, Object?>>[];
|
||||
for (final Plugin p in plugins) {
|
||||
final PluginPlatform platformPlugin = p.platforms[type];
|
||||
final PluginPlatform? platformPlugin = p.platforms[type];
|
||||
if (platformPlugin != null) {
|
||||
pluginConfigs.add(platformPlugin.toMap());
|
||||
}
|
||||
@ -355,10 +353,10 @@ AndroidEmbeddingVersion _getAndroidEmbeddingVersion(FlutterProject project) {
|
||||
}
|
||||
|
||||
Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin> plugins) async {
|
||||
final List<Map<String, dynamic>> androidPlugins =
|
||||
final List<Map<String, Object?>> androidPlugins =
|
||||
_extractPlatformMaps(plugins, AndroidPlugin.kConfigKey);
|
||||
|
||||
final Map<String, dynamic> templateContext = <String, dynamic>{
|
||||
final Map<String, Object> templateContext = <String, Object>{
|
||||
'plugins': androidPlugins,
|
||||
'androidX': isAppUsingAndroidX(project.android.hostAppGradleRoot),
|
||||
};
|
||||
@ -382,8 +380,10 @@ Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin>
|
||||
templateContext['needsShim'] = false;
|
||||
// If a plugin is using an embedding version older than 2.0 and the app is using 2.0,
|
||||
// then add shim for the old plugins.
|
||||
for (final Map<String, dynamic> plugin in androidPlugins) {
|
||||
if (plugin['supportsEmbeddingV1'] as bool && !(plugin['supportsEmbeddingV2'] as bool)) {
|
||||
for (final Map<String, Object?> plugin in androidPlugins) {
|
||||
final bool supportsEmbeddingV1 = (plugin['supportsEmbeddingV1'] as bool?) == true;
|
||||
final bool supportsEmbeddingV2 = (plugin['supportsEmbeddingV2'] as bool?) == true;
|
||||
if (supportsEmbeddingV1 && !supportsEmbeddingV2) {
|
||||
templateContext['needsShim'] = true;
|
||||
if (project.isModule) {
|
||||
globals.printStatus(
|
||||
@ -401,8 +401,10 @@ Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin>
|
||||
break;
|
||||
case AndroidEmbeddingVersion.v1:
|
||||
default:
|
||||
for (final Map<String, dynamic> plugin in androidPlugins) {
|
||||
if (!(plugin['supportsEmbeddingV1'] as bool) && plugin['supportsEmbeddingV2'] as bool) {
|
||||
for (final Map<String, Object?> plugin in androidPlugins) {
|
||||
final bool supportsEmbeddingV1 = (plugin['supportsEmbeddingV1'] as bool?) == true;
|
||||
final bool supportsEmbeddingV2 = (plugin['supportsEmbeddingV2'] as bool?) == true;
|
||||
if (!supportsEmbeddingV1 && supportsEmbeddingV2) {
|
||||
throwToolExit(
|
||||
'The plugin `${plugin['name']}` requires your app to be migrated to '
|
||||
'the Android embedding v2. Follow the steps on https://flutter.dev/go/android-project-migration '
|
||||
@ -711,8 +713,8 @@ void main(List<String> args) {
|
||||
''';
|
||||
|
||||
Future<void> _writeIOSPluginRegistrant(FlutterProject project, List<Plugin> plugins) async {
|
||||
final List<Map<String, dynamic>> iosPlugins = _extractPlatformMaps(plugins, IOSPlugin.kConfigKey);
|
||||
final Map<String, dynamic> context = <String, dynamic>{
|
||||
final List<Map<String, Object?>> iosPlugins = _extractPlatformMaps(plugins, IOSPlugin.kConfigKey);
|
||||
final Map<String, Object> context = <String, Object>{
|
||||
'os': 'ios',
|
||||
'deploymentTarget': '9.0',
|
||||
'framework': 'Flutter',
|
||||
@ -761,8 +763,8 @@ String _cmakeRelativePluginSymlinkDirectoryPath(CmakeBasedProject project) {
|
||||
|
||||
Future<void> _writeLinuxPluginFiles(FlutterProject project, List<Plugin> plugins) async {
|
||||
final List<Plugin>nativePlugins = _filterNativePlugins(plugins, LinuxPlugin.kConfigKey);
|
||||
final List<Map<String, dynamic>> linuxPlugins = _extractPlatformMaps(nativePlugins, LinuxPlugin.kConfigKey);
|
||||
final Map<String, dynamic> context = <String, dynamic>{
|
||||
final List<Map<String, Object?>> linuxPlugins = _extractPlatformMaps(nativePlugins, LinuxPlugin.kConfigKey);
|
||||
final Map<String, Object> context = <String, Object>{
|
||||
'os': 'linux',
|
||||
'plugins': linuxPlugins,
|
||||
'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.linux),
|
||||
@ -771,7 +773,7 @@ Future<void> _writeLinuxPluginFiles(FlutterProject project, List<Plugin> plugins
|
||||
await _writePluginCmakefile(project.linux.generatedPluginCmakeFile, context, globals.templateRenderer);
|
||||
}
|
||||
|
||||
Future<void> _writeLinuxPluginRegistrant(Directory destination, Map<String, dynamic> templateContext) async {
|
||||
Future<void> _writeLinuxPluginRegistrant(Directory destination, Map<String, Object> templateContext) async {
|
||||
_renderTemplateToFile(
|
||||
_linuxPluginRegistryHeaderTemplate,
|
||||
templateContext,
|
||||
@ -786,7 +788,7 @@ Future<void> _writeLinuxPluginRegistrant(Directory destination, Map<String, dyna
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _writePluginCmakefile(File destinationFile, Map<String, dynamic> templateContext, TemplateRenderer templateRenderer) async {
|
||||
Future<void> _writePluginCmakefile(File destinationFile, Map<String, Object> templateContext, TemplateRenderer templateRenderer) async {
|
||||
_renderTemplateToFile(
|
||||
_pluginCmakefileTemplate,
|
||||
templateContext,
|
||||
@ -797,8 +799,8 @@ Future<void> _writePluginCmakefile(File destinationFile, Map<String, dynamic> te
|
||||
|
||||
Future<void> _writeMacOSPluginRegistrant(FlutterProject project, List<Plugin> plugins) async {
|
||||
final List<Plugin>nativePlugins = _filterNativePlugins(plugins, MacOSPlugin.kConfigKey);
|
||||
final List<Map<String, dynamic>> macosPlugins = _extractPlatformMaps(nativePlugins, MacOSPlugin.kConfigKey);
|
||||
final Map<String, dynamic> context = <String, dynamic>{
|
||||
final List<Map<String, Object?>> macosPlugins = _extractPlatformMaps(nativePlugins, MacOSPlugin.kConfigKey);
|
||||
final Map<String, Object> context = <String, Object>{
|
||||
'os': 'macos',
|
||||
'framework': 'FlutterMacOS',
|
||||
'plugins': macosPlugins,
|
||||
@ -814,7 +816,7 @@ Future<void> _writeMacOSPluginRegistrant(FlutterProject project, List<Plugin> pl
|
||||
/// Filters out Dart-only plugins, which shouldn't be added to the native generated registrants.
|
||||
List<Plugin> _filterNativePlugins(List<Plugin> plugins, String platformKey) {
|
||||
return plugins.where((Plugin element) {
|
||||
final PluginPlatform plugin = element.platforms[platformKey];
|
||||
final PluginPlatform? plugin = element.platforms[platformKey];
|
||||
if (plugin == null) {
|
||||
return false;
|
||||
}
|
||||
@ -830,7 +832,7 @@ List<Plugin> _filterNativePlugins(List<Plugin> plugins, String platformKey) {
|
||||
/// Returns only the plugins with the given platform variant.
|
||||
List<Plugin> _filterPluginsByVariant(List<Plugin> plugins, String platformKey, PluginPlatformVariant variant) {
|
||||
return plugins.where((Plugin element) {
|
||||
final PluginPlatform platformPlugin = element.platforms[platformKey];
|
||||
final PluginPlatform? platformPlugin = element.platforms[platformKey];
|
||||
if (platformPlugin == null) {
|
||||
return false;
|
||||
}
|
||||
@ -844,8 +846,8 @@ List<Plugin> _filterPluginsByVariant(List<Plugin> plugins, String platformKey, P
|
||||
Future<void> writeWindowsPluginFiles(FlutterProject project, List<Plugin> plugins, TemplateRenderer templateRenderer) async {
|
||||
final List<Plugin> nativePlugins = _filterNativePlugins(plugins, WindowsPlugin.kConfigKey);
|
||||
final List<Plugin> win32Plugins = _filterPluginsByVariant(nativePlugins, WindowsPlugin.kConfigKey, PluginPlatformVariant.win32);
|
||||
final List<Map<String, dynamic>> pluginInfo = _extractPlatformMaps(win32Plugins, WindowsPlugin.kConfigKey);
|
||||
final Map<String, dynamic> context = <String, dynamic>{
|
||||
final List<Map<String, Object?>> pluginInfo = _extractPlatformMaps(win32Plugins, WindowsPlugin.kConfigKey);
|
||||
final Map<String, Object> context = <String, Object>{
|
||||
'os': 'windows',
|
||||
'plugins': pluginInfo,
|
||||
'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.windows),
|
||||
@ -860,8 +862,8 @@ Future<void> writeWindowsPluginFiles(FlutterProject project, List<Plugin> plugin
|
||||
Future<void> writeWindowsUwpPluginFiles(FlutterProject project, List<Plugin> plugins, TemplateRenderer templateRenderer) async {
|
||||
final List<Plugin> nativePlugins = _filterNativePlugins(plugins, WindowsPlugin.kConfigKey);
|
||||
final List<Plugin> uwpPlugins = _filterPluginsByVariant(nativePlugins, WindowsPlugin.kConfigKey, PluginPlatformVariant.winuwp);
|
||||
final List<Map<String, dynamic>> pluginInfo = _extractPlatformMaps(uwpPlugins, WindowsPlugin.kConfigKey);
|
||||
final Map<String, dynamic> context = <String, dynamic>{
|
||||
final List<Map<String, Object?>> pluginInfo = _extractPlatformMaps(uwpPlugins, WindowsPlugin.kConfigKey);
|
||||
final Map<String, Object> context = <String, Object>{
|
||||
'os': 'windows',
|
||||
'plugins': pluginInfo,
|
||||
'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.windowsUwp),
|
||||
@ -870,7 +872,7 @@ Future<void> writeWindowsUwpPluginFiles(FlutterProject project, List<Plugin> plu
|
||||
await _writePluginCmakefile(project.windowsUwp.generatedPluginCmakeFile, context, templateRenderer);
|
||||
}
|
||||
|
||||
Future<void> _writeCppPluginRegistrant(Directory destination, Map<String, dynamic> templateContext, TemplateRenderer templateRenderer) async {
|
||||
Future<void> _writeCppPluginRegistrant(Directory destination, Map<String, Object> templateContext, TemplateRenderer templateRenderer) async {
|
||||
_renderTemplateToFile(
|
||||
_cppPluginRegistryHeaderTemplate,
|
||||
templateContext,
|
||||
@ -886,13 +888,13 @@ Future<void> _writeCppPluginRegistrant(Directory destination, Map<String, dynami
|
||||
}
|
||||
|
||||
Future<void> _writeWebPluginRegistrant(FlutterProject project, List<Plugin> plugins) async {
|
||||
final List<Map<String, dynamic>> webPlugins = _extractPlatformMaps(plugins, WebPlugin.kConfigKey);
|
||||
final Map<String, dynamic> context = <String, dynamic>{
|
||||
final List<Map<String, Object?>> webPlugins = _extractPlatformMaps(plugins, WebPlugin.kConfigKey);
|
||||
final Map<String, Object> context = <String, Object>{
|
||||
'plugins': webPlugins,
|
||||
};
|
||||
final File pluginFile = project.web.libDirectory.childFile('generated_plugin_registrant.dart');
|
||||
if (webPlugins.isEmpty) {
|
||||
return ErrorHandlingFileSystem.deleteIfExists(pluginFile);
|
||||
ErrorHandlingFileSystem.deleteIfExists(pluginFile);
|
||||
} else {
|
||||
_renderTemplateToFile(
|
||||
_dartPluginRegistryTemplate,
|
||||
@ -911,34 +913,34 @@ Future<void> _writeWebPluginRegistrant(FlutterProject project, List<Plugin> plug
|
||||
///
|
||||
/// This uses [project.flutterPluginsDependenciesFile], so it should only be
|
||||
/// run after refreshPluginList has been run since the last plugin change.
|
||||
void createPluginSymlinks(FlutterProject project, {bool force = false, @visibleForTesting FeatureFlags featureFlagsOverride}) {
|
||||
void createPluginSymlinks(FlutterProject project, {bool force = false, @visibleForTesting FeatureFlags? featureFlagsOverride}) {
|
||||
final FeatureFlags localFeatureFlags = featureFlagsOverride ?? featureFlags;
|
||||
Map<String, dynamic> platformPlugins;
|
||||
final String pluginFileContent = _readFileContent(project.flutterPluginsDependenciesFile);
|
||||
Map<String, Object?>? platformPlugins;
|
||||
final String? pluginFileContent = _readFileContent(project.flutterPluginsDependenciesFile);
|
||||
if (pluginFileContent != null) {
|
||||
final Map<String, dynamic> pluginInfo = json.decode(pluginFileContent) as Map<String, dynamic>;
|
||||
platformPlugins = pluginInfo[_kFlutterPluginsPluginListKey] as Map<String, dynamic>;
|
||||
final Map<String, Object?>? pluginInfo = json.decode(pluginFileContent) as Map<String, Object?>?;
|
||||
platformPlugins = pluginInfo?[_kFlutterPluginsPluginListKey] as Map<String, Object?>?;
|
||||
}
|
||||
platformPlugins ??= <String, dynamic>{};
|
||||
platformPlugins ??= <String, Object?>{};
|
||||
|
||||
if (localFeatureFlags.isWindowsEnabled && project.windows.existsSync()) {
|
||||
_createPlatformPluginSymlinks(
|
||||
project.windows.pluginSymlinkDirectory,
|
||||
platformPlugins[project.windows.pluginConfigKey] as List<dynamic>,
|
||||
platformPlugins[project.windows.pluginConfigKey] as List<Object?>?,
|
||||
force: force,
|
||||
);
|
||||
}
|
||||
if (localFeatureFlags.isLinuxEnabled && project.linux.existsSync()) {
|
||||
_createPlatformPluginSymlinks(
|
||||
project.linux.pluginSymlinkDirectory,
|
||||
platformPlugins[project.linux.pluginConfigKey] as List<dynamic>,
|
||||
platformPlugins[project.linux.pluginConfigKey] as List<Object?>?,
|
||||
force: force,
|
||||
);
|
||||
}
|
||||
if (localFeatureFlags.isWindowsUwpEnabled && project.windowsUwp.existsSync()) {
|
||||
_createPlatformPluginSymlinks(
|
||||
project.windowsUwp.pluginSymlinkDirectory,
|
||||
platformPlugins[project.windows.pluginConfigKey] as List<dynamic>,
|
||||
platformPlugins[project.windows.pluginConfigKey] as List<Object?>?,
|
||||
force: force,
|
||||
);
|
||||
}
|
||||
@ -948,12 +950,12 @@ void createPluginSymlinks(FlutterProject project, {bool force = false, @visibleF
|
||||
/// failure cases.
|
||||
@visibleForTesting
|
||||
void handleSymlinkException(FileSystemException e, {
|
||||
@required Platform platform,
|
||||
@required OperatingSystemUtils os,
|
||||
required Platform platform,
|
||||
required OperatingSystemUtils os,
|
||||
}) {
|
||||
if (platform.isWindows && (e.osError?.errorCode ?? 0) == 1314) {
|
||||
final String versionString = RegExp(r'[\d.]+').firstMatch(os.name)?.group(0);
|
||||
final Version version = Version.parse(versionString);
|
||||
final String? versionString = RegExp(r'[\d.]+').firstMatch(os.name)?.group(0);
|
||||
final Version? version = Version.parse(versionString);
|
||||
// Windows 10 14972 is the oldest version that allows creating symlinks
|
||||
// just by enabling developer mode; before that it requires running the
|
||||
// terminal as Administrator.
|
||||
@ -970,7 +972,7 @@ void handleSymlinkException(FileSystemException e, {
|
||||
/// Creates [symlinkDirectory] containing symlinks to each plugin listed in [platformPlugins].
|
||||
///
|
||||
/// If [force] is true, the directory will be created only if missing.
|
||||
void _createPlatformPluginSymlinks(Directory symlinkDirectory, List<dynamic> platformPlugins, {bool force = false}) {
|
||||
void _createPlatformPluginSymlinks(Directory symlinkDirectory, List<Object?>? platformPlugins, {bool force = false}) {
|
||||
if (force && symlinkDirectory.existsSync()) {
|
||||
// Start fresh to avoid stale links.
|
||||
symlinkDirectory.deleteSync(recursive: true);
|
||||
@ -979,9 +981,9 @@ void _createPlatformPluginSymlinks(Directory symlinkDirectory, List<dynamic> pla
|
||||
if (platformPlugins == null) {
|
||||
return;
|
||||
}
|
||||
for (final Map<String, dynamic> pluginInfo in platformPlugins.cast<Map<String, dynamic>>()) {
|
||||
final String name = pluginInfo[_kFlutterPluginsNameKey] as String;
|
||||
final String path = pluginInfo[_kFlutterPluginsPathKey] as String;
|
||||
for (final Map<String, Object?> pluginInfo in platformPlugins.cast<Map<String, Object?>>()) {
|
||||
final String name = pluginInfo[_kFlutterPluginsNameKey]! as String;
|
||||
final String path = pluginInfo[_kFlutterPluginsPathKey]! as String;
|
||||
final Link link = symlinkDirectory.childLink(name);
|
||||
if (link.existsSync()) {
|
||||
continue;
|
||||
@ -1015,10 +1017,10 @@ Future<void> refreshPluginsList(
|
||||
if (changed || legacyChanged) {
|
||||
createPluginSymlinks(project, force: true);
|
||||
if (iosPlatform) {
|
||||
globals.cocoaPods.invalidatePodInstallOutput(project.ios);
|
||||
globals.cocoaPods?.invalidatePodInstallOutput(project.ios);
|
||||
}
|
||||
if (macOSPlatform) {
|
||||
globals.cocoaPods.invalidatePodInstallOutput(project.macos);
|
||||
globals.cocoaPods?.invalidatePodInstallOutput(project.macos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1064,12 +1066,12 @@ Future<void> injectPlugins(
|
||||
];
|
||||
for (final XcodeBasedProject subproject in darwinProjects) {
|
||||
if (plugins.isNotEmpty) {
|
||||
await globals.cocoaPods.setupPodfile(subproject);
|
||||
await globals.cocoaPods?.setupPodfile(subproject);
|
||||
}
|
||||
/// The user may have a custom maintained Podfile that they're running `pod install`
|
||||
/// on themselves.
|
||||
else if (subproject.podfile.existsSync() && subproject.podfileLock.existsSync()) {
|
||||
globals.cocoaPods.addPodsDependencyToFlutterXcconfig(subproject);
|
||||
globals.cocoaPods?.addPodsDependencyToFlutterXcconfig(subproject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1119,9 +1121,9 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
|
||||
continue;
|
||||
}
|
||||
// The plugin doesn't implement an interface, verify that it has a default implementation.
|
||||
final String implementsPackage = plugin.implementsPackage;
|
||||
final String? implementsPackage = plugin.implementsPackage;
|
||||
if (implementsPackage == null || implementsPackage.isEmpty) {
|
||||
final String defaultImplementation = plugin.defaultPackagePlatforms[platform];
|
||||
final String? defaultImplementation = plugin.defaultPackagePlatforms[platform];
|
||||
if (defaultImplementation == null) {
|
||||
if (throwOnPluginPubspecError) {
|
||||
globals.printError(
|
||||
@ -1153,7 +1155,7 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
|
||||
}
|
||||
final String resolutionKey = '$platform/$implementsPackage';
|
||||
if (directDependencyResolutions.containsKey(resolutionKey)) {
|
||||
final PluginInterfaceResolution currResolution = directDependencyResolutions[resolutionKey];
|
||||
final PluginInterfaceResolution? currResolution = directDependencyResolutions[resolutionKey];
|
||||
if (currResolution != null && currResolution.plugin.isDirectDependency) {
|
||||
if (plugin.isDirectDependency) {
|
||||
if (throwOnPluginPubspecError) {
|
||||
@ -1223,14 +1225,14 @@ Future<void> generateMainDartWithPluginRegistrant(
|
||||
final LanguageVersion entrypointVersion = determineLanguageVersion(
|
||||
mainFile,
|
||||
packageConfig.packageOf(mainFile.absolute.uri),
|
||||
Cache.flutterRoot,
|
||||
Cache.flutterRoot!,
|
||||
);
|
||||
final Map<String, dynamic> templateContext = <String, dynamic>{
|
||||
final Map<String, Object> templateContext = <String, Object>{
|
||||
'mainEntrypoint': currentMainUri,
|
||||
'dartLanguageVersion': entrypointVersion.toString(),
|
||||
LinuxPlugin.kConfigKey: <dynamic>[],
|
||||
MacOSPlugin.kConfigKey: <dynamic>[],
|
||||
WindowsPlugin.kConfigKey: <dynamic>[],
|
||||
LinuxPlugin.kConfigKey: <Object?>[],
|
||||
MacOSPlugin.kConfigKey: <Object?>[],
|
||||
WindowsPlugin.kConfigKey: <Object?>[],
|
||||
};
|
||||
if (resolutions.isEmpty) {
|
||||
try {
|
||||
@ -1248,7 +1250,7 @@ Future<void> generateMainDartWithPluginRegistrant(
|
||||
}
|
||||
for (final PluginInterfaceResolution resolution in resolutions) {
|
||||
assert(templateContext.containsKey(resolution.platform));
|
||||
(templateContext[resolution.platform] as List<dynamic>).add(resolution.toMap());
|
||||
(templateContext[resolution.platform] as List<Object?>?)?.add(resolution.toMap());
|
||||
}
|
||||
try {
|
||||
_renderTemplateToFile(
|
||||
|
@ -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()) {
|
||||
|
@ -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 'package:xml/xml.dart';
|
||||
import 'package:yaml/yaml.dart';
|
||||
@ -20,7 +18,7 @@ import 'cmake.dart';
|
||||
import 'features.dart';
|
||||
import 'flutter_manifest.dart';
|
||||
import 'flutter_plugins.dart';
|
||||
import 'globals.dart' as globals;
|
||||
import 'globals_null_migrated.dart' as globals;
|
||||
import 'ios/plist_parser.dart';
|
||||
import 'ios/xcode_build_settings.dart' as xcode;
|
||||
import 'ios/xcodeproj.dart';
|
||||
@ -29,8 +27,8 @@ import 'template.dart';
|
||||
|
||||
class FlutterProjectFactory {
|
||||
FlutterProjectFactory({
|
||||
@required Logger logger,
|
||||
@required FileSystem fileSystem,
|
||||
required Logger logger,
|
||||
required FileSystem fileSystem,
|
||||
}) : _logger = logger,
|
||||
_fileSystem = fileSystem;
|
||||
|
||||
@ -89,7 +87,7 @@ class FlutterProject {
|
||||
|
||||
/// Create a [FlutterProject] and bypass the project caching.
|
||||
@visibleForTesting
|
||||
static FlutterProject fromDirectoryTest(Directory directory, [Logger logger]) {
|
||||
static FlutterProject fromDirectoryTest(Directory directory, [Logger? logger]) {
|
||||
final FileSystem fileSystem = directory.fileSystem;
|
||||
logger ??= BufferLogger.test();
|
||||
final FlutterManifest manifest = FlutterProject._readManifest(
|
||||
@ -126,14 +124,14 @@ class FlutterProject {
|
||||
// Don't require iOS build info, this method is only
|
||||
// used during create as best-effort, use the
|
||||
// default target bundle identifier.
|
||||
final String bundleIdentifier = await ios.productBundleIdentifier(null);
|
||||
final String? bundleIdentifier = await ios.productBundleIdentifier(null);
|
||||
if (bundleIdentifier != null) {
|
||||
candidates.add(bundleIdentifier);
|
||||
}
|
||||
}
|
||||
if (android.existsSync()) {
|
||||
final String applicationId = android.applicationId;
|
||||
final String group = android.group;
|
||||
final String? applicationId = android.applicationId;
|
||||
final String? group = android.group;
|
||||
candidates.addAll(<String>[
|
||||
if (applicationId != null)
|
||||
applicationId,
|
||||
@ -142,21 +140,21 @@ class FlutterProject {
|
||||
]);
|
||||
}
|
||||
if (example.android.existsSync()) {
|
||||
final String applicationId = example.android.applicationId;
|
||||
final String? applicationId = example.android.applicationId;
|
||||
if (applicationId != null) {
|
||||
candidates.add(applicationId);
|
||||
}
|
||||
}
|
||||
if (example.ios.existsSync()) {
|
||||
final String bundleIdentifier = await example.ios.productBundleIdentifier(null);
|
||||
final String? bundleIdentifier = await example.ios.productBundleIdentifier(null);
|
||||
if (bundleIdentifier != null) {
|
||||
candidates.add(bundleIdentifier);
|
||||
}
|
||||
}
|
||||
return Set<String>.of(candidates.map<String>(_organizationNameFromPackageName).whereType<String>());
|
||||
return Set<String>.of(candidates.map<String?>(_organizationNameFromPackageName).whereType<String>());
|
||||
}
|
||||
|
||||
String _organizationNameFromPackageName(String packageName) {
|
||||
String? _organizationNameFromPackageName(String packageName) {
|
||||
if (packageName != null && 0 <= packageName.lastIndexOf('.')) {
|
||||
return packageName.substring(0, packageName.lastIndexOf('.'));
|
||||
}
|
||||
@ -164,35 +162,35 @@ class FlutterProject {
|
||||
}
|
||||
|
||||
/// The iOS sub project of this project.
|
||||
IosProject _ios;
|
||||
IosProject? _ios;
|
||||
IosProject get ios => _ios ??= IosProject.fromFlutter(this);
|
||||
|
||||
/// The Android sub project of this project.
|
||||
AndroidProject _android;
|
||||
AndroidProject? _android;
|
||||
AndroidProject get android => _android ??= AndroidProject._(this);
|
||||
|
||||
/// The web sub project of this project.
|
||||
WebProject _web;
|
||||
WebProject? _web;
|
||||
WebProject get web => _web ??= WebProject._(this);
|
||||
|
||||
/// The MacOS sub project of this project.
|
||||
MacOSProject _macos;
|
||||
MacOSProject? _macos;
|
||||
MacOSProject get macos => _macos ??= MacOSProject._(this);
|
||||
|
||||
/// The Linux sub project of this project.
|
||||
LinuxProject _linux;
|
||||
LinuxProject? _linux;
|
||||
LinuxProject get linux => _linux ??= LinuxProject._(this);
|
||||
|
||||
/// The Windows sub project of this project.
|
||||
WindowsProject _windows;
|
||||
WindowsProject? _windows;
|
||||
WindowsProject get windows => _windows ??= WindowsProject._(this);
|
||||
|
||||
/// The Windows UWP sub project of this project.
|
||||
WindowsUwpProject _windowUwp;
|
||||
WindowsUwpProject? _windowUwp;
|
||||
WindowsUwpProject get windowsUwp => _windowUwp ??= WindowsUwpProject._(this);
|
||||
|
||||
/// The Fuchsia sub project of this project.
|
||||
FuchsiaProject _fuchsia;
|
||||
FuchsiaProject? _fuchsia;
|
||||
FuchsiaProject get fuchsia => _fuchsia ??= FuchsiaProject._(this);
|
||||
|
||||
/// The `pubspec.yaml` file of this project.
|
||||
@ -256,10 +254,10 @@ class FlutterProject {
|
||||
/// Completes with an empty [FlutterManifest], if the file does not exist.
|
||||
/// Completes with a ToolExit on validation error.
|
||||
static FlutterManifest _readManifest(String path, {
|
||||
@required Logger logger,
|
||||
@required FileSystem fileSystem,
|
||||
required Logger logger,
|
||||
required FileSystem fileSystem,
|
||||
}) {
|
||||
FlutterManifest manifest;
|
||||
FlutterManifest? manifest;
|
||||
try {
|
||||
manifest = FlutterManifest.createFromPath(
|
||||
path,
|
||||
@ -350,8 +348,8 @@ class FlutterProject {
|
||||
|
||||
/// Returns a json encoded string containing the [appName], [version], and [buildNumber] that is used to generate version.json
|
||||
String getVersionInfo() {
|
||||
final String buildName = manifest.buildName;
|
||||
final String buildNumber = manifest.buildNumber;
|
||||
final String? buildName = manifest.buildName;
|
||||
final String? buildNumber = manifest.buildNumber;
|
||||
final Map<String, String> versionFileJson = <String, String>{
|
||||
'app_name': manifest.appName,
|
||||
if (buildName != null)
|
||||
@ -534,16 +532,16 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
|
||||
|
||||
/// The product bundle identifier of the host app, or null if not set or if
|
||||
/// iOS tooling needed to read it is not installed.
|
||||
Future<String> productBundleIdentifier(BuildInfo buildInfo) async {
|
||||
Future<String?> productBundleIdentifier(BuildInfo? buildInfo) async {
|
||||
if (!existsSync()) {
|
||||
return null;
|
||||
}
|
||||
return _productBundleIdentifier ??= await _parseProductBundleIdentifier(buildInfo);
|
||||
}
|
||||
String _productBundleIdentifier;
|
||||
String? _productBundleIdentifier;
|
||||
|
||||
Future<String> _parseProductBundleIdentifier(BuildInfo buildInfo) async {
|
||||
String fromPlist;
|
||||
Future<String?> _parseProductBundleIdentifier(BuildInfo? buildInfo) async {
|
||||
String? fromPlist;
|
||||
final File defaultInfoPlist = defaultHostInfoPlist;
|
||||
// Users can change the location of the Info.plist.
|
||||
// Try parsing the default, first.
|
||||
@ -561,7 +559,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
|
||||
return fromPlist;
|
||||
}
|
||||
}
|
||||
final Map<String, String> allBuildSettings = await buildSettingsForBuildInfo(buildInfo);
|
||||
final Map<String, String>? allBuildSettings = await buildSettingsForBuildInfo(buildInfo);
|
||||
if (allBuildSettings != null) {
|
||||
if (fromPlist != null) {
|
||||
// Perform variable substitution using build settings.
|
||||
@ -576,7 +574,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
|
||||
// or companion watchOS projects. However, on non-macOS platforms this is
|
||||
// only used for display purposes and to regenerate organization names, so
|
||||
// best-effort is probably fine.
|
||||
final String fromPbxproj = _firstMatchInFile(xcodeProjectInfoFile, _productBundleIdPattern)?.group(2);
|
||||
final String? fromPbxproj = _firstMatchInFile(xcodeProjectInfoFile, _productBundleIdPattern)?.group(2);
|
||||
if (fromPbxproj != null && (fromPlist == null || fromPlist == _productBundleIdVariable)) {
|
||||
return fromPbxproj;
|
||||
}
|
||||
@ -585,22 +583,22 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
|
||||
}
|
||||
|
||||
/// The bundle name of the host app, `My App.app`.
|
||||
Future<String> hostAppBundleName(BuildInfo buildInfo) async {
|
||||
Future<String?> hostAppBundleName(BuildInfo buildInfo) async {
|
||||
if (!existsSync()) {
|
||||
return null;
|
||||
}
|
||||
return _hostAppBundleName ??= await _parseHostAppBundleName(buildInfo);
|
||||
}
|
||||
String _hostAppBundleName;
|
||||
String? _hostAppBundleName;
|
||||
|
||||
Future<String> _parseHostAppBundleName(BuildInfo buildInfo) async {
|
||||
// The product name and bundle name are derived from the display name, which the user
|
||||
// is instructed to change in Xcode as part of deploying to the App Store.
|
||||
// https://flutter.dev/docs/deployment/ios#review-xcode-project-settings
|
||||
// The only source of truth for the name is Xcode's interpretation of the build settings.
|
||||
String productName;
|
||||
if (globals.xcodeProjectInterpreter.isInstalled) {
|
||||
final Map<String, String> xcodeBuildSettings = await buildSettingsForBuildInfo(buildInfo);
|
||||
String? productName;
|
||||
if (globals.xcodeProjectInterpreter?.isInstalled == true) {
|
||||
final Map<String, String>? xcodeBuildSettings = await buildSettingsForBuildInfo(buildInfo);
|
||||
if (xcodeBuildSettings != null) {
|
||||
productName = xcodeBuildSettings['FULL_PRODUCT_NAME'];
|
||||
}
|
||||
@ -614,27 +612,28 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
|
||||
/// The build settings for the host app of this project, as a detached map.
|
||||
///
|
||||
/// Returns null, if iOS tooling is unavailable.
|
||||
Future<Map<String, String>> buildSettingsForBuildInfo(BuildInfo buildInfo, { EnvironmentType environmentType = EnvironmentType.physical }) async {
|
||||
Future<Map<String, String>?> buildSettingsForBuildInfo(BuildInfo? buildInfo, { EnvironmentType environmentType = EnvironmentType.physical }) async {
|
||||
if (!existsSync()) {
|
||||
return null;
|
||||
}
|
||||
final XcodeProjectInfo info = await projectInfo();
|
||||
final XcodeProjectInfo? info = await projectInfo();
|
||||
if (info == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String scheme = info.schemeFor(buildInfo);
|
||||
final String? scheme = info.schemeFor(buildInfo);
|
||||
if (scheme == null) {
|
||||
info.reportFlavorNotFoundAndExit();
|
||||
}
|
||||
|
||||
final String configuration = (await projectInfo()).buildConfigurationFor(
|
||||
final String? configuration = (await projectInfo())?.buildConfigurationFor(
|
||||
buildInfo,
|
||||
scheme,
|
||||
);
|
||||
final XcodeProjectBuildContext buildContext = XcodeProjectBuildContext(environmentType: environmentType, scheme: scheme, configuration: configuration);
|
||||
if (_buildSettingsByBuildContext[buildContext] == null) {
|
||||
final Map<String, String> calculatedBuildSettings = await _xcodeProjectBuildSettings(buildContext);
|
||||
final Map<String, String>? currentBuildSettings = _buildSettingsByBuildContext[buildContext];
|
||||
if (currentBuildSettings == null) {
|
||||
final Map<String, String>? calculatedBuildSettings = await _xcodeProjectBuildSettings(buildContext);
|
||||
if (calculatedBuildSettings != null) {
|
||||
_buildSettingsByBuildContext[buildContext] = calculatedBuildSettings;
|
||||
}
|
||||
@ -644,17 +643,17 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
|
||||
|
||||
final Map<XcodeProjectBuildContext, Map<String, String>> _buildSettingsByBuildContext = <XcodeProjectBuildContext, Map<String, String>>{};
|
||||
|
||||
Future<XcodeProjectInfo> projectInfo() async {
|
||||
final XcodeProjectInterpreter xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
|
||||
Future<XcodeProjectInfo?> projectInfo() async {
|
||||
final XcodeProjectInterpreter? xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
|
||||
if (!xcodeProject.existsSync() || xcodeProjectInterpreter == null || !xcodeProjectInterpreter.isInstalled) {
|
||||
return null;
|
||||
}
|
||||
return _projectInfo ??= await xcodeProjectInterpreter.getInfo(hostAppRoot.path);
|
||||
}
|
||||
XcodeProjectInfo _projectInfo;
|
||||
XcodeProjectInfo? _projectInfo;
|
||||
|
||||
Future<Map<String, String>> _xcodeProjectBuildSettings(XcodeProjectBuildContext buildContext) async {
|
||||
final XcodeProjectInterpreter xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
|
||||
Future<Map<String, String>?> _xcodeProjectBuildSettings(XcodeProjectBuildContext buildContext) async {
|
||||
final XcodeProjectInterpreter? xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
|
||||
if (xcodeProjectInterpreter == null || !xcodeProjectInterpreter.isInstalled) {
|
||||
return null;
|
||||
}
|
||||
@ -680,7 +679,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
|
||||
|
||||
/// Check if one the [targets] of the project is a watchOS companion app target.
|
||||
Future<bool> containsWatchCompanion(List<String> targets, BuildInfo buildInfo) async {
|
||||
final String bundleIdentifier = await productBundleIdentifier(buildInfo);
|
||||
final String? bundleIdentifier = await productBundleIdentifier(buildInfo);
|
||||
// A bundle identifier is required for a companion app.
|
||||
if (bundleIdentifier == null) {
|
||||
return false;
|
||||
@ -748,7 +747,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
|
||||
// However, cocoapods will run before that script and requires something
|
||||
// to be in this location.
|
||||
final Directory framework = globals.fs.directory(
|
||||
globals.artifacts.getArtifactPath(
|
||||
globals.artifacts?.getArtifactPath(
|
||||
Artifact.flutterXcframework,
|
||||
platform: TargetPlatform.ios,
|
||||
mode: mode,
|
||||
@ -876,7 +875,7 @@ class AndroidProject extends FlutterProjectPlatform {
|
||||
|
||||
/// Returns true if the current version of the Gradle plugin is supported.
|
||||
bool get isSupportedVersion => _isSupportedVersion ??= _computeSupportedVersion();
|
||||
bool _isSupportedVersion;
|
||||
bool? _isSupportedVersion;
|
||||
|
||||
bool _computeSupportedVersion() {
|
||||
final FileSystem fileSystem = hostAppGradleRoot.fileSystem;
|
||||
@ -927,12 +926,12 @@ class AndroidProject extends FlutterProjectPlatform {
|
||||
return hostAppGradleRoot.childFile('build.gradle').existsSync();
|
||||
}
|
||||
|
||||
String get applicationId {
|
||||
String? get applicationId {
|
||||
final File gradleFile = hostAppGradleRoot.childDirectory('app').childFile('build.gradle');
|
||||
return _firstMatchInFile(gradleFile, _applicationIdPattern)?.group(1);
|
||||
}
|
||||
|
||||
String get group {
|
||||
String? get group {
|
||||
final File gradleFile = hostAppGradleRoot.childFile('build.gradle');
|
||||
return _firstMatchInFile(gradleFile, _groupPattern)?.group(1);
|
||||
}
|
||||
@ -993,7 +992,7 @@ to migrate your project.
|
||||
'library_new_embedding',
|
||||
), ephemeralDirectory);
|
||||
await _overwriteFromTemplate(globals.fs.path.join('module', 'android', 'gradle'), ephemeralDirectory);
|
||||
globals.gradleUtils.injectGradleWrapperIfNeeded(ephemeralDirectory);
|
||||
globals.gradleUtils?.injectGradleWrapperIfNeeded(ephemeralDirectory);
|
||||
}
|
||||
|
||||
Future<void> _overwriteFromTemplate(String path, Directory target) async {
|
||||
@ -1038,9 +1037,9 @@ to migrate your project.
|
||||
'Please ensure that you have read permission to this file and try again.');
|
||||
}
|
||||
for (final XmlElement metaData in document.findAllElements('meta-data')) {
|
||||
final String name = metaData.getAttribute('android:name');
|
||||
final String? name = metaData.getAttribute('android:name');
|
||||
if (name == 'flutterEmbedding') {
|
||||
final String embeddingVersionString = metaData.getAttribute('android:value');
|
||||
final String? embeddingVersionString = metaData.getAttribute('android:value');
|
||||
if (embeddingVersionString == '1') {
|
||||
return AndroidEmbeddingVersion.v1;
|
||||
}
|
||||
@ -1102,12 +1101,12 @@ void _deleteIfExistsSync(Directory directory) {
|
||||
/// Returns the first line-based match for [regExp] in [file].
|
||||
///
|
||||
/// Assumes UTF8 encoding.
|
||||
Match _firstMatchInFile(File file, RegExp regExp) {
|
||||
Match? _firstMatchInFile(File file, RegExp regExp) {
|
||||
if (!file.existsSync()) {
|
||||
return null;
|
||||
}
|
||||
for (final String line in file.readAsLinesSync()) {
|
||||
final Match match = regExp.firstMatch(line);
|
||||
final Match? match = regExp.firstMatch(line);
|
||||
if (match != null) {
|
||||
return match;
|
||||
}
|
||||
@ -1254,20 +1253,20 @@ class WindowsUwpProject extends WindowsProject {
|
||||
File get runnerCmakeFile => _editableDirectory.childDirectory('runner_uwp').childFile('CMakeLists.txt');
|
||||
|
||||
/// Eventually this will be used to check if the user's unstable project needs to be regenerated.
|
||||
int get projectVersion => int.tryParse(_editableDirectory.childFile('project_version').readAsStringSync());
|
||||
int? get projectVersion => int.tryParse(_editableDirectory.childFile('project_version').readAsStringSync());
|
||||
|
||||
/// Retrieve the GUID of the UWP package.
|
||||
String get packageGuid => _packageGuid ??= getCmakePackageGuid(runnerCmakeFile);
|
||||
String _packageGuid;
|
||||
String? get packageGuid => _packageGuid ??= getCmakePackageGuid(runnerCmakeFile);
|
||||
String? _packageGuid;
|
||||
|
||||
File get appManifest => _editableDirectory.childDirectory('runner_uwp').childFile('appxmanifest.in');
|
||||
|
||||
String get packageVersion => _packageVersion ??= parseAppVersion(this);
|
||||
String _packageVersion;
|
||||
String? get packageVersion => _packageVersion ??= parseAppVersion(this);
|
||||
String? _packageVersion;
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
String parseAppVersion(WindowsUwpProject project) {
|
||||
String? parseAppVersion(WindowsUwpProject project) {
|
||||
final File appManifestFile = project.appManifest;
|
||||
if (!appManifestFile.existsSync()) {
|
||||
return null;
|
||||
@ -1329,7 +1328,7 @@ class LinuxProject extends FlutterProjectPlatform implements CmakeBasedProject {
|
||||
|
||||
Future<void> ensureReadyForPlatformSpecificTooling() async {}
|
||||
|
||||
String get applicationId {
|
||||
String? get applicationId {
|
||||
return _firstMatchInFile(cmakeFile, _applicationIdPattern)?.group(1);
|
||||
}
|
||||
}
|
||||
@ -1340,13 +1339,13 @@ class FuchsiaProject {
|
||||
|
||||
final FlutterProject project;
|
||||
|
||||
Directory _editableHostAppDirectory;
|
||||
Directory? _editableHostAppDirectory;
|
||||
Directory get editableHostAppDirectory =>
|
||||
_editableHostAppDirectory ??= project.directory.childDirectory('fuchsia');
|
||||
|
||||
bool existsSync() => editableHostAppDirectory.existsSync();
|
||||
|
||||
Directory _meta;
|
||||
Directory? _meta;
|
||||
Directory get meta =>
|
||||
_meta ??= editableHostAppDirectory.childDirectory('meta');
|
||||
}
|
||||
|
@ -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 {}
|
||||
|
Loading…
Reference in New Issue
Block a user