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_info.dart';
|
||||||
import 'package:flutter_tools/src/build_system/depfile.dart';
|
import 'package:flutter_tools/src/build_system/depfile.dart';
|
||||||
import 'package:flutter_tools/src/bundle.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/cache.dart';
|
||||||
import 'package:flutter_tools/src/context_runner.dart';
|
import 'package:flutter_tools/src/context_runner.dart';
|
||||||
import 'package:flutter_tools/src/devfs.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
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'package:meta/meta.dart';
|
|
||||||
|
|
||||||
import '../base/context.dart';
|
import '../base/context.dart';
|
||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
|
|
||||||
/// The builder in the current context.
|
/// The builder in the current context.
|
||||||
AndroidBuilder get androidBuilder {
|
AndroidBuilder? get androidBuilder {
|
||||||
return context.get<AndroidBuilder>();
|
return context.get<AndroidBuilder>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,25 +15,25 @@ abstract class AndroidBuilder {
|
|||||||
const AndroidBuilder();
|
const AndroidBuilder();
|
||||||
/// Builds an AAR artifact.
|
/// Builds an AAR artifact.
|
||||||
Future<void> buildAar({
|
Future<void> buildAar({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required Set<AndroidBuildInfo> androidBuildInfo,
|
required Set<AndroidBuildInfo> androidBuildInfo,
|
||||||
@required String target,
|
required String target,
|
||||||
@required String outputDirectoryPath,
|
String? outputDirectoryPath,
|
||||||
@required String buildNumber,
|
required String buildNumber,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Builds an APK artifact.
|
/// Builds an APK artifact.
|
||||||
Future<void> buildApk({
|
Future<void> buildApk({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required AndroidBuildInfo androidBuildInfo,
|
required AndroidBuildInfo androidBuildInfo,
|
||||||
@required String target,
|
required String target,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Builds an App Bundle artifact.
|
/// Builds an App Bundle artifact.
|
||||||
Future<void> buildAab({
|
Future<void> buildAab({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required AndroidBuildInfo androidBuildInfo,
|
required AndroidBuildInfo androidBuildInfo,
|
||||||
@required String target,
|
required String target,
|
||||||
bool validateDeferredComponents = true,
|
bool validateDeferredComponents = true,
|
||||||
bool deferredComponentsEnabled = false,
|
bool deferredComponentsEnabled = false,
|
||||||
});
|
});
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'package:crypto/crypto.dart';
|
import 'package:crypto/crypto.dart';
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:process/process.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 String newSettingsRelativeFile = fileSystem.path.relative(newSettingsFile.path);
|
||||||
final Status status = logger.startProgress('✏️ Creating `$newSettingsRelativeFile`...');
|
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',
|
final File legacySettingsDotGradleFiles = fileSystem.file(fileSystem.path.join(flutterRoot, 'packages','flutter_tools',
|
||||||
'gradle', 'settings.gradle.legacy_versions'));
|
'gradle', 'settings.gradle.legacy_versions'));
|
||||||
assert(legacySettingsDotGradleFiles.existsSync());
|
assert(legacySettingsDotGradleFiles.existsSync());
|
||||||
@ -161,13 +159,13 @@ void createSettingsAarGradle(Directory androidDirectory, Logger logger) {
|
|||||||
/// An implementation of the [AndroidBuilder] that delegates to gradle.
|
/// An implementation of the [AndroidBuilder] that delegates to gradle.
|
||||||
class AndroidGradleBuilder implements AndroidBuilder {
|
class AndroidGradleBuilder implements AndroidBuilder {
|
||||||
AndroidGradleBuilder({
|
AndroidGradleBuilder({
|
||||||
@required Logger logger,
|
required Logger logger,
|
||||||
@required ProcessManager processManager,
|
required ProcessManager processManager,
|
||||||
@required FileSystem fileSystem,
|
required FileSystem fileSystem,
|
||||||
@required Artifacts artifacts,
|
required Artifacts artifacts,
|
||||||
@required Usage usage,
|
required Usage usage,
|
||||||
@required GradleUtils gradleUtils,
|
required GradleUtils gradleUtils,
|
||||||
@required Platform platform,
|
required Platform platform,
|
||||||
}) : _logger = logger,
|
}) : _logger = logger,
|
||||||
_fileSystem = fileSystem,
|
_fileSystem = fileSystem,
|
||||||
_artifacts = artifacts,
|
_artifacts = artifacts,
|
||||||
@ -187,11 +185,11 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
/// Builds the AAR and POM files for the current Flutter module or plugin.
|
/// Builds the AAR and POM files for the current Flutter module or plugin.
|
||||||
@override
|
@override
|
||||||
Future<void> buildAar({
|
Future<void> buildAar({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required Set<AndroidBuildInfo> androidBuildInfo,
|
required Set<AndroidBuildInfo> androidBuildInfo,
|
||||||
@required String target,
|
required String target,
|
||||||
String outputDirectoryPath,
|
String? outputDirectoryPath,
|
||||||
@required String buildNumber,
|
required String buildNumber,
|
||||||
}) async {
|
}) async {
|
||||||
Directory outputDirectory =
|
Directory outputDirectory =
|
||||||
_fileSystem.directory(outputDirectoryPath ?? project.android.buildDirectory);
|
_fileSystem.directory(outputDirectoryPath ?? project.android.buildDirectory);
|
||||||
@ -224,9 +222,9 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
/// Builds the APK.
|
/// Builds the APK.
|
||||||
@override
|
@override
|
||||||
Future<void> buildApk({
|
Future<void> buildApk({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required AndroidBuildInfo androidBuildInfo,
|
required AndroidBuildInfo androidBuildInfo,
|
||||||
@required String target,
|
required String target,
|
||||||
}) async {
|
}) async {
|
||||||
await buildGradleApp(
|
await buildGradleApp(
|
||||||
project: project,
|
project: project,
|
||||||
@ -240,9 +238,9 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
/// Builds the App Bundle.
|
/// Builds the App Bundle.
|
||||||
@override
|
@override
|
||||||
Future<void> buildAab({
|
Future<void> buildAab({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required AndroidBuildInfo androidBuildInfo,
|
required AndroidBuildInfo androidBuildInfo,
|
||||||
@required String target,
|
required String target,
|
||||||
bool validateDeferredComponents = true,
|
bool validateDeferredComponents = true,
|
||||||
bool deferredComponentsEnabled = false,
|
bool deferredComponentsEnabled = false,
|
||||||
}) async {
|
}) async {
|
||||||
@ -269,11 +267,11 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
/// * [retries] is the max number of build retries in case one of the [GradleHandledError] handler
|
/// * [retries] is the max number of build retries in case one of the [GradleHandledError] handler
|
||||||
/// returns [GradleBuildStatus.retry] or [GradleBuildStatus.retryWithAarPlugins].
|
/// returns [GradleBuildStatus.retry] or [GradleBuildStatus.retryWithAarPlugins].
|
||||||
Future<void> buildGradleApp({
|
Future<void> buildGradleApp({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required AndroidBuildInfo androidBuildInfo,
|
required AndroidBuildInfo androidBuildInfo,
|
||||||
@required String target,
|
required String target,
|
||||||
@required bool isBuildingBundle,
|
required bool isBuildingBundle,
|
||||||
@required List<GradleHandledError> localGradleErrors,
|
required List<GradleHandledError> localGradleErrors,
|
||||||
bool shouldBuildPluginAsAar = false,
|
bool shouldBuildPluginAsAar = false,
|
||||||
bool validateDeferredComponents = true,
|
bool validateDeferredComponents = true,
|
||||||
bool deferredComponentsEnabled = false,
|
bool deferredComponentsEnabled = false,
|
||||||
@ -361,7 +359,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
if (target != null) {
|
if (target != null) {
|
||||||
command.add('-Ptarget=$target');
|
command.add('-Ptarget=$target');
|
||||||
}
|
}
|
||||||
final List<DeferredComponent> deferredComponents = project.manifest.deferredComponents;
|
final List<DeferredComponent>? deferredComponents = project.manifest.deferredComponents;
|
||||||
if (deferredComponents != null) {
|
if (deferredComponents != null) {
|
||||||
if (deferredComponentsEnabled) {
|
if (deferredComponentsEnabled) {
|
||||||
command.add('-Pdeferred-components=true');
|
command.add('-Pdeferred-components=true');
|
||||||
@ -406,9 +404,9 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
}
|
}
|
||||||
command.add(assembleTask);
|
command.add(assembleTask);
|
||||||
|
|
||||||
GradleHandledError detectedGradleError;
|
GradleHandledError? detectedGradleError;
|
||||||
String detectedGradleErrorLine;
|
String? detectedGradleErrorLine;
|
||||||
String consumeLog(String line) {
|
String? consumeLog(String line) {
|
||||||
// This message was removed from first-party plugins,
|
// This message was removed from first-party plugins,
|
||||||
// but older plugin versions still display this message.
|
// but older plugin versions still display this message.
|
||||||
if (androidXPluginWarningRegex.hasMatch(line)) {
|
if (androidXPluginWarningRegex.hasMatch(line)) {
|
||||||
@ -441,7 +439,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
allowReentrantFlutter: true,
|
allowReentrantFlutter: true,
|
||||||
environment: <String, String>{
|
environment: <String, String>{
|
||||||
if (javaPath != null)
|
if (javaPath != null)
|
||||||
'JAVA_HOME': javaPath,
|
'JAVA_HOME': javaPath!,
|
||||||
},
|
},
|
||||||
mapFunction: consumeLog,
|
mapFunction: consumeLog,
|
||||||
);
|
);
|
||||||
@ -466,15 +464,15 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
exitCode: exitCode,
|
exitCode: exitCode,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
final GradleBuildStatus status = await detectedGradleError.handler(
|
final GradleBuildStatus status = await detectedGradleError!.handler(
|
||||||
line: detectedGradleErrorLine,
|
line: detectedGradleErrorLine!,
|
||||||
project: project,
|
project: project,
|
||||||
usesAndroidX: usesAndroidX,
|
usesAndroidX: usesAndroidX,
|
||||||
shouldBuildPluginAsAar: shouldBuildPluginAsAar,
|
shouldBuildPluginAsAar: shouldBuildPluginAsAar,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (retries >= 1) {
|
if (retries >= 1) {
|
||||||
final String successEventLabel = 'gradle-${detectedGradleError.eventLabel}-success';
|
final String successEventLabel = 'gradle-${detectedGradleError!.eventLabel}-success';
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case GradleBuildStatus.retry:
|
case GradleBuildStatus.retry:
|
||||||
await buildGradleApp(
|
await buildGradleApp(
|
||||||
@ -504,7 +502,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
// noop.
|
// noop.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BuildEvent('gradle-${detectedGradleError.eventLabel}-failure', type: 'gradle', flutterUsage: _usage).send();
|
BuildEvent('gradle-${detectedGradleError?.eventLabel}-failure', type: 'gradle', flutterUsage: _usage).send();
|
||||||
throwToolExit(
|
throwToolExit(
|
||||||
'Gradle task $assembleTask failed with exit code $exitCode',
|
'Gradle task $assembleTask failed with exit code $exitCode',
|
||||||
exitCode: exitCode,
|
exitCode: exitCode,
|
||||||
@ -580,7 +578,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
.childFile('snapshot.$archName.json');
|
.childFile('snapshot.$archName.json');
|
||||||
final File precompilerTrace = _fileSystem.directory(buildInfo.codeSizeDirectory)
|
final File precompilerTrace = _fileSystem.directory(buildInfo.codeSizeDirectory)
|
||||||
.childFile('trace.$archName.json');
|
.childFile('trace.$archName.json');
|
||||||
final Map<String, Object> output = await sizeAnalyzer.analyzeZipSizeAndAotSnapshot(
|
final Map<String, Object?> output = await sizeAnalyzer.analyzeZipSizeAndAotSnapshot(
|
||||||
zipFile: zipFile,
|
zipFile: zipFile,
|
||||||
aotSnapshot: aotSnapshot,
|
aotSnapshot: aotSnapshot,
|
||||||
precompilerTrace: precompilerTrace,
|
precompilerTrace: precompilerTrace,
|
||||||
@ -616,11 +614,11 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
/// * [outputDir] is the destination of the artifacts,
|
/// * [outputDir] is the destination of the artifacts,
|
||||||
/// * [buildNumber] is the build number of the output aar,
|
/// * [buildNumber] is the build number of the output aar,
|
||||||
Future<void> buildGradleAar({
|
Future<void> buildGradleAar({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required AndroidBuildInfo androidBuildInfo,
|
required AndroidBuildInfo androidBuildInfo,
|
||||||
@required String target,
|
required String target,
|
||||||
@required Directory outputDirectory,
|
required Directory outputDirectory,
|
||||||
@required String buildNumber,
|
required String buildNumber,
|
||||||
}) async {
|
}) async {
|
||||||
assert(project != null);
|
assert(project != null);
|
||||||
assert(target != null);
|
assert(target != null);
|
||||||
@ -638,7 +636,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
"Running Gradle task '$aarTask'...",
|
"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(
|
final String initScript = _fileSystem.path.join(
|
||||||
flutterRoot,
|
flutterRoot,
|
||||||
'packages',
|
'packages',
|
||||||
@ -721,7 +719,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
allowReentrantFlutter: true,
|
allowReentrantFlutter: true,
|
||||||
environment: <String, String>{
|
environment: <String, String>{
|
||||||
if (javaPath != null)
|
if (javaPath != null)
|
||||||
'JAVA_HOME': javaPath,
|
'JAVA_HOME': javaPath!,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
@ -757,7 +755,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
Future<void> buildPluginsAsAar(
|
Future<void> buildPluginsAsAar(
|
||||||
FlutterProject flutterProject,
|
FlutterProject flutterProject,
|
||||||
AndroidBuildInfo androidBuildInfo, {
|
AndroidBuildInfo androidBuildInfo, {
|
||||||
@required Directory buildDirectory,
|
required Directory buildDirectory,
|
||||||
}) async {
|
}) async {
|
||||||
final File flutterPluginFile = flutterProject.flutterPluginsFile;
|
final File flutterPluginFile = flutterProject.flutterPluginsFile;
|
||||||
if (!flutterPluginFile.existsSync()) {
|
if (!flutterPluginFile.existsSync()) {
|
||||||
@ -806,12 +804,12 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
|
|
||||||
/// Prints how to consume the AAR from a host app.
|
/// Prints how to consume the AAR from a host app.
|
||||||
void printHowToConsumeAar({
|
void printHowToConsumeAar({
|
||||||
@required Set<String> buildModes,
|
required Set<String> buildModes,
|
||||||
String androidPackage = 'unknown',
|
String? androidPackage = 'unknown',
|
||||||
@required Directory repoDirectory,
|
required Directory repoDirectory,
|
||||||
@required Logger logger,
|
required Logger logger,
|
||||||
@required FileSystem fileSystem,
|
required FileSystem fileSystem,
|
||||||
String buildNumber,
|
String? buildNumber,
|
||||||
}) {
|
}) {
|
||||||
assert(buildModes != null && buildModes.isNotEmpty);
|
assert(buildModes != null && buildModes.isNotEmpty);
|
||||||
assert(repoDirectory != null);
|
assert(repoDirectory != null);
|
||||||
@ -919,7 +917,7 @@ Iterable<String> findApkFilesModule(
|
|||||||
if (apkFile.existsSync()) {
|
if (apkFile.existsSync()) {
|
||||||
return <File>[apkFile];
|
return <File>[apkFile];
|
||||||
}
|
}
|
||||||
final String flavor = buildInfo.flavor;
|
final String? flavor = buildInfo.flavor;
|
||||||
if (flavor != null) {
|
if (flavor != null) {
|
||||||
// Android Studio Gradle plugin v3 adds flavor to path.
|
// Android Studio Gradle plugin v3 adds flavor to path.
|
||||||
apkFile = apkDirectory
|
apkFile = apkDirectory
|
||||||
@ -954,7 +952,7 @@ Iterable<String> listApkPaths(
|
|||||||
final String buildType = camelCase(androidBuildInfo.buildInfo.modeName);
|
final String buildType = camelCase(androidBuildInfo.buildInfo.modeName);
|
||||||
final List<String> apkPartialName = <String>[
|
final List<String> apkPartialName = <String>[
|
||||||
if (androidBuildInfo.buildInfo.flavor?.isNotEmpty ?? false)
|
if (androidBuildInfo.buildInfo.flavor?.isNotEmpty ?? false)
|
||||||
androidBuildInfo.buildInfo.lowerCasedFlavor,
|
androidBuildInfo.buildInfo.lowerCasedFlavor!,
|
||||||
'$buildType.apk',
|
'$buildType.apk',
|
||||||
];
|
];
|
||||||
if (androidBuildInfo.splitPerAbi) {
|
if (androidBuildInfo.splitPerAbi) {
|
||||||
@ -1013,15 +1011,14 @@ File findBundleFile(FlutterProject project, BuildInfo buildInfo, Logger logger,
|
|||||||
logger: logger,
|
logger: logger,
|
||||||
usage: usage,
|
usage: usage,
|
||||||
);
|
);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Throws a [ToolExit] exception and logs the event.
|
/// Throws a [ToolExit] exception and logs the event.
|
||||||
void _exitWithExpectedFileNotFound({
|
Never _exitWithExpectedFileNotFound({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required String fileExtension,
|
required String fileExtension,
|
||||||
@required Logger logger,
|
required Logger logger,
|
||||||
@required Usage usage,
|
required Usage usage,
|
||||||
}) {
|
}) {
|
||||||
assert(project != null);
|
assert(project != null);
|
||||||
assert(fileExtension != 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
|
/// This method generates symlinks in the temp directory to the engine artifacts
|
||||||
/// following the convention specified on https://maven.apache.org/pom.html#Repositories
|
/// following the convention specified on https://maven.apache.org/pom.html#Repositories
|
||||||
Directory _getLocalEngineRepo({
|
Directory _getLocalEngineRepo({
|
||||||
@required String engineOutPath,
|
required String engineOutPath,
|
||||||
@required AndroidBuildInfo androidBuildInfo,
|
required AndroidBuildInfo androidBuildInfo,
|
||||||
@required FileSystem fileSystem,
|
required FileSystem fileSystem,
|
||||||
}) {
|
}) {
|
||||||
assert(engineOutPath != null);
|
assert(engineOutPath != null);
|
||||||
assert(androidBuildInfo != null);
|
assert(androidBuildInfo != null);
|
||||||
|
@ -2,13 +2,12 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
import '../base/error_handling_io.dart';
|
import '../base/error_handling_io.dart';
|
||||||
import '../base/file_system.dart';
|
import '../base/file_system.dart';
|
||||||
import '../base/process.dart';
|
import '../base/process.dart';
|
||||||
import '../globals.dart' as globals;
|
import '../globals_null_migrated.dart' as globals;
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
import '../reporting/reporting.dart';
|
import '../reporting/reporting.dart';
|
||||||
import 'android_studio.dart';
|
import 'android_studio.dart';
|
||||||
@ -18,8 +17,8 @@ typedef GradleErrorTest = bool Function(String);
|
|||||||
/// A Gradle error handled by the tool.
|
/// A Gradle error handled by the tool.
|
||||||
class GradleHandledError {
|
class GradleHandledError {
|
||||||
const GradleHandledError({
|
const GradleHandledError({
|
||||||
@required this.test,
|
required this.test,
|
||||||
@required this.handler,
|
required this.handler,
|
||||||
this.eventLabel,
|
this.eventLabel,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -29,16 +28,16 @@ class GradleHandledError {
|
|||||||
|
|
||||||
/// The handler function.
|
/// The handler function.
|
||||||
final Future<GradleBuildStatus> Function({
|
final Future<GradleBuildStatus> Function({
|
||||||
@required String line,
|
required String line,
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required bool usesAndroidX,
|
required bool usesAndroidX,
|
||||||
@required bool shouldBuildPluginAsAar,
|
required bool shouldBuildPluginAsAar,
|
||||||
}) handler;
|
}) handler;
|
||||||
|
|
||||||
/// The [BuildEvent] label is named gradle-[eventLabel].
|
/// The [BuildEvent] label is named gradle-[eventLabel].
|
||||||
/// If not empty, the build event is logged along with
|
/// If not empty, the build event is logged along with
|
||||||
/// additional metadata such as the attempt number.
|
/// additional metadata such as the attempt number.
|
||||||
final String eventLabel;
|
final String? eventLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The status of the Gradle build.
|
/// The status of the Gradle build.
|
||||||
@ -85,10 +84,10 @@ final GradleHandledError permissionDeniedErrorHandler = GradleHandledError(
|
|||||||
'Permission denied',
|
'Permission denied',
|
||||||
]),
|
]),
|
||||||
handler: ({
|
handler: ({
|
||||||
@required String line,
|
required String line,
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required bool usesAndroidX,
|
required bool usesAndroidX,
|
||||||
@required bool shouldBuildPluginAsAar,
|
required bool shouldBuildPluginAsAar,
|
||||||
}) async {
|
}) async {
|
||||||
globals.printStatus('${globals.logger.terminal.warningMark} Gradle does not have execution permission.', emphasis: true);
|
globals.printStatus('${globals.logger.terminal.warningMark} Gradle does not have execution permission.', emphasis: true);
|
||||||
globals.printStatus(
|
globals.printStatus(
|
||||||
@ -122,17 +121,17 @@ final GradleHandledError networkErrorHandler = GradleHandledError(
|
|||||||
'Gateway Time-out'
|
'Gateway Time-out'
|
||||||
]),
|
]),
|
||||||
handler: ({
|
handler: ({
|
||||||
@required String line,
|
required String line,
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required bool usesAndroidX,
|
required bool usesAndroidX,
|
||||||
@required bool shouldBuildPluginAsAar,
|
required bool shouldBuildPluginAsAar,
|
||||||
}) async {
|
}) async {
|
||||||
globals.printError(
|
globals.printError(
|
||||||
'${globals.logger.terminal.warningMark} Gradle threw an error while downloading artifacts from the network. '
|
'${globals.logger.terminal.warningMark} Gradle threw an error while downloading artifacts from the network. '
|
||||||
'Retrying to download...'
|
'Retrying to download...'
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
final String homeDir = globals.platform.environment['HOME'];
|
final String? homeDir = globals.platform.environment['HOME'];
|
||||||
if (homeDir != null) {
|
if (homeDir != null) {
|
||||||
final Directory directory = globals.fs.directory(globals.fs.path.join(homeDir, '.gradle'));
|
final Directory directory = globals.fs.directory(globals.fs.path.join(homeDir, '.gradle'));
|
||||||
ErrorHandlingFileSystem.deleteIfExists(directory, recursive: true);
|
ErrorHandlingFileSystem.deleteIfExists(directory, recursive: true);
|
||||||
@ -152,10 +151,10 @@ final GradleHandledError r8FailureHandler = GradleHandledError(
|
|||||||
'com.android.tools.r8',
|
'com.android.tools.r8',
|
||||||
]),
|
]),
|
||||||
handler: ({
|
handler: ({
|
||||||
@required String line,
|
required String line,
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required bool usesAndroidX,
|
required bool usesAndroidX,
|
||||||
@required bool shouldBuildPluginAsAar,
|
required bool shouldBuildPluginAsAar,
|
||||||
}) async {
|
}) async {
|
||||||
globals.printStatus('${globals.logger.terminal.warningMark} The shrinker may have failed to optimize the Java bytecode.', emphasis: true);
|
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);
|
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);
|
_androidXFailureRegex.hasMatch(line);
|
||||||
},
|
},
|
||||||
handler: ({
|
handler: ({
|
||||||
@required String line,
|
required String line,
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required bool usesAndroidX,
|
required bool usesAndroidX,
|
||||||
@required bool shouldBuildPluginAsAar,
|
required bool shouldBuildPluginAsAar,
|
||||||
}) async {
|
}) async {
|
||||||
final bool hasPlugins = project.flutterPluginsFile.existsSync();
|
final bool hasPlugins = project.flutterPluginsFile.existsSync();
|
||||||
if (!hasPlugins) {
|
if (!hasPlugins) {
|
||||||
@ -259,21 +258,21 @@ final GradleHandledError licenseNotAcceptedHandler = GradleHandledError(
|
|||||||
'You have not accepted the license agreements of the following SDK components',
|
'You have not accepted the license agreements of the following SDK components',
|
||||||
]),
|
]),
|
||||||
handler: ({
|
handler: ({
|
||||||
@required String line,
|
required String line,
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required bool usesAndroidX,
|
required bool usesAndroidX,
|
||||||
@required bool shouldBuildPluginAsAar,
|
required bool shouldBuildPluginAsAar,
|
||||||
}) async {
|
}) async {
|
||||||
const String licenseNotAcceptedMatcher =
|
const String licenseNotAcceptedMatcher =
|
||||||
r'You have not accepted the license agreements of the following SDK components:\s*\[(.+)\]';
|
r'You have not accepted the license agreements of the following SDK components:\s*\[(.+)\]';
|
||||||
|
|
||||||
final RegExp licenseFailure = RegExp(licenseNotAcceptedMatcher, multiLine: true);
|
final RegExp licenseFailure = RegExp(licenseNotAcceptedMatcher, multiLine: true);
|
||||||
assert(licenseFailure != null);
|
assert(licenseFailure != null);
|
||||||
final Match licenseMatch = licenseFailure.firstMatch(line);
|
final Match? licenseMatch = licenseFailure.firstMatch(line);
|
||||||
globals.printStatus(
|
globals.printStatus(
|
||||||
'${globals.logger.terminal.warningMark} Unable to download needed Android SDK components, as the '
|
'${globals.logger.terminal.warningMark} Unable to download needed Android SDK components, as the '
|
||||||
'following licenses have not been accepted:\n'
|
'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'
|
'To resolve this, please run the following command in a Terminal:\n'
|
||||||
'flutter doctor --android-licenses'
|
'flutter doctor --android-licenses'
|
||||||
);
|
);
|
||||||
@ -293,14 +292,14 @@ final GradleHandledError flavorUndefinedHandler = GradleHandledError(
|
|||||||
return _undefinedTaskPattern.hasMatch(line);
|
return _undefinedTaskPattern.hasMatch(line);
|
||||||
},
|
},
|
||||||
handler: ({
|
handler: ({
|
||||||
@required String line,
|
required String line,
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required bool usesAndroidX,
|
required bool usesAndroidX,
|
||||||
@required bool shouldBuildPluginAsAar,
|
required bool shouldBuildPluginAsAar,
|
||||||
}) async {
|
}) async {
|
||||||
final RunResult tasksRunResult = await globals.processUtils.run(
|
final RunResult tasksRunResult = await globals.processUtils.run(
|
||||||
<String>[
|
<String>[
|
||||||
globals.gradleUtils.getExecutable(project),
|
globals.gradleUtils!.getExecutable(project),
|
||||||
'app:tasks' ,
|
'app:tasks' ,
|
||||||
'--all',
|
'--all',
|
||||||
'--console=auto',
|
'--console=auto',
|
||||||
@ -309,15 +308,15 @@ final GradleHandledError flavorUndefinedHandler = GradleHandledError(
|
|||||||
workingDirectory: project.android.hostAppGradleRoot.path,
|
workingDirectory: project.android.hostAppGradleRoot.path,
|
||||||
environment: <String, String>{
|
environment: <String, String>{
|
||||||
if (javaPath != null)
|
if (javaPath != null)
|
||||||
'JAVA_HOME': javaPath,
|
'JAVA_HOME': javaPath!,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// Extract build types and product flavors.
|
// Extract build types and product flavors.
|
||||||
final Set<String> variants = <String>{};
|
final Set<String> variants = <String>{};
|
||||||
for (final String task in tasksRunResult.stdout.split('\n')) {
|
for (final String task in tasksRunResult.stdout.split('\n')) {
|
||||||
final Match match = _assembleTaskPattern.matchAsPrefix(task);
|
final Match? match = _assembleTaskPattern.matchAsPrefix(task);
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
final String variant = match.group(1).toLowerCase();
|
final String variant = match.group(1)!.toLowerCase();
|
||||||
if (!variant.endsWith('test')) {
|
if (!variant.endsWith('test')) {
|
||||||
variants.add(variant);
|
variants.add(variant);
|
||||||
}
|
}
|
||||||
@ -366,32 +365,32 @@ final GradleHandledError minSdkVersion = GradleHandledError(
|
|||||||
return _minSdkVersionPattern.hasMatch(line);
|
return _minSdkVersionPattern.hasMatch(line);
|
||||||
},
|
},
|
||||||
handler: ({
|
handler: ({
|
||||||
@required String line,
|
required String line,
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required bool usesAndroidX,
|
required bool usesAndroidX,
|
||||||
@required bool shouldBuildPluginAsAar,
|
required bool shouldBuildPluginAsAar,
|
||||||
}) async {
|
}) async {
|
||||||
final File gradleFile = project.directory
|
final File gradleFile = project.directory
|
||||||
.childDirectory('android')
|
.childDirectory('android')
|
||||||
.childDirectory('app')
|
.childDirectory('app')
|
||||||
.childFile('build.gradle');
|
.childFile('build.gradle');
|
||||||
|
|
||||||
final Match minSdkVersionMatch = _minSdkVersionPattern.firstMatch(line);
|
final Match? minSdkVersionMatch = _minSdkVersionPattern.firstMatch(line);
|
||||||
assert(minSdkVersionMatch.groupCount == 3);
|
assert(minSdkVersionMatch?.groupCount == 3);
|
||||||
|
|
||||||
final String bold = globals.logger.terminal.bolden(
|
final String bold = globals.logger.terminal.bolden(
|
||||||
'Fix this issue by adding the following to the file ${gradleFile.path}:\n'
|
'Fix this issue by adding the following to the file ${gradleFile.path}:\n'
|
||||||
'android {\n'
|
'android {\n'
|
||||||
' defaultConfig {\n'
|
' defaultConfig {\n'
|
||||||
' minSdkVersion ${minSdkVersionMatch.group(2)}\n'
|
' minSdkVersion ${minSdkVersionMatch?.group(2)}\n'
|
||||||
' }\n'
|
' }\n'
|
||||||
'}\n'
|
'}\n'
|
||||||
);
|
);
|
||||||
globals.printStatus(
|
globals.printStatus(
|
||||||
'\n'
|
'\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'
|
'$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.'
|
'Alternatively, try to find a version of this plugin that supports these lower versions of the Android SDK.'
|
||||||
);
|
);
|
||||||
return GradleBuildStatus.exit;
|
return GradleBuildStatus.exit;
|
||||||
@ -407,10 +406,10 @@ final GradleHandledError transformInputIssue = GradleHandledError(
|
|||||||
return line.contains('https://issuetracker.google.com/issues/158753935');
|
return line.contains('https://issuetracker.google.com/issues/158753935');
|
||||||
},
|
},
|
||||||
handler: ({
|
handler: ({
|
||||||
@required String line,
|
required String line,
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required bool usesAndroidX,
|
required bool usesAndroidX,
|
||||||
@required bool shouldBuildPluginAsAar,
|
required bool shouldBuildPluginAsAar,
|
||||||
}) async {
|
}) async {
|
||||||
final File gradleFile = project.directory
|
final File gradleFile = project.directory
|
||||||
.childDirectory('android')
|
.childDirectory('android')
|
||||||
@ -441,10 +440,10 @@ final GradleHandledError lockFileDepMissing = GradleHandledError(
|
|||||||
return line.contains('which is not part of the dependency lock state');
|
return line.contains('which is not part of the dependency lock state');
|
||||||
},
|
},
|
||||||
handler: ({
|
handler: ({
|
||||||
@required String line,
|
required String line,
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required bool usesAndroidX,
|
required bool usesAndroidX,
|
||||||
@required bool shouldBuildPluginAsAar,
|
required bool shouldBuildPluginAsAar,
|
||||||
}) async {
|
}) async {
|
||||||
final File gradleFile = project.directory
|
final File gradleFile = project.directory
|
||||||
.childDirectory('android')
|
.childDirectory('android')
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
import '../base/common.dart';
|
import '../base/common.dart';
|
||||||
@ -29,11 +27,11 @@ final RegExp _androidPluginRegExp = RegExp(r'com\.android\.tools\.build:gradle:(
|
|||||||
/// or constructing a Gradle project.
|
/// or constructing a Gradle project.
|
||||||
class GradleUtils {
|
class GradleUtils {
|
||||||
GradleUtils({
|
GradleUtils({
|
||||||
@required Platform platform,
|
required Platform platform,
|
||||||
@required Logger logger,
|
required Logger logger,
|
||||||
@required FileSystem fileSystem,
|
required FileSystem fileSystem,
|
||||||
@required Cache cache,
|
required Cache cache,
|
||||||
@required OperatingSystemUtils operatingSystemUtils,
|
required OperatingSystemUtils operatingSystemUtils,
|
||||||
}) : _platform = platform,
|
}) : _platform = platform,
|
||||||
_logger = logger,
|
_logger = logger,
|
||||||
_cache = cache,
|
_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");
|
logger.printTrace("$buildFile doesn't provide an AGP version, assuming AGP version: $_defaultGradleVersion");
|
||||||
return _defaultGradleVersion;
|
return _defaultGradleVersion;
|
||||||
}
|
}
|
||||||
final String androidPluginVersion = pluginMatches.first.group(1);
|
final String? androidPluginVersion = pluginMatches.first.group(1);
|
||||||
logger.printTrace('$buildFile provides AGP version: $androidPluginVersion');
|
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.
|
/// Returns true if [targetVersion] is within the range [min] and [max] inclusive.
|
||||||
bool _isWithinVersionRange(
|
bool _isWithinVersionRange(
|
||||||
String targetVersion, {
|
String targetVersion, {
|
||||||
@required String min,
|
required String min,
|
||||||
@required String max,
|
required String max,
|
||||||
}) {
|
}) {
|
||||||
assert(min != null);
|
assert(min != null);
|
||||||
assert(max != null);
|
assert(max != null);
|
||||||
final Version parsedTargetVersion = Version.parse(targetVersion);
|
final Version? parsedTargetVersion = Version.parse(targetVersion);
|
||||||
final Version minVersion = Version.parse(min);
|
final Version? minVersion = Version.parse(min);
|
||||||
final Version maxVersion = Version.parse(max);
|
final Version? maxVersion = Version.parse(max);
|
||||||
return minVersion != null &&
|
return minVersion != null &&
|
||||||
maxVersion != null &&
|
maxVersion != null &&
|
||||||
parsedTargetVersion != null &&
|
parsedTargetVersion != null &&
|
||||||
@ -193,8 +191,8 @@ String getGradleVersionFor(String androidPluginVersion) {
|
|||||||
/// If [requireAndroidSdk] is true (the default) and no Android SDK is found,
|
/// If [requireAndroidSdk] is true (the default) and no Android SDK is found,
|
||||||
/// this will fail with a [ToolExit].
|
/// this will fail with a [ToolExit].
|
||||||
void updateLocalProperties({
|
void updateLocalProperties({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
BuildInfo buildInfo,
|
BuildInfo? buildInfo,
|
||||||
bool requireAndroidSdk = true,
|
bool requireAndroidSdk = true,
|
||||||
}) {
|
}) {
|
||||||
if (requireAndroidSdk && globals.androidSdk == null) {
|
if (requireAndroidSdk && globals.androidSdk == null) {
|
||||||
@ -211,7 +209,7 @@ void updateLocalProperties({
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeIfNecessary(String key, String value) {
|
void changeIfNecessary(String key, String? value) {
|
||||||
if (settings.values[key] == value) {
|
if (settings.values[key] == value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -223,21 +221,21 @@ void updateLocalProperties({
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final AndroidSdk androidSdk = globals.androidSdk;
|
final AndroidSdk? androidSdk = globals.androidSdk;
|
||||||
if (androidSdk != null) {
|
if (androidSdk != null) {
|
||||||
changeIfNecessary('sdk.dir', globals.fsUtils.escapePath(androidSdk.directory.path));
|
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) {
|
if (buildInfo != null) {
|
||||||
changeIfNecessary('flutter.buildMode', buildInfo.modeName);
|
changeIfNecessary('flutter.buildMode', buildInfo.modeName);
|
||||||
final String buildName = validatedBuildNameForPlatform(
|
final String? buildName = validatedBuildNameForPlatform(
|
||||||
TargetPlatform.android_arm,
|
TargetPlatform.android_arm,
|
||||||
buildInfo.buildName ?? project.manifest.buildName,
|
buildInfo.buildName ?? project.manifest.buildName,
|
||||||
globals.logger,
|
globals.logger,
|
||||||
);
|
);
|
||||||
changeIfNecessary('flutter.versionName', buildName);
|
changeIfNecessary('flutter.versionName', buildName);
|
||||||
final String buildNumber = validatedBuildNumberForPlatform(
|
final String? buildNumber = validatedBuildNumberForPlatform(
|
||||||
TargetPlatform.android_arm,
|
TargetPlatform.android_arm,
|
||||||
buildInfo.buildNumber ?? project.manifest.buildNumber,
|
buildInfo.buildNumber ?? project.manifest.buildNumber,
|
||||||
globals.logger,
|
globals.logger,
|
||||||
@ -255,7 +253,7 @@ void updateLocalProperties({
|
|||||||
/// Writes the path to the Android SDK, if known.
|
/// Writes the path to the Android SDK, if known.
|
||||||
void writeLocalProperties(File properties) {
|
void writeLocalProperties(File properties) {
|
||||||
final SettingsFile settings = SettingsFile();
|
final SettingsFile settings = SettingsFile();
|
||||||
final AndroidSdk androidSdk = globals.androidSdk;
|
final AndroidSdk? androidSdk = globals.androidSdk;
|
||||||
if (androidSdk != null) {
|
if (androidSdk != null) {
|
||||||
settings.values['sdk.dir'] = globals.fsUtils.escapePath(androidSdk.directory.path);
|
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
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'package:convert/convert.dart';
|
import 'package:convert/convert.dart';
|
||||||
import 'package:crypto/crypto.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/config.dart';
|
||||||
import 'base/file_system.dart';
|
import 'base/file_system.dart';
|
||||||
import 'base/logger.dart';
|
|
||||||
import 'build_info.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 'convert.dart';
|
||||||
import 'devfs.dart';
|
|
||||||
import 'globals_null_migrated.dart' as globals;
|
import 'globals_null_migrated.dart' as globals;
|
||||||
import 'project.dart';
|
|
||||||
|
|
||||||
String get defaultMainPath => globals.fs.path.join('lib', 'main.dart');
|
String get defaultMainPath => globals.fs.path.join('lib', 'main.dart');
|
||||||
const String defaultAssetBasePath = '.';
|
|
||||||
const String defaultManifestPath = 'pubspec.yaml';
|
const String defaultManifestPath = 'pubspec.yaml';
|
||||||
String get defaultDepfilePath => globals.fs.path.join(getBuildDirectory(), 'snapshot_blob.bin.d');
|
String get defaultDepfilePath => globals.fs.path.join(getBuildDirectory(), 'snapshot_blob.bin.d');
|
||||||
|
|
||||||
String getDefaultApplicationKernelPath({
|
String getDefaultApplicationKernelPath({
|
||||||
@required bool trackWidgetCreation,
|
required bool trackWidgetCreation,
|
||||||
}) {
|
}) {
|
||||||
return getKernelPathForTransformerOptions(
|
return getKernelPathForTransformerOptions(
|
||||||
globals.fs.path.join(getBuildDirectory(), 'app.dill'),
|
globals.fs.path.join(getBuildDirectory(), 'app.dill'),
|
||||||
@ -39,15 +25,15 @@ String getDefaultApplicationKernelPath({
|
|||||||
}
|
}
|
||||||
|
|
||||||
String getDefaultCachedKernelPath({
|
String getDefaultCachedKernelPath({
|
||||||
@required bool trackWidgetCreation,
|
required bool trackWidgetCreation,
|
||||||
@required List<String> dartDefines,
|
required List<String> dartDefines,
|
||||||
@required List<String> extraFrontEndOptions,
|
List<String> extraFrontEndOptions = const <String>[],
|
||||||
FileSystem fileSystem,
|
FileSystem? fileSystem,
|
||||||
Config config,
|
Config? config,
|
||||||
}) {
|
}) {
|
||||||
final StringBuffer buffer = StringBuffer();
|
final StringBuffer buffer = StringBuffer();
|
||||||
buffer.writeAll(dartDefines);
|
buffer.writeAll(dartDefines);
|
||||||
buffer.writeAll(extraFrontEndOptions ?? <String>[]);
|
buffer.writeAll(extraFrontEndOptions);
|
||||||
String buildPrefix = '';
|
String buildPrefix = '';
|
||||||
if (buffer.isNotEmpty) {
|
if (buffer.isNotEmpty) {
|
||||||
final String output = buffer.toString();
|
final String output = buffer.toString();
|
||||||
@ -65,7 +51,7 @@ String getDefaultCachedKernelPath({
|
|||||||
|
|
||||||
String getKernelPathForTransformerOptions(
|
String getKernelPathForTransformerOptions(
|
||||||
String path, {
|
String path, {
|
||||||
@required bool trackWidgetCreation,
|
required bool trackWidgetCreation,
|
||||||
}) {
|
}) {
|
||||||
if (trackWidgetCreation) {
|
if (trackWidgetCreation) {
|
||||||
path += '.track.dill';
|
path += '.track.dill';
|
||||||
@ -74,151 +60,3 @@ String getKernelPathForTransformerOptions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const String defaultPrivateKeyPath = 'privatekey.der';
|
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
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'base/file_system.dart';
|
import 'base/file_system.dart';
|
||||||
import 'project.dart';
|
import 'project.dart';
|
||||||
|
|
||||||
/// Extracts the `BINARY_NAME` from a project's CMake file.
|
/// Extracts the `BINARY_NAME` from a project's CMake file.
|
||||||
///
|
///
|
||||||
/// Returns `null` if it cannot be found.
|
/// Returns `null` if it cannot be found.
|
||||||
String getCmakeExecutableName(CmakeBasedProject project) {
|
String? getCmakeExecutableName(CmakeBasedProject project) {
|
||||||
if (!project.cmakeFile.existsSync()) {
|
if (!project.cmakeFile.existsSync()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final RegExp nameSetPattern = RegExp(r'^\s*set\(BINARY_NAME\s*"(.*)"\s*\)\s*$');
|
final RegExp nameSetPattern = RegExp(r'^\s*set\(BINARY_NAME\s*"(.*)"\s*\)\s*$');
|
||||||
for (final String line in project.cmakeFile.readAsLinesSync()) {
|
for (final String line in project.cmakeFile.readAsLinesSync()) {
|
||||||
final RegExpMatch match = nameSetPattern.firstMatch(line);
|
final RegExpMatch? match = nameSetPattern.firstMatch(line);
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
return match.group(1);
|
return match.group(1);
|
||||||
}
|
}
|
||||||
@ -27,13 +25,13 @@ String getCmakeExecutableName(CmakeBasedProject project) {
|
|||||||
/// Extracts the `PACKAGE_GUID` from a project's CMake file.
|
/// Extracts the `PACKAGE_GUID` from a project's CMake file.
|
||||||
///
|
///
|
||||||
/// Returns `null` if it cannot be found.
|
/// Returns `null` if it cannot be found.
|
||||||
String getCmakePackageGuid(File cmakeFile) {
|
String? getCmakePackageGuid(File cmakeFile) {
|
||||||
if (!cmakeFile.existsSync()) {
|
if (!cmakeFile.existsSync()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final RegExp nameSetPattern = RegExp(r'^\s*set\(PACKAGE_GUID\s*"(.*)"\s*\)\s*$');
|
final RegExp nameSetPattern = RegExp(r'^\s*set\(PACKAGE_GUID\s*"(.*)"\s*\)\s*$');
|
||||||
for (final String line in cmakeFile.readAsLinesSync()) {
|
for (final String line in cmakeFile.readAsLinesSync()) {
|
||||||
final RegExpMatch match = nameSetPattern.firstMatch(line);
|
final RegExpMatch? match = nameSetPattern.firstMatch(line);
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
return match.group(1);
|
return match.group(1);
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
import '../base/common.dart';
|
import '../base/common.dart';
|
||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../bundle.dart';
|
import '../bundle.dart';
|
||||||
|
import '../bundle_builder.dart';
|
||||||
import '../features.dart';
|
import '../features.dart';
|
||||||
import '../globals_null_migrated.dart' as globals;
|
import '../globals_null_migrated.dart' as globals;
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
|
@ -12,7 +12,7 @@ import '../asset.dart';
|
|||||||
import '../base/common.dart';
|
import '../base/common.dart';
|
||||||
import '../base/file_system.dart';
|
import '../base/file_system.dart';
|
||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../bundle.dart';
|
import '../bundle_builder.dart';
|
||||||
import '../devfs.dart';
|
import '../devfs.dart';
|
||||||
import '../device.dart';
|
import '../device.dart';
|
||||||
import '../globals_null_migrated.dart' as globals;
|
import '../globals_null_migrated.dart' as globals;
|
||||||
|
@ -18,6 +18,7 @@ import '../base/process.dart';
|
|||||||
import '../base/utils.dart';
|
import '../base/utils.dart';
|
||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../bundle.dart';
|
import '../bundle.dart';
|
||||||
|
import '../bundle_builder.dart';
|
||||||
import '../convert.dart';
|
import '../convert.dart';
|
||||||
import '../device.dart';
|
import '../device.dart';
|
||||||
import '../device_port_forwarder.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
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:package_config/package_config.dart';
|
import 'package:package_config/package_config.dart';
|
||||||
import 'package:path/path.dart' as path; // flutter_ignore: package_path_import
|
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/language_version.dart';
|
||||||
import 'dart/package_map.dart';
|
import 'dart/package_map.dart';
|
||||||
import 'features.dart';
|
import 'features.dart';
|
||||||
import 'globals.dart' as globals;
|
import 'globals_null_migrated.dart' as globals;
|
||||||
import 'platform_plugins.dart';
|
import 'platform_plugins.dart';
|
||||||
import 'plugins.dart';
|
import 'plugins.dart';
|
||||||
import 'project.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
|
final String renderedTemplate = templateRenderer
|
||||||
.renderString(template, context, htmlEscapeValues: false);
|
.renderString(template, context, htmlEscapeValues: false);
|
||||||
file.createSync(recursive: true);
|
file.createSync(recursive: true);
|
||||||
file.writeAsStringSync(renderedTemplate);
|
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 FileSystem fs = fileSystem ?? globals.fs;
|
||||||
final File pubspecFile = fs.file(packageRoot.resolve('pubspec.yaml'));
|
final File pubspecFile = fs.file(packageRoot.resolve('pubspec.yaml'));
|
||||||
if (!pubspecFile.existsSync()) {
|
if (!pubspecFile.existsSync()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
dynamic pubspec;
|
Object? pubspec;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pubspec = loadYaml(pubspecFile.readAsStringSync());
|
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');
|
globals.printTrace('Failed to parse plugin manifest for $name: $err');
|
||||||
// Do nothing, potentially not a plugin.
|
// Do nothing, potentially not a plugin.
|
||||||
}
|
}
|
||||||
if (pubspec == null) {
|
if (pubspec == null || pubspec is! YamlMap) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final dynamic flutterConfig = pubspec['flutter'];
|
final Object? flutterConfig = pubspec['flutter'];
|
||||||
if (flutterConfig == null || !(flutterConfig.containsKey('plugin') as bool)) {
|
if (flutterConfig == null || flutterConfig is! YamlMap || !flutterConfig.containsKey('plugin')) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final String packageRootPath = fs.path.fromUri(packageRoot);
|
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');
|
globals.printTrace('Found plugin $name at $packageRootPath');
|
||||||
return Plugin.fromYaml(
|
return Plugin.fromYaml(
|
||||||
name,
|
name,
|
||||||
packageRootPath,
|
packageRootPath,
|
||||||
flutterConfig['plugin'] as YamlMap,
|
flutterConfig['plugin'] as YamlMap?,
|
||||||
dependencies == null ? <String>[] : <String>[...dependencies.keys.cast<String>()],
|
dependencies == null ? <String>[] : <String>[...dependencies.keys.cast<String>()],
|
||||||
fileSystem: fs,
|
fileSystem: fs,
|
||||||
appDependencies: appDependencies,
|
appDependencies: appDependencies,
|
||||||
@ -82,7 +80,7 @@ Future<List<Plugin>> findPlugins(FlutterProject project, { bool throwOnError = t
|
|||||||
);
|
);
|
||||||
for (final Package package in packageConfig.packages) {
|
for (final Package package in packageConfig.packages) {
|
||||||
final Uri packageRoot = package.packageUriRoot.resolve('..');
|
final Uri packageRoot = package.packageUriRoot.resolve('..');
|
||||||
final Plugin plugin = _pluginFromPackage(
|
final Plugin? plugin = _pluginFromPackage(
|
||||||
package.name,
|
package.name,
|
||||||
packageRoot,
|
packageRoot,
|
||||||
project.manifest.dependencies,
|
project.manifest.dependencies,
|
||||||
@ -102,15 +100,15 @@ const String _kFlutterPluginsPathKey = 'path';
|
|||||||
const String _kFlutterPluginsDependenciesKey = 'dependencies';
|
const String _kFlutterPluginsDependenciesKey = 'dependencies';
|
||||||
|
|
||||||
/// Filters [plugins] to those supported by [platformKey].
|
/// 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) {
|
final Iterable<Plugin> platformPlugins = plugins.where((Plugin p) {
|
||||||
return p.platforms.containsKey(platformKey);
|
return p.platforms.containsKey(platformKey);
|
||||||
});
|
});
|
||||||
|
|
||||||
final Set<String> pluginNames = platformPlugins.map((Plugin plugin) => plugin.name).toSet();
|
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) {
|
for (final Plugin plugin in platformPlugins) {
|
||||||
pluginInfo.add(<String, dynamic>{
|
pluginInfo.add(<String, Object>{
|
||||||
_kFlutterPluginsNameKey: plugin.name,
|
_kFlutterPluginsNameKey: plugin.name,
|
||||||
_kFlutterPluginsPathKey: globals.fsUtils.escapePath(plugin.path),
|
_kFlutterPluginsPathKey: globals.fsUtils.escapePath(plugin.path),
|
||||||
_kFlutterPluginsDependenciesKey: <String>[...plugin.dependencies.where(pluginNames.contains)],
|
_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 windowsKey = project.windows.pluginConfigKey;
|
||||||
final String webKey = project.web.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[iosKey] = _filterPluginsByPlatform(plugins, iosKey);
|
||||||
pluginsMap[androidKey] = _filterPluginsByPlatform(plugins, androidKey);
|
pluginsMap[androidKey] = _filterPluginsByPlatform(plugins, androidKey);
|
||||||
pluginsMap[macosKey] = _filterPluginsByPlatform(plugins, macosKey);
|
pluginsMap[macosKey] = _filterPluginsByPlatform(plugins, macosKey);
|
||||||
@ -187,7 +185,7 @@ bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) {
|
|||||||
pluginsMap[windowsKey] = _filterPluginsByPlatform(plugins, windowsKey);
|
pluginsMap[windowsKey] = _filterPluginsByPlatform(plugins, windowsKey);
|
||||||
pluginsMap[webKey] = _filterPluginsByPlatform(plugins, webKey);
|
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['info'] = 'This is a generated file; do not edit or check into version control.';
|
||||||
result[_kFlutterPluginsPluginListKey] = pluginsMap;
|
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,
|
// Only notify if the plugins list has changed. [date_created] will always be different,
|
||||||
// [version] is not relevant for this check.
|
// [version] is not relevant for this check.
|
||||||
final String oldPluginsFileStringContent = _readFileContent(pluginsFile);
|
final String? oldPluginsFileStringContent = _readFileContent(pluginsFile);
|
||||||
bool pluginsChanged = true;
|
bool pluginsChanged = true;
|
||||||
if (oldPluginsFileStringContent != null) {
|
if (oldPluginsFileStringContent != null) {
|
||||||
pluginsChanged = oldPluginsFileStringContent.contains(pluginsMap.toString());
|
pluginsChanged = oldPluginsFileStringContent.contains(pluginsMap.toString());
|
||||||
@ -211,12 +209,12 @@ bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) {
|
|||||||
return pluginsChanged;
|
return pluginsChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<dynamic> _createPluginLegacyDependencyGraph(List<Plugin> plugins) {
|
List<Object?> _createPluginLegacyDependencyGraph(List<Plugin> plugins) {
|
||||||
final List<dynamic> directAppDependencies = <dynamic>[];
|
final List<Object> directAppDependencies = <Object>[];
|
||||||
|
|
||||||
final Set<String> pluginNames = plugins.map((Plugin plugin) => plugin.name).toSet();
|
final Set<String> pluginNames = plugins.map((Plugin plugin) => plugin.name).toSet();
|
||||||
for (final Plugin plugin in plugins) {
|
for (final Plugin plugin in plugins) {
|
||||||
directAppDependencies.add(<String, dynamic>{
|
directAppDependencies.add(<String, Object>{
|
||||||
'name': plugin.name,
|
'name': plugin.name,
|
||||||
// Extract the plugin dependencies which happen to be plugins.
|
// Extract the plugin dependencies which happen to be plugins.
|
||||||
'dependencies': <String>[...plugin.dependencies.where(pluginNames.contains)],
|
'dependencies': <String>[...plugin.dependencies.where(pluginNames.contains)],
|
||||||
@ -245,7 +243,7 @@ bool _writeFlutterPluginsListLegacy(FlutterProject project, List<Plugin> plugins
|
|||||||
for (final Plugin plugin in plugins) {
|
for (final Plugin plugin in plugins) {
|
||||||
flutterPluginsBuffer.write('${plugin.name}=${globals.fsUtils.escapePath(plugin.path)}\n');
|
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();
|
final String pluginFileContent = flutterPluginsBuffer.toString();
|
||||||
pluginsFile.writeAsStringSync(pluginFileContent, flush: true);
|
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.
|
/// 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;
|
return file.existsSync() ? file.readAsStringSync() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,10 +333,10 @@ public final class GeneratedPluginRegistrant {
|
|||||||
}
|
}
|
||||||
''';
|
''';
|
||||||
|
|
||||||
List<Map<String, dynamic>> _extractPlatformMaps(List<Plugin> plugins, String type) {
|
List<Map<String, Object?>> _extractPlatformMaps(List<Plugin> plugins, String type) {
|
||||||
final List<Map<String, dynamic>> pluginConfigs = <Map<String, dynamic>>[];
|
final List<Map<String, Object?>> pluginConfigs = <Map<String, Object?>>[];
|
||||||
for (final Plugin p in plugins) {
|
for (final Plugin p in plugins) {
|
||||||
final PluginPlatform platformPlugin = p.platforms[type];
|
final PluginPlatform? platformPlugin = p.platforms[type];
|
||||||
if (platformPlugin != null) {
|
if (platformPlugin != null) {
|
||||||
pluginConfigs.add(platformPlugin.toMap());
|
pluginConfigs.add(platformPlugin.toMap());
|
||||||
}
|
}
|
||||||
@ -355,10 +353,10 @@ AndroidEmbeddingVersion _getAndroidEmbeddingVersion(FlutterProject project) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin> plugins) async {
|
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);
|
_extractPlatformMaps(plugins, AndroidPlugin.kConfigKey);
|
||||||
|
|
||||||
final Map<String, dynamic> templateContext = <String, dynamic>{
|
final Map<String, Object> templateContext = <String, Object>{
|
||||||
'plugins': androidPlugins,
|
'plugins': androidPlugins,
|
||||||
'androidX': isAppUsingAndroidX(project.android.hostAppGradleRoot),
|
'androidX': isAppUsingAndroidX(project.android.hostAppGradleRoot),
|
||||||
};
|
};
|
||||||
@ -382,8 +380,10 @@ Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin>
|
|||||||
templateContext['needsShim'] = false;
|
templateContext['needsShim'] = false;
|
||||||
// If a plugin is using an embedding version older than 2.0 and the app is using 2.0,
|
// 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.
|
// then add shim for the old plugins.
|
||||||
for (final Map<String, dynamic> plugin in androidPlugins) {
|
for (final Map<String, Object?> plugin in androidPlugins) {
|
||||||
if (plugin['supportsEmbeddingV1'] as bool && !(plugin['supportsEmbeddingV2'] as bool)) {
|
final bool supportsEmbeddingV1 = (plugin['supportsEmbeddingV1'] as bool?) == true;
|
||||||
|
final bool supportsEmbeddingV2 = (plugin['supportsEmbeddingV2'] as bool?) == true;
|
||||||
|
if (supportsEmbeddingV1 && !supportsEmbeddingV2) {
|
||||||
templateContext['needsShim'] = true;
|
templateContext['needsShim'] = true;
|
||||||
if (project.isModule) {
|
if (project.isModule) {
|
||||||
globals.printStatus(
|
globals.printStatus(
|
||||||
@ -401,8 +401,10 @@ Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin>
|
|||||||
break;
|
break;
|
||||||
case AndroidEmbeddingVersion.v1:
|
case AndroidEmbeddingVersion.v1:
|
||||||
default:
|
default:
|
||||||
for (final Map<String, dynamic> plugin in androidPlugins) {
|
for (final Map<String, Object?> plugin in androidPlugins) {
|
||||||
if (!(plugin['supportsEmbeddingV1'] as bool) && plugin['supportsEmbeddingV2'] as bool) {
|
final bool supportsEmbeddingV1 = (plugin['supportsEmbeddingV1'] as bool?) == true;
|
||||||
|
final bool supportsEmbeddingV2 = (plugin['supportsEmbeddingV2'] as bool?) == true;
|
||||||
|
if (!supportsEmbeddingV1 && supportsEmbeddingV2) {
|
||||||
throwToolExit(
|
throwToolExit(
|
||||||
'The plugin `${plugin['name']}` requires your app to be migrated to '
|
'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 '
|
'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 {
|
Future<void> _writeIOSPluginRegistrant(FlutterProject project, List<Plugin> plugins) async {
|
||||||
final List<Map<String, dynamic>> iosPlugins = _extractPlatformMaps(plugins, IOSPlugin.kConfigKey);
|
final List<Map<String, Object?>> iosPlugins = _extractPlatformMaps(plugins, IOSPlugin.kConfigKey);
|
||||||
final Map<String, dynamic> context = <String, dynamic>{
|
final Map<String, Object> context = <String, Object>{
|
||||||
'os': 'ios',
|
'os': 'ios',
|
||||||
'deploymentTarget': '9.0',
|
'deploymentTarget': '9.0',
|
||||||
'framework': 'Flutter',
|
'framework': 'Flutter',
|
||||||
@ -761,8 +763,8 @@ String _cmakeRelativePluginSymlinkDirectoryPath(CmakeBasedProject project) {
|
|||||||
|
|
||||||
Future<void> _writeLinuxPluginFiles(FlutterProject project, List<Plugin> plugins) async {
|
Future<void> _writeLinuxPluginFiles(FlutterProject project, List<Plugin> plugins) async {
|
||||||
final List<Plugin>nativePlugins = _filterNativePlugins(plugins, LinuxPlugin.kConfigKey);
|
final List<Plugin>nativePlugins = _filterNativePlugins(plugins, LinuxPlugin.kConfigKey);
|
||||||
final List<Map<String, dynamic>> linuxPlugins = _extractPlatformMaps(nativePlugins, LinuxPlugin.kConfigKey);
|
final List<Map<String, Object?>> linuxPlugins = _extractPlatformMaps(nativePlugins, LinuxPlugin.kConfigKey);
|
||||||
final Map<String, dynamic> context = <String, dynamic>{
|
final Map<String, Object> context = <String, Object>{
|
||||||
'os': 'linux',
|
'os': 'linux',
|
||||||
'plugins': linuxPlugins,
|
'plugins': linuxPlugins,
|
||||||
'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.linux),
|
'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.linux),
|
||||||
@ -771,7 +773,7 @@ Future<void> _writeLinuxPluginFiles(FlutterProject project, List<Plugin> plugins
|
|||||||
await _writePluginCmakefile(project.linux.generatedPluginCmakeFile, context, globals.templateRenderer);
|
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(
|
_renderTemplateToFile(
|
||||||
_linuxPluginRegistryHeaderTemplate,
|
_linuxPluginRegistryHeaderTemplate,
|
||||||
templateContext,
|
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(
|
_renderTemplateToFile(
|
||||||
_pluginCmakefileTemplate,
|
_pluginCmakefileTemplate,
|
||||||
templateContext,
|
templateContext,
|
||||||
@ -797,8 +799,8 @@ Future<void> _writePluginCmakefile(File destinationFile, Map<String, dynamic> te
|
|||||||
|
|
||||||
Future<void> _writeMacOSPluginRegistrant(FlutterProject project, List<Plugin> plugins) async {
|
Future<void> _writeMacOSPluginRegistrant(FlutterProject project, List<Plugin> plugins) async {
|
||||||
final List<Plugin>nativePlugins = _filterNativePlugins(plugins, MacOSPlugin.kConfigKey);
|
final List<Plugin>nativePlugins = _filterNativePlugins(plugins, MacOSPlugin.kConfigKey);
|
||||||
final List<Map<String, dynamic>> macosPlugins = _extractPlatformMaps(nativePlugins, MacOSPlugin.kConfigKey);
|
final List<Map<String, Object?>> macosPlugins = _extractPlatformMaps(nativePlugins, MacOSPlugin.kConfigKey);
|
||||||
final Map<String, dynamic> context = <String, dynamic>{
|
final Map<String, Object> context = <String, Object>{
|
||||||
'os': 'macos',
|
'os': 'macos',
|
||||||
'framework': 'FlutterMacOS',
|
'framework': 'FlutterMacOS',
|
||||||
'plugins': macosPlugins,
|
'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.
|
/// Filters out Dart-only plugins, which shouldn't be added to the native generated registrants.
|
||||||
List<Plugin> _filterNativePlugins(List<Plugin> plugins, String platformKey) {
|
List<Plugin> _filterNativePlugins(List<Plugin> plugins, String platformKey) {
|
||||||
return plugins.where((Plugin element) {
|
return plugins.where((Plugin element) {
|
||||||
final PluginPlatform plugin = element.platforms[platformKey];
|
final PluginPlatform? plugin = element.platforms[platformKey];
|
||||||
if (plugin == null) {
|
if (plugin == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -830,7 +832,7 @@ List<Plugin> _filterNativePlugins(List<Plugin> plugins, String platformKey) {
|
|||||||
/// Returns only the plugins with the given platform variant.
|
/// Returns only the plugins with the given platform variant.
|
||||||
List<Plugin> _filterPluginsByVariant(List<Plugin> plugins, String platformKey, PluginPlatformVariant variant) {
|
List<Plugin> _filterPluginsByVariant(List<Plugin> plugins, String platformKey, PluginPlatformVariant variant) {
|
||||||
return plugins.where((Plugin element) {
|
return plugins.where((Plugin element) {
|
||||||
final PluginPlatform platformPlugin = element.platforms[platformKey];
|
final PluginPlatform? platformPlugin = element.platforms[platformKey];
|
||||||
if (platformPlugin == null) {
|
if (platformPlugin == null) {
|
||||||
return false;
|
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 {
|
Future<void> writeWindowsPluginFiles(FlutterProject project, List<Plugin> plugins, TemplateRenderer templateRenderer) async {
|
||||||
final List<Plugin> nativePlugins = _filterNativePlugins(plugins, WindowsPlugin.kConfigKey);
|
final List<Plugin> nativePlugins = _filterNativePlugins(plugins, WindowsPlugin.kConfigKey);
|
||||||
final List<Plugin> win32Plugins = _filterPluginsByVariant(nativePlugins, WindowsPlugin.kConfigKey, PluginPlatformVariant.win32);
|
final List<Plugin> win32Plugins = _filterPluginsByVariant(nativePlugins, WindowsPlugin.kConfigKey, PluginPlatformVariant.win32);
|
||||||
final List<Map<String, dynamic>> pluginInfo = _extractPlatformMaps(win32Plugins, WindowsPlugin.kConfigKey);
|
final List<Map<String, Object?>> pluginInfo = _extractPlatformMaps(win32Plugins, WindowsPlugin.kConfigKey);
|
||||||
final Map<String, dynamic> context = <String, dynamic>{
|
final Map<String, Object> context = <String, Object>{
|
||||||
'os': 'windows',
|
'os': 'windows',
|
||||||
'plugins': pluginInfo,
|
'plugins': pluginInfo,
|
||||||
'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.windows),
|
'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 {
|
Future<void> writeWindowsUwpPluginFiles(FlutterProject project, List<Plugin> plugins, TemplateRenderer templateRenderer) async {
|
||||||
final List<Plugin> nativePlugins = _filterNativePlugins(plugins, WindowsPlugin.kConfigKey);
|
final List<Plugin> nativePlugins = _filterNativePlugins(plugins, WindowsPlugin.kConfigKey);
|
||||||
final List<Plugin> uwpPlugins = _filterPluginsByVariant(nativePlugins, WindowsPlugin.kConfigKey, PluginPlatformVariant.winuwp);
|
final List<Plugin> uwpPlugins = _filterPluginsByVariant(nativePlugins, WindowsPlugin.kConfigKey, PluginPlatformVariant.winuwp);
|
||||||
final List<Map<String, dynamic>> pluginInfo = _extractPlatformMaps(uwpPlugins, WindowsPlugin.kConfigKey);
|
final List<Map<String, Object?>> pluginInfo = _extractPlatformMaps(uwpPlugins, WindowsPlugin.kConfigKey);
|
||||||
final Map<String, dynamic> context = <String, dynamic>{
|
final Map<String, Object> context = <String, Object>{
|
||||||
'os': 'windows',
|
'os': 'windows',
|
||||||
'plugins': pluginInfo,
|
'plugins': pluginInfo,
|
||||||
'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.windowsUwp),
|
'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.windowsUwp),
|
||||||
@ -870,7 +872,7 @@ Future<void> writeWindowsUwpPluginFiles(FlutterProject project, List<Plugin> plu
|
|||||||
await _writePluginCmakefile(project.windowsUwp.generatedPluginCmakeFile, context, templateRenderer);
|
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(
|
_renderTemplateToFile(
|
||||||
_cppPluginRegistryHeaderTemplate,
|
_cppPluginRegistryHeaderTemplate,
|
||||||
templateContext,
|
templateContext,
|
||||||
@ -886,13 +888,13 @@ Future<void> _writeCppPluginRegistrant(Directory destination, Map<String, dynami
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _writeWebPluginRegistrant(FlutterProject project, List<Plugin> plugins) async {
|
Future<void> _writeWebPluginRegistrant(FlutterProject project, List<Plugin> plugins) async {
|
||||||
final List<Map<String, dynamic>> webPlugins = _extractPlatformMaps(plugins, WebPlugin.kConfigKey);
|
final List<Map<String, Object?>> webPlugins = _extractPlatformMaps(plugins, WebPlugin.kConfigKey);
|
||||||
final Map<String, dynamic> context = <String, dynamic>{
|
final Map<String, Object> context = <String, Object>{
|
||||||
'plugins': webPlugins,
|
'plugins': webPlugins,
|
||||||
};
|
};
|
||||||
final File pluginFile = project.web.libDirectory.childFile('generated_plugin_registrant.dart');
|
final File pluginFile = project.web.libDirectory.childFile('generated_plugin_registrant.dart');
|
||||||
if (webPlugins.isEmpty) {
|
if (webPlugins.isEmpty) {
|
||||||
return ErrorHandlingFileSystem.deleteIfExists(pluginFile);
|
ErrorHandlingFileSystem.deleteIfExists(pluginFile);
|
||||||
} else {
|
} else {
|
||||||
_renderTemplateToFile(
|
_renderTemplateToFile(
|
||||||
_dartPluginRegistryTemplate,
|
_dartPluginRegistryTemplate,
|
||||||
@ -911,34 +913,34 @@ Future<void> _writeWebPluginRegistrant(FlutterProject project, List<Plugin> plug
|
|||||||
///
|
///
|
||||||
/// This uses [project.flutterPluginsDependenciesFile], so it should only be
|
/// This uses [project.flutterPluginsDependenciesFile], so it should only be
|
||||||
/// run after refreshPluginList has been run since the last plugin change.
|
/// 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;
|
final FeatureFlags localFeatureFlags = featureFlagsOverride ?? featureFlags;
|
||||||
Map<String, dynamic> platformPlugins;
|
Map<String, Object?>? platformPlugins;
|
||||||
final String pluginFileContent = _readFileContent(project.flutterPluginsDependenciesFile);
|
final String? pluginFileContent = _readFileContent(project.flutterPluginsDependenciesFile);
|
||||||
if (pluginFileContent != null) {
|
if (pluginFileContent != null) {
|
||||||
final Map<String, dynamic> pluginInfo = json.decode(pluginFileContent) as Map<String, dynamic>;
|
final Map<String, Object?>? pluginInfo = json.decode(pluginFileContent) as Map<String, Object?>?;
|
||||||
platformPlugins = pluginInfo[_kFlutterPluginsPluginListKey] as Map<String, dynamic>;
|
platformPlugins = pluginInfo?[_kFlutterPluginsPluginListKey] as Map<String, Object?>?;
|
||||||
}
|
}
|
||||||
platformPlugins ??= <String, dynamic>{};
|
platformPlugins ??= <String, Object?>{};
|
||||||
|
|
||||||
if (localFeatureFlags.isWindowsEnabled && project.windows.existsSync()) {
|
if (localFeatureFlags.isWindowsEnabled && project.windows.existsSync()) {
|
||||||
_createPlatformPluginSymlinks(
|
_createPlatformPluginSymlinks(
|
||||||
project.windows.pluginSymlinkDirectory,
|
project.windows.pluginSymlinkDirectory,
|
||||||
platformPlugins[project.windows.pluginConfigKey] as List<dynamic>,
|
platformPlugins[project.windows.pluginConfigKey] as List<Object?>?,
|
||||||
force: force,
|
force: force,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (localFeatureFlags.isLinuxEnabled && project.linux.existsSync()) {
|
if (localFeatureFlags.isLinuxEnabled && project.linux.existsSync()) {
|
||||||
_createPlatformPluginSymlinks(
|
_createPlatformPluginSymlinks(
|
||||||
project.linux.pluginSymlinkDirectory,
|
project.linux.pluginSymlinkDirectory,
|
||||||
platformPlugins[project.linux.pluginConfigKey] as List<dynamic>,
|
platformPlugins[project.linux.pluginConfigKey] as List<Object?>?,
|
||||||
force: force,
|
force: force,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (localFeatureFlags.isWindowsUwpEnabled && project.windowsUwp.existsSync()) {
|
if (localFeatureFlags.isWindowsUwpEnabled && project.windowsUwp.existsSync()) {
|
||||||
_createPlatformPluginSymlinks(
|
_createPlatformPluginSymlinks(
|
||||||
project.windowsUwp.pluginSymlinkDirectory,
|
project.windowsUwp.pluginSymlinkDirectory,
|
||||||
platformPlugins[project.windows.pluginConfigKey] as List<dynamic>,
|
platformPlugins[project.windows.pluginConfigKey] as List<Object?>?,
|
||||||
force: force,
|
force: force,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -948,12 +950,12 @@ void createPluginSymlinks(FlutterProject project, {bool force = false, @visibleF
|
|||||||
/// failure cases.
|
/// failure cases.
|
||||||
@visibleForTesting
|
@visibleForTesting
|
||||||
void handleSymlinkException(FileSystemException e, {
|
void handleSymlinkException(FileSystemException e, {
|
||||||
@required Platform platform,
|
required Platform platform,
|
||||||
@required OperatingSystemUtils os,
|
required OperatingSystemUtils os,
|
||||||
}) {
|
}) {
|
||||||
if (platform.isWindows && (e.osError?.errorCode ?? 0) == 1314) {
|
if (platform.isWindows && (e.osError?.errorCode ?? 0) == 1314) {
|
||||||
final String versionString = RegExp(r'[\d.]+').firstMatch(os.name)?.group(0);
|
final String? versionString = RegExp(r'[\d.]+').firstMatch(os.name)?.group(0);
|
||||||
final Version version = Version.parse(versionString);
|
final Version? version = Version.parse(versionString);
|
||||||
// Windows 10 14972 is the oldest version that allows creating symlinks
|
// Windows 10 14972 is the oldest version that allows creating symlinks
|
||||||
// just by enabling developer mode; before that it requires running the
|
// just by enabling developer mode; before that it requires running the
|
||||||
// terminal as Administrator.
|
// terminal as Administrator.
|
||||||
@ -970,7 +972,7 @@ void handleSymlinkException(FileSystemException e, {
|
|||||||
/// Creates [symlinkDirectory] containing symlinks to each plugin listed in [platformPlugins].
|
/// Creates [symlinkDirectory] containing symlinks to each plugin listed in [platformPlugins].
|
||||||
///
|
///
|
||||||
/// If [force] is true, the directory will be created only if missing.
|
/// 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()) {
|
if (force && symlinkDirectory.existsSync()) {
|
||||||
// Start fresh to avoid stale links.
|
// Start fresh to avoid stale links.
|
||||||
symlinkDirectory.deleteSync(recursive: true);
|
symlinkDirectory.deleteSync(recursive: true);
|
||||||
@ -979,9 +981,9 @@ void _createPlatformPluginSymlinks(Directory symlinkDirectory, List<dynamic> pla
|
|||||||
if (platformPlugins == null) {
|
if (platformPlugins == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (final Map<String, dynamic> pluginInfo in platformPlugins.cast<Map<String, dynamic>>()) {
|
for (final Map<String, Object?> pluginInfo in platformPlugins.cast<Map<String, Object?>>()) {
|
||||||
final String name = pluginInfo[_kFlutterPluginsNameKey] as String;
|
final String name = pluginInfo[_kFlutterPluginsNameKey]! as String;
|
||||||
final String path = pluginInfo[_kFlutterPluginsPathKey] as String;
|
final String path = pluginInfo[_kFlutterPluginsPathKey]! as String;
|
||||||
final Link link = symlinkDirectory.childLink(name);
|
final Link link = symlinkDirectory.childLink(name);
|
||||||
if (link.existsSync()) {
|
if (link.existsSync()) {
|
||||||
continue;
|
continue;
|
||||||
@ -1015,10 +1017,10 @@ Future<void> refreshPluginsList(
|
|||||||
if (changed || legacyChanged) {
|
if (changed || legacyChanged) {
|
||||||
createPluginSymlinks(project, force: true);
|
createPluginSymlinks(project, force: true);
|
||||||
if (iosPlatform) {
|
if (iosPlatform) {
|
||||||
globals.cocoaPods.invalidatePodInstallOutput(project.ios);
|
globals.cocoaPods?.invalidatePodInstallOutput(project.ios);
|
||||||
}
|
}
|
||||||
if (macOSPlatform) {
|
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) {
|
for (final XcodeBasedProject subproject in darwinProjects) {
|
||||||
if (plugins.isNotEmpty) {
|
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`
|
/// The user may have a custom maintained Podfile that they're running `pod install`
|
||||||
/// on themselves.
|
/// on themselves.
|
||||||
else if (subproject.podfile.existsSync() && subproject.podfileLock.existsSync()) {
|
else if (subproject.podfile.existsSync() && subproject.podfileLock.existsSync()) {
|
||||||
globals.cocoaPods.addPodsDependencyToFlutterXcconfig(subproject);
|
globals.cocoaPods?.addPodsDependencyToFlutterXcconfig(subproject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1119,9 +1121,9 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// The plugin doesn't implement an interface, verify that it has a default implementation.
|
// 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) {
|
if (implementsPackage == null || implementsPackage.isEmpty) {
|
||||||
final String defaultImplementation = plugin.defaultPackagePlatforms[platform];
|
final String? defaultImplementation = plugin.defaultPackagePlatforms[platform];
|
||||||
if (defaultImplementation == null) {
|
if (defaultImplementation == null) {
|
||||||
if (throwOnPluginPubspecError) {
|
if (throwOnPluginPubspecError) {
|
||||||
globals.printError(
|
globals.printError(
|
||||||
@ -1153,7 +1155,7 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
|
|||||||
}
|
}
|
||||||
final String resolutionKey = '$platform/$implementsPackage';
|
final String resolutionKey = '$platform/$implementsPackage';
|
||||||
if (directDependencyResolutions.containsKey(resolutionKey)) {
|
if (directDependencyResolutions.containsKey(resolutionKey)) {
|
||||||
final PluginInterfaceResolution currResolution = directDependencyResolutions[resolutionKey];
|
final PluginInterfaceResolution? currResolution = directDependencyResolutions[resolutionKey];
|
||||||
if (currResolution != null && currResolution.plugin.isDirectDependency) {
|
if (currResolution != null && currResolution.plugin.isDirectDependency) {
|
||||||
if (plugin.isDirectDependency) {
|
if (plugin.isDirectDependency) {
|
||||||
if (throwOnPluginPubspecError) {
|
if (throwOnPluginPubspecError) {
|
||||||
@ -1223,14 +1225,14 @@ Future<void> generateMainDartWithPluginRegistrant(
|
|||||||
final LanguageVersion entrypointVersion = determineLanguageVersion(
|
final LanguageVersion entrypointVersion = determineLanguageVersion(
|
||||||
mainFile,
|
mainFile,
|
||||||
packageConfig.packageOf(mainFile.absolute.uri),
|
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,
|
'mainEntrypoint': currentMainUri,
|
||||||
'dartLanguageVersion': entrypointVersion.toString(),
|
'dartLanguageVersion': entrypointVersion.toString(),
|
||||||
LinuxPlugin.kConfigKey: <dynamic>[],
|
LinuxPlugin.kConfigKey: <Object?>[],
|
||||||
MacOSPlugin.kConfigKey: <dynamic>[],
|
MacOSPlugin.kConfigKey: <Object?>[],
|
||||||
WindowsPlugin.kConfigKey: <dynamic>[],
|
WindowsPlugin.kConfigKey: <Object?>[],
|
||||||
};
|
};
|
||||||
if (resolutions.isEmpty) {
|
if (resolutions.isEmpty) {
|
||||||
try {
|
try {
|
||||||
@ -1248,7 +1250,7 @@ Future<void> generateMainDartWithPluginRegistrant(
|
|||||||
}
|
}
|
||||||
for (final PluginInterfaceResolution resolution in resolutions) {
|
for (final PluginInterfaceResolution resolution in resolutions) {
|
||||||
assert(templateContext.containsKey(resolution.platform));
|
assert(templateContext.containsKey(resolution.platform));
|
||||||
(templateContext[resolution.platform] as List<dynamic>).add(resolution.toMap());
|
(templateContext[resolution.platform] as List<Object?>?)?.add(resolution.toMap());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
_renderTemplateToFile(
|
_renderTemplateToFile(
|
||||||
|
@ -13,7 +13,7 @@ import '../base/file_system.dart';
|
|||||||
import '../base/logger.dart';
|
import '../base/logger.dart';
|
||||||
import '../base/utils.dart';
|
import '../base/utils.dart';
|
||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../bundle.dart';
|
import '../bundle_builder.dart';
|
||||||
import '../convert.dart';
|
import '../convert.dart';
|
||||||
import '../devfs.dart';
|
import '../devfs.dart';
|
||||||
import '../globals_null_migrated.dart' as globals;
|
import '../globals_null_migrated.dart' as globals;
|
||||||
|
@ -4,17 +4,13 @@
|
|||||||
|
|
||||||
// @dart = 2.8
|
// @dart = 2.8
|
||||||
|
|
||||||
import 'android/gradle_utils.dart';
|
|
||||||
import 'base/context.dart';
|
import 'base/context.dart';
|
||||||
import 'device.dart';
|
import 'device.dart';
|
||||||
import 'doctor.dart';
|
import 'doctor.dart';
|
||||||
import 'fuchsia/fuchsia_sdk.dart';
|
import 'fuchsia/fuchsia_sdk.dart';
|
||||||
import 'globals_null_migrated.dart' as globals;
|
|
||||||
import 'ios/simulators.dart';
|
import 'ios/simulators.dart';
|
||||||
import 'macos/cocoapods.dart';
|
|
||||||
import 'macos/cocoapods_validator.dart';
|
import 'macos/cocoapods_validator.dart';
|
||||||
import 'macos/xcdevice.dart';
|
import 'macos/xcdevice.dart';
|
||||||
import 'project.dart';
|
|
||||||
import 'reporting/crash_reporting.dart';
|
import 'reporting/crash_reporting.dart';
|
||||||
import 'runner/local_engine.dart';
|
import 'runner/local_engine.dart';
|
||||||
|
|
||||||
@ -24,22 +20,10 @@ CrashReporter get crashReporter => context.get<CrashReporter>();
|
|||||||
Doctor get doctor => context.get<Doctor>();
|
Doctor get doctor => context.get<Doctor>();
|
||||||
DeviceManager get deviceManager => context.get<DeviceManager>();
|
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>();
|
CocoaPodsValidator get cocoapodsValidator => context.get<CocoaPodsValidator>();
|
||||||
|
|
||||||
LocalEngineLocator get localEngineLocator => context.get<LocalEngineLocator>();
|
LocalEngineLocator get localEngineLocator => context.get<LocalEngineLocator>();
|
||||||
|
|
||||||
CocoaPods get cocoaPods => context.get<CocoaPods>();
|
|
||||||
FuchsiaArtifacts get fuchsiaArtifacts => context.get<FuchsiaArtifacts>();
|
FuchsiaArtifacts get fuchsiaArtifacts => context.get<FuchsiaArtifacts>();
|
||||||
IOSSimulatorUtils get iosSimulatorUtils => context.get<IOSSimulatorUtils>();
|
IOSSimulatorUtils get iosSimulatorUtils => context.get<IOSSimulatorUtils>();
|
||||||
|
|
||||||
XCDevice get xcdevice => context.get<XCDevice>();
|
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_sdk.dart';
|
||||||
import 'android/android_studio.dart';
|
import 'android/android_studio.dart';
|
||||||
|
import 'android/gradle_utils.dart';
|
||||||
import 'artifacts.dart';
|
import 'artifacts.dart';
|
||||||
import 'base/bot_detector.dart';
|
import 'base/bot_detector.dart';
|
||||||
import 'base/config.dart';
|
import 'base/config.dart';
|
||||||
@ -28,8 +29,10 @@ import 'cache.dart';
|
|||||||
import 'ios/ios_workflow.dart';
|
import 'ios/ios_workflow.dart';
|
||||||
import 'ios/plist_parser.dart';
|
import 'ios/plist_parser.dart';
|
||||||
import 'ios/xcodeproj.dart';
|
import 'ios/xcodeproj.dart';
|
||||||
|
import 'macos/cocoapods.dart';
|
||||||
import 'macos/xcode.dart';
|
import 'macos/xcode.dart';
|
||||||
import 'persistent_tool_state.dart';
|
import 'persistent_tool_state.dart';
|
||||||
|
import 'project.dart';
|
||||||
import 'reporting/reporting.dart';
|
import 'reporting/reporting.dart';
|
||||||
import 'version.dart';
|
import 'version.dart';
|
||||||
|
|
||||||
@ -196,3 +199,15 @@ LocalFileSystem get localFileSystem => _instance ??= LocalFileSystem(
|
|||||||
Signals.defaultExitSignals,
|
Signals.defaultExitSignals,
|
||||||
shutdownHooks,
|
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
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'package:meta/meta.dart';
|
|
||||||
|
|
||||||
import '../artifacts.dart';
|
import '../artifacts.dart';
|
||||||
import '../base/file_system.dart';
|
import '../base/file_system.dart';
|
||||||
import '../build_info.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
|
/// targetOverride: Optional parameter, if null or unspecified the default value
|
||||||
/// from xcode_backend.sh is used 'lib/main.dart'.
|
/// from xcode_backend.sh is used 'lib/main.dart'.
|
||||||
Future<void> updateGeneratedXcodeProperties({
|
Future<void> updateGeneratedXcodeProperties({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required BuildInfo buildInfo,
|
required BuildInfo buildInfo,
|
||||||
String targetOverride,
|
String? targetOverride,
|
||||||
bool useMacOSConfig = false,
|
bool useMacOSConfig = false,
|
||||||
String buildDirOverride,
|
String? buildDirOverride,
|
||||||
}) async {
|
}) async {
|
||||||
final List<String> xcodeBuildSettings = _xcodeBuildSettingsLines(
|
final List<String> xcodeBuildSettings = _xcodeBuildSettingsLines(
|
||||||
project: project,
|
project: project,
|
||||||
@ -64,8 +60,8 @@ Future<void> updateGeneratedXcodeProperties({
|
|||||||
/// for Xcode targets that need them.
|
/// for Xcode targets that need them.
|
||||||
/// See [XcodeBasedProject.generatedXcodePropertiesFile].
|
/// See [XcodeBasedProject.generatedXcodePropertiesFile].
|
||||||
void _updateGeneratedXcodePropertiesFile({
|
void _updateGeneratedXcodePropertiesFile({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required List<String> xcodeBuildSettings,
|
required List<String> xcodeBuildSettings,
|
||||||
bool useMacOSConfig = false,
|
bool useMacOSConfig = false,
|
||||||
}) {
|
}) {
|
||||||
final StringBuffer localsBuffer = StringBuffer();
|
final StringBuffer localsBuffer = StringBuffer();
|
||||||
@ -84,8 +80,8 @@ void _updateGeneratedXcodePropertiesFile({
|
|||||||
/// as flags for Flutter tools.
|
/// as flags for Flutter tools.
|
||||||
/// See [XcodeBasedProject.generatedEnvironmentVariableExportScript].
|
/// See [XcodeBasedProject.generatedEnvironmentVariableExportScript].
|
||||||
void _updateGeneratedEnvironmentVariablesScript({
|
void _updateGeneratedEnvironmentVariablesScript({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required List<String> xcodeBuildSettings,
|
required List<String> xcodeBuildSettings,
|
||||||
bool useMacOSConfig = false,
|
bool useMacOSConfig = false,
|
||||||
}) {
|
}) {
|
||||||
final StringBuffer localsBuffer = StringBuffer();
|
final StringBuffer localsBuffer = StringBuffer();
|
||||||
@ -107,21 +103,21 @@ void _updateGeneratedEnvironmentVariablesScript({
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Build name parsed and validated from build info and manifest. Used for CFBundleShortVersionString.
|
/// Build name parsed and validated from build info and manifest. Used for CFBundleShortVersionString.
|
||||||
String parsedBuildName({
|
String? parsedBuildName({
|
||||||
@required FlutterManifest manifest,
|
required FlutterManifest manifest,
|
||||||
BuildInfo buildInfo,
|
BuildInfo? buildInfo,
|
||||||
}) {
|
}) {
|
||||||
final String buildNameToParse = buildInfo?.buildName ?? manifest.buildName;
|
final String? buildNameToParse = buildInfo?.buildName ?? manifest.buildName;
|
||||||
return validatedBuildNameForPlatform(TargetPlatform.ios, buildNameToParse, globals.logger);
|
return validatedBuildNameForPlatform(TargetPlatform.ios, buildNameToParse, globals.logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build number parsed and validated from build info and manifest. Used for CFBundleVersion.
|
/// Build number parsed and validated from build info and manifest. Used for CFBundleVersion.
|
||||||
String parsedBuildNumber({
|
String? parsedBuildNumber({
|
||||||
@required FlutterManifest manifest,
|
required FlutterManifest manifest,
|
||||||
BuildInfo buildInfo,
|
BuildInfo? buildInfo,
|
||||||
}) {
|
}) {
|
||||||
String buildNumberToParse = buildInfo?.buildNumber ?? manifest.buildNumber;
|
String? buildNumberToParse = buildInfo?.buildNumber ?? manifest.buildNumber;
|
||||||
final String buildNumber = validatedBuildNumberForPlatform(
|
final String? buildNumber = validatedBuildNumberForPlatform(
|
||||||
TargetPlatform.ios,
|
TargetPlatform.ios,
|
||||||
buildNumberToParse,
|
buildNumberToParse,
|
||||||
globals.logger,
|
globals.logger,
|
||||||
@ -141,15 +137,15 @@ String parsedBuildNumber({
|
|||||||
|
|
||||||
/// List of lines of build settings. Example: 'FLUTTER_BUILD_DIR=build'
|
/// List of lines of build settings. Example: 'FLUTTER_BUILD_DIR=build'
|
||||||
List<String> _xcodeBuildSettingsLines({
|
List<String> _xcodeBuildSettingsLines({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required BuildInfo buildInfo,
|
required BuildInfo buildInfo,
|
||||||
String targetOverride,
|
String? targetOverride,
|
||||||
bool useMacOSConfig = false,
|
bool useMacOSConfig = false,
|
||||||
String buildDirOverride,
|
String? buildDirOverride,
|
||||||
}) {
|
}) {
|
||||||
final List<String> xcodeBuildSettings = <String>[];
|
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');
|
xcodeBuildSettings.add('FLUTTER_ROOT=$flutterRoot');
|
||||||
|
|
||||||
// This holds because requiresProjectRoot is true for this command
|
// 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';
|
final String buildNumber = parsedBuildNumber(manifest: project.manifest, buildInfo: buildInfo) ?? '1';
|
||||||
xcodeBuildSettings.add('FLUTTER_BUILD_NUMBER=$buildNumber');
|
xcodeBuildSettings.add('FLUTTER_BUILD_NUMBER=$buildNumber');
|
||||||
|
|
||||||
final Artifacts artifacts = globals.artifacts;
|
final Artifacts? artifacts = globals.artifacts;
|
||||||
if (artifacts is LocalEngineArtifacts) {
|
if (artifacts is LocalEngineArtifacts) {
|
||||||
final LocalEngineArtifacts localEngineArtifacts = artifacts;
|
final LocalEngineArtifacts localEngineArtifacts = artifacts;
|
||||||
final String engineOutPath = localEngineArtifacts.engineOutPath;
|
final String engineOutPath = localEngineArtifacts.engineOutPath;
|
||||||
|
@ -29,7 +29,7 @@ import '../base/net.dart';
|
|||||||
import '../base/platform.dart';
|
import '../base/platform.dart';
|
||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../build_system/targets/web.dart';
|
import '../build_system/targets/web.dart';
|
||||||
import '../bundle.dart';
|
import '../bundle_builder.dart';
|
||||||
import '../cache.dart';
|
import '../cache.dart';
|
||||||
import '../compile.dart';
|
import '../compile.dart';
|
||||||
import '../convert.dart';
|
import '../convert.dart';
|
||||||
|
@ -2,10 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
import 'package:meta/meta.dart';
|
|
||||||
import 'package:process/process.dart';
|
import 'package:process/process.dart';
|
||||||
|
|
||||||
import '../base/common.dart';
|
import '../base/common.dart';
|
||||||
@ -85,12 +82,12 @@ const Version cocoaPodsRecommendedVersion = Version.withText(1, 10, 0, '1.10.0')
|
|||||||
/// installing iOS/macOS dependencies.
|
/// installing iOS/macOS dependencies.
|
||||||
class CocoaPods {
|
class CocoaPods {
|
||||||
CocoaPods({
|
CocoaPods({
|
||||||
@required FileSystem fileSystem,
|
required FileSystem fileSystem,
|
||||||
@required ProcessManager processManager,
|
required ProcessManager processManager,
|
||||||
@required XcodeProjectInterpreter xcodeProjectInterpreter,
|
required XcodeProjectInterpreter xcodeProjectInterpreter,
|
||||||
@required Logger logger,
|
required Logger logger,
|
||||||
@required Platform platform,
|
required Platform platform,
|
||||||
@required Usage usage,
|
required Usage usage,
|
||||||
}) : _fileSystem = fileSystem,
|
}) : _fileSystem = fileSystem,
|
||||||
_processManager = processManager,
|
_processManager = processManager,
|
||||||
_xcodeProjectInterpreter = xcodeProjectInterpreter,
|
_xcodeProjectInterpreter = xcodeProjectInterpreter,
|
||||||
@ -112,33 +109,33 @@ class CocoaPods {
|
|||||||
final Logger _logger;
|
final Logger _logger;
|
||||||
final Usage _usage;
|
final Usage _usage;
|
||||||
|
|
||||||
Future<String> _versionText;
|
Future<String?>? _versionText;
|
||||||
|
|
||||||
Future<bool> get isInstalled =>
|
Future<bool> get isInstalled =>
|
||||||
_processUtils.exitsHappy(<String>['which', 'pod']);
|
_processUtils.exitsHappy(<String>['which', 'pod']);
|
||||||
|
|
||||||
Future<String> get cocoaPodsVersionText {
|
Future<String?> get cocoaPodsVersionText {
|
||||||
_versionText ??= _processUtils.run(
|
_versionText ??= _processUtils.run(
|
||||||
<String>['pod', '--version'],
|
<String>['pod', '--version'],
|
||||||
environment: <String, String>{
|
environment: <String, String>{
|
||||||
'LANG': 'en_US.UTF-8',
|
'LANG': 'en_US.UTF-8',
|
||||||
},
|
},
|
||||||
).then<String>((RunResult result) {
|
).then<String?>((RunResult result) {
|
||||||
return result.exitCode == 0 ? result.stdout.trim() : null;
|
return result.exitCode == 0 ? result.stdout.trim() : null;
|
||||||
}, onError: (dynamic _) => null);
|
}, onError: (dynamic _) => null);
|
||||||
return _versionText;
|
return _versionText!;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<CocoaPodsStatus> get evaluateCocoaPodsInstallation async {
|
Future<CocoaPodsStatus> get evaluateCocoaPodsInstallation async {
|
||||||
if (!(await isInstalled)) {
|
if (!(await isInstalled)) {
|
||||||
return CocoaPodsStatus.notInstalled;
|
return CocoaPodsStatus.notInstalled;
|
||||||
}
|
}
|
||||||
final String versionText = await cocoaPodsVersionText;
|
final String? versionText = await cocoaPodsVersionText;
|
||||||
if (versionText == null) {
|
if (versionText == null) {
|
||||||
return CocoaPodsStatus.brokenInstall;
|
return CocoaPodsStatus.brokenInstall;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
final Version installedVersion = Version.parse(versionText);
|
final Version? installedVersion = Version.parse(versionText);
|
||||||
if (installedVersion == null) {
|
if (installedVersion == null) {
|
||||||
return CocoaPodsStatus.unknownVersion;
|
return CocoaPodsStatus.unknownVersion;
|
||||||
}
|
}
|
||||||
@ -155,8 +152,8 @@ class CocoaPods {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> processPods({
|
Future<bool> processPods({
|
||||||
@required XcodeBasedProject xcodeProject,
|
required XcodeBasedProject xcodeProject,
|
||||||
@required BuildMode buildMode,
|
required BuildMode buildMode,
|
||||||
bool dependenciesChanged = true,
|
bool dependenciesChanged = true,
|
||||||
}) async {
|
}) async {
|
||||||
if (!xcodeProject.podfile.existsSync()) {
|
if (!xcodeProject.podfile.existsSync()) {
|
||||||
@ -253,7 +250,7 @@ class CocoaPods {
|
|||||||
podfileTemplateName = isSwift ? 'Podfile-ios-swift' : 'Podfile-ios-objc';
|
podfileTemplateName = isSwift ? 'Podfile-ios-swift' : 'Podfile-ios-objc';
|
||||||
}
|
}
|
||||||
final File podfileTemplate = _fileSystem.file(_fileSystem.path.join(
|
final File podfileTemplate = _fileSystem.file(_fileSystem.path.join(
|
||||||
Cache.flutterRoot,
|
Cache.flutterRoot!,
|
||||||
'packages',
|
'packages',
|
||||||
'flutter_tools',
|
'flutter_tools',
|
||||||
'templates',
|
'templates',
|
||||||
@ -391,7 +388,7 @@ class CocoaPods {
|
|||||||
//
|
//
|
||||||
// Warn the user if they are still symlinking to the framework.
|
// Warn the user if they are still symlinking to the framework.
|
||||||
final Link flutterSymlink = _fileSystem.link(_fileSystem.path.join(
|
final Link flutterSymlink = _fileSystem.link(_fileSystem.path.join(
|
||||||
(xcodeProject as IosProject).symlinks.path,
|
xcodeProject.symlinks.path,
|
||||||
'flutter',
|
'flutter',
|
||||||
));
|
));
|
||||||
if (flutterSymlink.existsSync()) {
|
if (flutterSymlink.existsSync()) {
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:xml/xml.dart';
|
import 'package:xml/xml.dart';
|
||||||
import 'package:yaml/yaml.dart';
|
import 'package:yaml/yaml.dart';
|
||||||
@ -20,7 +18,7 @@ import 'cmake.dart';
|
|||||||
import 'features.dart';
|
import 'features.dart';
|
||||||
import 'flutter_manifest.dart';
|
import 'flutter_manifest.dart';
|
||||||
import 'flutter_plugins.dart';
|
import 'flutter_plugins.dart';
|
||||||
import 'globals.dart' as globals;
|
import 'globals_null_migrated.dart' as globals;
|
||||||
import 'ios/plist_parser.dart';
|
import 'ios/plist_parser.dart';
|
||||||
import 'ios/xcode_build_settings.dart' as xcode;
|
import 'ios/xcode_build_settings.dart' as xcode;
|
||||||
import 'ios/xcodeproj.dart';
|
import 'ios/xcodeproj.dart';
|
||||||
@ -29,8 +27,8 @@ import 'template.dart';
|
|||||||
|
|
||||||
class FlutterProjectFactory {
|
class FlutterProjectFactory {
|
||||||
FlutterProjectFactory({
|
FlutterProjectFactory({
|
||||||
@required Logger logger,
|
required Logger logger,
|
||||||
@required FileSystem fileSystem,
|
required FileSystem fileSystem,
|
||||||
}) : _logger = logger,
|
}) : _logger = logger,
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
|
|
||||||
@ -89,7 +87,7 @@ class FlutterProject {
|
|||||||
|
|
||||||
/// Create a [FlutterProject] and bypass the project caching.
|
/// Create a [FlutterProject] and bypass the project caching.
|
||||||
@visibleForTesting
|
@visibleForTesting
|
||||||
static FlutterProject fromDirectoryTest(Directory directory, [Logger logger]) {
|
static FlutterProject fromDirectoryTest(Directory directory, [Logger? logger]) {
|
||||||
final FileSystem fileSystem = directory.fileSystem;
|
final FileSystem fileSystem = directory.fileSystem;
|
||||||
logger ??= BufferLogger.test();
|
logger ??= BufferLogger.test();
|
||||||
final FlutterManifest manifest = FlutterProject._readManifest(
|
final FlutterManifest manifest = FlutterProject._readManifest(
|
||||||
@ -126,14 +124,14 @@ class FlutterProject {
|
|||||||
// Don't require iOS build info, this method is only
|
// Don't require iOS build info, this method is only
|
||||||
// used during create as best-effort, use the
|
// used during create as best-effort, use the
|
||||||
// default target bundle identifier.
|
// default target bundle identifier.
|
||||||
final String bundleIdentifier = await ios.productBundleIdentifier(null);
|
final String? bundleIdentifier = await ios.productBundleIdentifier(null);
|
||||||
if (bundleIdentifier != null) {
|
if (bundleIdentifier != null) {
|
||||||
candidates.add(bundleIdentifier);
|
candidates.add(bundleIdentifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (android.existsSync()) {
|
if (android.existsSync()) {
|
||||||
final String applicationId = android.applicationId;
|
final String? applicationId = android.applicationId;
|
||||||
final String group = android.group;
|
final String? group = android.group;
|
||||||
candidates.addAll(<String>[
|
candidates.addAll(<String>[
|
||||||
if (applicationId != null)
|
if (applicationId != null)
|
||||||
applicationId,
|
applicationId,
|
||||||
@ -142,21 +140,21 @@ class FlutterProject {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
if (example.android.existsSync()) {
|
if (example.android.existsSync()) {
|
||||||
final String applicationId = example.android.applicationId;
|
final String? applicationId = example.android.applicationId;
|
||||||
if (applicationId != null) {
|
if (applicationId != null) {
|
||||||
candidates.add(applicationId);
|
candidates.add(applicationId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (example.ios.existsSync()) {
|
if (example.ios.existsSync()) {
|
||||||
final String bundleIdentifier = await example.ios.productBundleIdentifier(null);
|
final String? bundleIdentifier = await example.ios.productBundleIdentifier(null);
|
||||||
if (bundleIdentifier != null) {
|
if (bundleIdentifier != null) {
|
||||||
candidates.add(bundleIdentifier);
|
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('.')) {
|
if (packageName != null && 0 <= packageName.lastIndexOf('.')) {
|
||||||
return packageName.substring(0, packageName.lastIndexOf('.'));
|
return packageName.substring(0, packageName.lastIndexOf('.'));
|
||||||
}
|
}
|
||||||
@ -164,35 +162,35 @@ class FlutterProject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The iOS sub project of this project.
|
/// The iOS sub project of this project.
|
||||||
IosProject _ios;
|
IosProject? _ios;
|
||||||
IosProject get ios => _ios ??= IosProject.fromFlutter(this);
|
IosProject get ios => _ios ??= IosProject.fromFlutter(this);
|
||||||
|
|
||||||
/// The Android sub project of this project.
|
/// The Android sub project of this project.
|
||||||
AndroidProject _android;
|
AndroidProject? _android;
|
||||||
AndroidProject get android => _android ??= AndroidProject._(this);
|
AndroidProject get android => _android ??= AndroidProject._(this);
|
||||||
|
|
||||||
/// The web sub project of this project.
|
/// The web sub project of this project.
|
||||||
WebProject _web;
|
WebProject? _web;
|
||||||
WebProject get web => _web ??= WebProject._(this);
|
WebProject get web => _web ??= WebProject._(this);
|
||||||
|
|
||||||
/// The MacOS sub project of this project.
|
/// The MacOS sub project of this project.
|
||||||
MacOSProject _macos;
|
MacOSProject? _macos;
|
||||||
MacOSProject get macos => _macos ??= MacOSProject._(this);
|
MacOSProject get macos => _macos ??= MacOSProject._(this);
|
||||||
|
|
||||||
/// The Linux sub project of this project.
|
/// The Linux sub project of this project.
|
||||||
LinuxProject _linux;
|
LinuxProject? _linux;
|
||||||
LinuxProject get linux => _linux ??= LinuxProject._(this);
|
LinuxProject get linux => _linux ??= LinuxProject._(this);
|
||||||
|
|
||||||
/// The Windows sub project of this project.
|
/// The Windows sub project of this project.
|
||||||
WindowsProject _windows;
|
WindowsProject? _windows;
|
||||||
WindowsProject get windows => _windows ??= WindowsProject._(this);
|
WindowsProject get windows => _windows ??= WindowsProject._(this);
|
||||||
|
|
||||||
/// The Windows UWP sub project of this project.
|
/// The Windows UWP sub project of this project.
|
||||||
WindowsUwpProject _windowUwp;
|
WindowsUwpProject? _windowUwp;
|
||||||
WindowsUwpProject get windowsUwp => _windowUwp ??= WindowsUwpProject._(this);
|
WindowsUwpProject get windowsUwp => _windowUwp ??= WindowsUwpProject._(this);
|
||||||
|
|
||||||
/// The Fuchsia sub project of this project.
|
/// The Fuchsia sub project of this project.
|
||||||
FuchsiaProject _fuchsia;
|
FuchsiaProject? _fuchsia;
|
||||||
FuchsiaProject get fuchsia => _fuchsia ??= FuchsiaProject._(this);
|
FuchsiaProject get fuchsia => _fuchsia ??= FuchsiaProject._(this);
|
||||||
|
|
||||||
/// The `pubspec.yaml` file of this project.
|
/// 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 an empty [FlutterManifest], if the file does not exist.
|
||||||
/// Completes with a ToolExit on validation error.
|
/// Completes with a ToolExit on validation error.
|
||||||
static FlutterManifest _readManifest(String path, {
|
static FlutterManifest _readManifest(String path, {
|
||||||
@required Logger logger,
|
required Logger logger,
|
||||||
@required FileSystem fileSystem,
|
required FileSystem fileSystem,
|
||||||
}) {
|
}) {
|
||||||
FlutterManifest manifest;
|
FlutterManifest? manifest;
|
||||||
try {
|
try {
|
||||||
manifest = FlutterManifest.createFromPath(
|
manifest = FlutterManifest.createFromPath(
|
||||||
path,
|
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
|
/// Returns a json encoded string containing the [appName], [version], and [buildNumber] that is used to generate version.json
|
||||||
String getVersionInfo() {
|
String getVersionInfo() {
|
||||||
final String buildName = manifest.buildName;
|
final String? buildName = manifest.buildName;
|
||||||
final String buildNumber = manifest.buildNumber;
|
final String? buildNumber = manifest.buildNumber;
|
||||||
final Map<String, String> versionFileJson = <String, String>{
|
final Map<String, String> versionFileJson = <String, String>{
|
||||||
'app_name': manifest.appName,
|
'app_name': manifest.appName,
|
||||||
if (buildName != null)
|
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
|
/// The product bundle identifier of the host app, or null if not set or if
|
||||||
/// iOS tooling needed to read it is not installed.
|
/// iOS tooling needed to read it is not installed.
|
||||||
Future<String> productBundleIdentifier(BuildInfo buildInfo) async {
|
Future<String?> productBundleIdentifier(BuildInfo? buildInfo) async {
|
||||||
if (!existsSync()) {
|
if (!existsSync()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return _productBundleIdentifier ??= await _parseProductBundleIdentifier(buildInfo);
|
return _productBundleIdentifier ??= await _parseProductBundleIdentifier(buildInfo);
|
||||||
}
|
}
|
||||||
String _productBundleIdentifier;
|
String? _productBundleIdentifier;
|
||||||
|
|
||||||
Future<String> _parseProductBundleIdentifier(BuildInfo buildInfo) async {
|
Future<String?> _parseProductBundleIdentifier(BuildInfo? buildInfo) async {
|
||||||
String fromPlist;
|
String? fromPlist;
|
||||||
final File defaultInfoPlist = defaultHostInfoPlist;
|
final File defaultInfoPlist = defaultHostInfoPlist;
|
||||||
// Users can change the location of the Info.plist.
|
// Users can change the location of the Info.plist.
|
||||||
// Try parsing the default, first.
|
// Try parsing the default, first.
|
||||||
@ -561,7 +559,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
|
|||||||
return fromPlist;
|
return fromPlist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final Map<String, String> allBuildSettings = await buildSettingsForBuildInfo(buildInfo);
|
final Map<String, String>? allBuildSettings = await buildSettingsForBuildInfo(buildInfo);
|
||||||
if (allBuildSettings != null) {
|
if (allBuildSettings != null) {
|
||||||
if (fromPlist != null) {
|
if (fromPlist != null) {
|
||||||
// Perform variable substitution using build settings.
|
// 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
|
// or companion watchOS projects. However, on non-macOS platforms this is
|
||||||
// only used for display purposes and to regenerate organization names, so
|
// only used for display purposes and to regenerate organization names, so
|
||||||
// best-effort is probably fine.
|
// 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)) {
|
if (fromPbxproj != null && (fromPlist == null || fromPlist == _productBundleIdVariable)) {
|
||||||
return fromPbxproj;
|
return fromPbxproj;
|
||||||
}
|
}
|
||||||
@ -585,22 +583,22 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The bundle name of the host app, `My App.app`.
|
/// The bundle name of the host app, `My App.app`.
|
||||||
Future<String> hostAppBundleName(BuildInfo buildInfo) async {
|
Future<String?> hostAppBundleName(BuildInfo buildInfo) async {
|
||||||
if (!existsSync()) {
|
if (!existsSync()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return _hostAppBundleName ??= await _parseHostAppBundleName(buildInfo);
|
return _hostAppBundleName ??= await _parseHostAppBundleName(buildInfo);
|
||||||
}
|
}
|
||||||
String _hostAppBundleName;
|
String? _hostAppBundleName;
|
||||||
|
|
||||||
Future<String> _parseHostAppBundleName(BuildInfo buildInfo) async {
|
Future<String> _parseHostAppBundleName(BuildInfo buildInfo) async {
|
||||||
// The product name and bundle name are derived from the display name, which the user
|
// 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.
|
// is instructed to change in Xcode as part of deploying to the App Store.
|
||||||
// https://flutter.dev/docs/deployment/ios#review-xcode-project-settings
|
// 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.
|
// The only source of truth for the name is Xcode's interpretation of the build settings.
|
||||||
String productName;
|
String? productName;
|
||||||
if (globals.xcodeProjectInterpreter.isInstalled) {
|
if (globals.xcodeProjectInterpreter?.isInstalled == true) {
|
||||||
final Map<String, String> xcodeBuildSettings = await buildSettingsForBuildInfo(buildInfo);
|
final Map<String, String>? xcodeBuildSettings = await buildSettingsForBuildInfo(buildInfo);
|
||||||
if (xcodeBuildSettings != null) {
|
if (xcodeBuildSettings != null) {
|
||||||
productName = xcodeBuildSettings['FULL_PRODUCT_NAME'];
|
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.
|
/// The build settings for the host app of this project, as a detached map.
|
||||||
///
|
///
|
||||||
/// Returns null, if iOS tooling is unavailable.
|
/// 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()) {
|
if (!existsSync()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final XcodeProjectInfo info = await projectInfo();
|
final XcodeProjectInfo? info = await projectInfo();
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String scheme = info.schemeFor(buildInfo);
|
final String? scheme = info.schemeFor(buildInfo);
|
||||||
if (scheme == null) {
|
if (scheme == null) {
|
||||||
info.reportFlavorNotFoundAndExit();
|
info.reportFlavorNotFoundAndExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
final String configuration = (await projectInfo()).buildConfigurationFor(
|
final String? configuration = (await projectInfo())?.buildConfigurationFor(
|
||||||
buildInfo,
|
buildInfo,
|
||||||
scheme,
|
scheme,
|
||||||
);
|
);
|
||||||
final XcodeProjectBuildContext buildContext = XcodeProjectBuildContext(environmentType: environmentType, scheme: scheme, configuration: configuration);
|
final XcodeProjectBuildContext buildContext = XcodeProjectBuildContext(environmentType: environmentType, scheme: scheme, configuration: configuration);
|
||||||
if (_buildSettingsByBuildContext[buildContext] == null) {
|
final Map<String, String>? currentBuildSettings = _buildSettingsByBuildContext[buildContext];
|
||||||
final Map<String, String> calculatedBuildSettings = await _xcodeProjectBuildSettings(buildContext);
|
if (currentBuildSettings == null) {
|
||||||
|
final Map<String, String>? calculatedBuildSettings = await _xcodeProjectBuildSettings(buildContext);
|
||||||
if (calculatedBuildSettings != null) {
|
if (calculatedBuildSettings != null) {
|
||||||
_buildSettingsByBuildContext[buildContext] = calculatedBuildSettings;
|
_buildSettingsByBuildContext[buildContext] = calculatedBuildSettings;
|
||||||
}
|
}
|
||||||
@ -644,17 +643,17 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
|
|||||||
|
|
||||||
final Map<XcodeProjectBuildContext, Map<String, String>> _buildSettingsByBuildContext = <XcodeProjectBuildContext, Map<String, String>>{};
|
final Map<XcodeProjectBuildContext, Map<String, String>> _buildSettingsByBuildContext = <XcodeProjectBuildContext, Map<String, String>>{};
|
||||||
|
|
||||||
Future<XcodeProjectInfo> projectInfo() async {
|
Future<XcodeProjectInfo?> projectInfo() async {
|
||||||
final XcodeProjectInterpreter xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
|
final XcodeProjectInterpreter? xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
|
||||||
if (!xcodeProject.existsSync() || xcodeProjectInterpreter == null || !xcodeProjectInterpreter.isInstalled) {
|
if (!xcodeProject.existsSync() || xcodeProjectInterpreter == null || !xcodeProjectInterpreter.isInstalled) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return _projectInfo ??= await xcodeProjectInterpreter.getInfo(hostAppRoot.path);
|
return _projectInfo ??= await xcodeProjectInterpreter.getInfo(hostAppRoot.path);
|
||||||
}
|
}
|
||||||
XcodeProjectInfo _projectInfo;
|
XcodeProjectInfo? _projectInfo;
|
||||||
|
|
||||||
Future<Map<String, String>> _xcodeProjectBuildSettings(XcodeProjectBuildContext buildContext) async {
|
Future<Map<String, String>?> _xcodeProjectBuildSettings(XcodeProjectBuildContext buildContext) async {
|
||||||
final XcodeProjectInterpreter xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
|
final XcodeProjectInterpreter? xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
|
||||||
if (xcodeProjectInterpreter == null || !xcodeProjectInterpreter.isInstalled) {
|
if (xcodeProjectInterpreter == null || !xcodeProjectInterpreter.isInstalled) {
|
||||||
return null;
|
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.
|
/// Check if one the [targets] of the project is a watchOS companion app target.
|
||||||
Future<bool> containsWatchCompanion(List<String> targets, BuildInfo buildInfo) async {
|
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.
|
// A bundle identifier is required for a companion app.
|
||||||
if (bundleIdentifier == null) {
|
if (bundleIdentifier == null) {
|
||||||
return false;
|
return false;
|
||||||
@ -748,7 +747,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
|
|||||||
// However, cocoapods will run before that script and requires something
|
// However, cocoapods will run before that script and requires something
|
||||||
// to be in this location.
|
// to be in this location.
|
||||||
final Directory framework = globals.fs.directory(
|
final Directory framework = globals.fs.directory(
|
||||||
globals.artifacts.getArtifactPath(
|
globals.artifacts?.getArtifactPath(
|
||||||
Artifact.flutterXcframework,
|
Artifact.flutterXcframework,
|
||||||
platform: TargetPlatform.ios,
|
platform: TargetPlatform.ios,
|
||||||
mode: mode,
|
mode: mode,
|
||||||
@ -876,7 +875,7 @@ class AndroidProject extends FlutterProjectPlatform {
|
|||||||
|
|
||||||
/// Returns true if the current version of the Gradle plugin is supported.
|
/// Returns true if the current version of the Gradle plugin is supported.
|
||||||
bool get isSupportedVersion => _isSupportedVersion ??= _computeSupportedVersion();
|
bool get isSupportedVersion => _isSupportedVersion ??= _computeSupportedVersion();
|
||||||
bool _isSupportedVersion;
|
bool? _isSupportedVersion;
|
||||||
|
|
||||||
bool _computeSupportedVersion() {
|
bool _computeSupportedVersion() {
|
||||||
final FileSystem fileSystem = hostAppGradleRoot.fileSystem;
|
final FileSystem fileSystem = hostAppGradleRoot.fileSystem;
|
||||||
@ -927,12 +926,12 @@ class AndroidProject extends FlutterProjectPlatform {
|
|||||||
return hostAppGradleRoot.childFile('build.gradle').existsSync();
|
return hostAppGradleRoot.childFile('build.gradle').existsSync();
|
||||||
}
|
}
|
||||||
|
|
||||||
String get applicationId {
|
String? get applicationId {
|
||||||
final File gradleFile = hostAppGradleRoot.childDirectory('app').childFile('build.gradle');
|
final File gradleFile = hostAppGradleRoot.childDirectory('app').childFile('build.gradle');
|
||||||
return _firstMatchInFile(gradleFile, _applicationIdPattern)?.group(1);
|
return _firstMatchInFile(gradleFile, _applicationIdPattern)?.group(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
String get group {
|
String? get group {
|
||||||
final File gradleFile = hostAppGradleRoot.childFile('build.gradle');
|
final File gradleFile = hostAppGradleRoot.childFile('build.gradle');
|
||||||
return _firstMatchInFile(gradleFile, _groupPattern)?.group(1);
|
return _firstMatchInFile(gradleFile, _groupPattern)?.group(1);
|
||||||
}
|
}
|
||||||
@ -993,7 +992,7 @@ to migrate your project.
|
|||||||
'library_new_embedding',
|
'library_new_embedding',
|
||||||
), ephemeralDirectory);
|
), ephemeralDirectory);
|
||||||
await _overwriteFromTemplate(globals.fs.path.join('module', 'android', 'gradle'), 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 {
|
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.');
|
'Please ensure that you have read permission to this file and try again.');
|
||||||
}
|
}
|
||||||
for (final XmlElement metaData in document.findAllElements('meta-data')) {
|
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') {
|
if (name == 'flutterEmbedding') {
|
||||||
final String embeddingVersionString = metaData.getAttribute('android:value');
|
final String? embeddingVersionString = metaData.getAttribute('android:value');
|
||||||
if (embeddingVersionString == '1') {
|
if (embeddingVersionString == '1') {
|
||||||
return AndroidEmbeddingVersion.v1;
|
return AndroidEmbeddingVersion.v1;
|
||||||
}
|
}
|
||||||
@ -1102,12 +1101,12 @@ void _deleteIfExistsSync(Directory directory) {
|
|||||||
/// Returns the first line-based match for [regExp] in [file].
|
/// Returns the first line-based match for [regExp] in [file].
|
||||||
///
|
///
|
||||||
/// Assumes UTF8 encoding.
|
/// Assumes UTF8 encoding.
|
||||||
Match _firstMatchInFile(File file, RegExp regExp) {
|
Match? _firstMatchInFile(File file, RegExp regExp) {
|
||||||
if (!file.existsSync()) {
|
if (!file.existsSync()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for (final String line in file.readAsLinesSync()) {
|
for (final String line in file.readAsLinesSync()) {
|
||||||
final Match match = regExp.firstMatch(line);
|
final Match? match = regExp.firstMatch(line);
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
@ -1254,20 +1253,20 @@ class WindowsUwpProject extends WindowsProject {
|
|||||||
File get runnerCmakeFile => _editableDirectory.childDirectory('runner_uwp').childFile('CMakeLists.txt');
|
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.
|
/// 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.
|
/// Retrieve the GUID of the UWP package.
|
||||||
String get packageGuid => _packageGuid ??= getCmakePackageGuid(runnerCmakeFile);
|
String? get packageGuid => _packageGuid ??= getCmakePackageGuid(runnerCmakeFile);
|
||||||
String _packageGuid;
|
String? _packageGuid;
|
||||||
|
|
||||||
File get appManifest => _editableDirectory.childDirectory('runner_uwp').childFile('appxmanifest.in');
|
File get appManifest => _editableDirectory.childDirectory('runner_uwp').childFile('appxmanifest.in');
|
||||||
|
|
||||||
String get packageVersion => _packageVersion ??= parseAppVersion(this);
|
String? get packageVersion => _packageVersion ??= parseAppVersion(this);
|
||||||
String _packageVersion;
|
String? _packageVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
@visibleForTesting
|
@visibleForTesting
|
||||||
String parseAppVersion(WindowsUwpProject project) {
|
String? parseAppVersion(WindowsUwpProject project) {
|
||||||
final File appManifestFile = project.appManifest;
|
final File appManifestFile = project.appManifest;
|
||||||
if (!appManifestFile.existsSync()) {
|
if (!appManifestFile.existsSync()) {
|
||||||
return null;
|
return null;
|
||||||
@ -1329,7 +1328,7 @@ class LinuxProject extends FlutterProjectPlatform implements CmakeBasedProject {
|
|||||||
|
|
||||||
Future<void> ensureReadyForPlatformSpecificTooling() async {}
|
Future<void> ensureReadyForPlatformSpecificTooling() async {}
|
||||||
|
|
||||||
String get applicationId {
|
String? get applicationId {
|
||||||
return _firstMatchInFile(cmakeFile, _applicationIdPattern)?.group(1);
|
return _firstMatchInFile(cmakeFile, _applicationIdPattern)?.group(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1340,13 +1339,13 @@ class FuchsiaProject {
|
|||||||
|
|
||||||
final FlutterProject project;
|
final FlutterProject project;
|
||||||
|
|
||||||
Directory _editableHostAppDirectory;
|
Directory? _editableHostAppDirectory;
|
||||||
Directory get editableHostAppDirectory =>
|
Directory get editableHostAppDirectory =>
|
||||||
_editableHostAppDirectory ??= project.directory.childDirectory('fuchsia');
|
_editableHostAppDirectory ??= project.directory.childDirectory('fuchsia');
|
||||||
|
|
||||||
bool existsSync() => editableHostAppDirectory.existsSync();
|
bool existsSync() => editableHostAppDirectory.existsSync();
|
||||||
|
|
||||||
Directory _meta;
|
Directory? _meta;
|
||||||
Directory get meta =>
|
Directory get meta =>
|
||||||
_meta ??= editableHostAppDirectory.childDirectory('meta');
|
_meta ??= editableHostAppDirectory.childDirectory('meta');
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import '../base/logger.dart';
|
|||||||
import '../base/os.dart';
|
import '../base/os.dart';
|
||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../bundle.dart';
|
import '../bundle.dart';
|
||||||
|
import '../bundle_builder.dart';
|
||||||
import '../desktop_device.dart';
|
import '../desktop_device.dart';
|
||||||
import '../devfs.dart';
|
import '../devfs.dart';
|
||||||
import '../device.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_info.dart';
|
||||||
import 'package:flutter_tools/src/build_system/build_system.dart';
|
import 'package:flutter_tools/src/build_system/build_system.dart';
|
||||||
import 'package:flutter_tools/src/bundle.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/cache.dart';
|
||||||
import 'package:flutter_tools/src/commands/build_bundle.dart';
|
import 'package:flutter_tools/src/commands/build_bundle.dart';
|
||||||
import 'package:flutter_tools/src/features.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
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'package:file/memory.dart';
|
import 'package:file/memory.dart';
|
||||||
import 'package:flutter_tools/src/android/gradle.dart';
|
import 'package:flutter_tools/src/android/gradle.dart';
|
||||||
import 'package:flutter_tools/src/base/file_system.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';
|
import '../../src/common.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
FileSystem fileSystem;
|
late FileSystem fileSystem;
|
||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
fileSystem = MemoryFileSystem.test();
|
fileSystem = MemoryFileSystem.test();
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'package:file/memory.dart';
|
import 'package:file/memory.dart';
|
||||||
import 'package:flutter_tools/src/android/gradle_utils.dart';
|
import 'package:flutter_tools/src/android/gradle_utils.dart';
|
||||||
import 'package:flutter_tools/src/base/file_system.dart';
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
@ -17,9 +15,9 @@ import '../../src/fakes.dart';
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group('injectGradleWrapperIfNeeded', () {
|
group('injectGradleWrapperIfNeeded', () {
|
||||||
MemoryFileSystem fileSystem;
|
late MemoryFileSystem fileSystem;
|
||||||
Directory gradleWrapperDirectory;
|
late Directory gradleWrapperDirectory;
|
||||||
GradleUtils gradleUtils;
|
late GradleUtils gradleUtils;
|
||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
fileSystem = MemoryFileSystem.test();
|
fileSystem = MemoryFileSystem.test();
|
||||||
|
@ -2,13 +2,10 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
import 'package:file/memory.dart';
|
import 'package:file/memory.dart';
|
||||||
import 'package:flutter_tools/src/platform_plugins.dart';
|
import 'package:flutter_tools/src/platform_plugins.dart';
|
||||||
|
|
||||||
|
|
||||||
import '../src/common.dart';
|
import '../src/common.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
@ -11,7 +11,7 @@ import 'package:file/memory.dart';
|
|||||||
import 'package:flutter_tools/src/asset.dart';
|
import 'package:flutter_tools/src/asset.dart';
|
||||||
import 'package:flutter_tools/src/base/file_system.dart';
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
import 'package:flutter_tools/src/base/platform.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/devfs.dart';
|
||||||
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
|
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/base/file_system.dart';
|
||||||
import 'package:flutter_tools/src/build_info.dart';
|
import 'package:flutter_tools/src/build_info.dart';
|
||||||
import 'package:flutter_tools/src/build_system/build_system.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/globals_null_migrated.dart' as globals;
|
||||||
import 'package:flutter_tools/src/project.dart';
|
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_info.dart';
|
||||||
import 'package:flutter_tools/src/build_system/build_system.dart';
|
import 'package:flutter_tools/src/build_system/build_system.dart';
|
||||||
import 'package:flutter_tools/src/bundle.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/convert.dart';
|
||||||
import 'package:flutter_tools/src/custom_devices/custom_device.dart';
|
import 'package:flutter_tools/src/custom_devices/custom_device.dart';
|
||||||
import 'package:flutter_tools/src/custom_devices/custom_device_config.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
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'package:flutter_tools/src/android/android_builder.dart';
|
import 'package:flutter_tools/src/android/android_builder.dart';
|
||||||
import 'package:flutter_tools/src/base/file_system.dart';
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
import 'package:flutter_tools/src/build_info.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/globals_null_migrated.dart' as globals;
|
||||||
import 'package:flutter_tools/src/project.dart';
|
import 'package:flutter_tools/src/project.dart';
|
||||||
|
|
||||||
import 'package:meta/meta.dart';
|
|
||||||
|
|
||||||
/// A fake implementation of [AndroidBuilder].
|
/// A fake implementation of [AndroidBuilder].
|
||||||
class FakeAndroidBuilder implements AndroidBuilder {
|
class FakeAndroidBuilder implements AndroidBuilder {
|
||||||
@override
|
@override
|
||||||
Future<void> buildAar({
|
Future<void> buildAar({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required Set<AndroidBuildInfo> androidBuildInfo,
|
required Set<AndroidBuildInfo> androidBuildInfo,
|
||||||
@required String target,
|
required String target,
|
||||||
@required String outputDirectoryPath,
|
String? outputDirectoryPath,
|
||||||
@required String buildNumber,
|
required String buildNumber,
|
||||||
}) async {}
|
}) async {}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> buildApk({
|
Future<void> buildApk({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required AndroidBuildInfo androidBuildInfo,
|
required AndroidBuildInfo androidBuildInfo,
|
||||||
@required String target,
|
required String target,
|
||||||
}) async {}
|
}) async {}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> buildAab({
|
Future<void> buildAab({
|
||||||
@required FlutterProject project,
|
required FlutterProject project,
|
||||||
@required AndroidBuildInfo androidBuildInfo,
|
required AndroidBuildInfo androidBuildInfo,
|
||||||
@required String target,
|
required String target,
|
||||||
bool validateDeferredComponents = true,
|
bool validateDeferredComponents = true,
|
||||||
bool deferredComponentsEnabled = false,
|
bool deferredComponentsEnabled = false,
|
||||||
}) async {}
|
}) async {}
|
||||||
|
Loading…
Reference in New Issue
Block a user