mirror of
https://github.com/flutter/flutter
synced 2024-08-27 03:50:33 +00:00
[macos] add flavor options to commands in the flutter_tool
(#118421)
* Add new macos target configured for flavors * Rename Free App copy-Info.plist to Free App Info.plist * Remove bogus entitlements * Remove Generated.xcconfig * Audit project.pbxproj * Remove unused configs * share one info.plist * Modify scheme so that paid app works * Codesign automatic * Pipe flavor as scheme into xcodebuild * Ignore incoming flavor string * pipe flavor for flutter run to work * Add devicelab tests * Error if host and target device are same for flutter install desktop * Avoid bang (!) by promoting a local. Co-authored-by: Jenn Magder <magder@google.com> * Add supportsInstall property * Override in test classes * Add install test on macOS * Refactor application_package and add tests for package directory Co-authored-by: a-wallen <stephenwallen@google.com> Co-authored-by: Jenn Magder <magder@google.com>
This commit is contained in:
parent
09bd0f6613
commit
73096fd96e
14
.ci.yaml
14
.ci.yaml
|
@ -2668,6 +2668,20 @@ targets:
|
||||||
- bin/**
|
- bin/**
|
||||||
- .ci.yaml
|
- .ci.yaml
|
||||||
|
|
||||||
|
- name: Mac flavors_test_macos
|
||||||
|
bringup: true
|
||||||
|
recipe: devicelab/devicelab_drone
|
||||||
|
timeout: 60
|
||||||
|
properties:
|
||||||
|
dependencies: >-
|
||||||
|
[
|
||||||
|
{"dependency": "xcode", "version": "14a5294e"},
|
||||||
|
{"dependency": "gems", "version": "v3.3.14"}
|
||||||
|
]
|
||||||
|
tags: >
|
||||||
|
["devicelab", "hostonly", "mac"]
|
||||||
|
task_name: flavors_test_macos
|
||||||
|
|
||||||
- name: Mac flutter_gallery_macos__compile
|
- name: Mac flutter_gallery_macos__compile
|
||||||
presubmit: false
|
presubmit: false
|
||||||
recipe: devicelab/devicelab_drone
|
recipe: devicelab/devicelab_drone
|
||||||
|
|
|
@ -220,6 +220,7 @@
|
||||||
/dev/devicelab/bin/tasks/complex_layout_win_desktop__start_up.dart @yaakovschectman @flutter/desktop
|
/dev/devicelab/bin/tasks/complex_layout_win_desktop__start_up.dart @yaakovschectman @flutter/desktop
|
||||||
/dev/devicelab/bin/tasks/dart_plugin_registry_test.dart @stuartmorgan @flutter/plugin
|
/dev/devicelab/bin/tasks/dart_plugin_registry_test.dart @stuartmorgan @flutter/plugin
|
||||||
/dev/devicelab/bin/tasks/entrypoint_dart_registrant.dart @aaclarke @flutter/plugin
|
/dev/devicelab/bin/tasks/entrypoint_dart_registrant.dart @aaclarke @flutter/plugin
|
||||||
|
/dev/devicelab/bin/tasks/flavors_test_macos.dart @a-wallen @flutter/desktop
|
||||||
/dev/devicelab/bin/tasks/flutter_gallery_macos__compile.dart @a-wallen @flutter/desktop
|
/dev/devicelab/bin/tasks/flutter_gallery_macos__compile.dart @a-wallen @flutter/desktop
|
||||||
/dev/devicelab/bin/tasks/flutter_gallery_macos__start_up.dart @a-wallen @flutter/desktop
|
/dev/devicelab/bin/tasks/flutter_gallery_macos__start_up.dart @a-wallen @flutter/desktop
|
||||||
/dev/devicelab/bin/tasks/flutter_gallery_win_desktop__compile.dart @yaakovschectman @flutter/desktop
|
/dev/devicelab/bin/tasks/flutter_gallery_win_desktop__compile.dart @yaakovschectman @flutter/desktop
|
||||||
|
|
39
dev/devicelab/bin/tasks/flavors_test_macos.dart
Normal file
39
dev/devicelab/bin/tasks/flavors_test_macos.dart
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
import 'package:flutter_devicelab/framework/devices.dart';
|
||||||
|
import 'package:flutter_devicelab/framework/framework.dart';
|
||||||
|
import 'package:flutter_devicelab/framework/task_result.dart';
|
||||||
|
import 'package:flutter_devicelab/framework/utils.dart';
|
||||||
|
import 'package:flutter_devicelab/tasks/integration_tests.dart';
|
||||||
|
|
||||||
|
Future<void> main() async {
|
||||||
|
deviceOperatingSystem = DeviceOperatingSystem.macos;
|
||||||
|
await task(() async {
|
||||||
|
await createFlavorsTest().call();
|
||||||
|
await createIntegrationTestFlavorsTest().call();
|
||||||
|
|
||||||
|
await inDirectory('${flutterDirectory.path}/dev/integration_tests/flavors', () async {
|
||||||
|
final StringBuffer stderr = StringBuffer();
|
||||||
|
|
||||||
|
await evalFlutter(
|
||||||
|
'install',
|
||||||
|
canFail: true,
|
||||||
|
stderr: stderr,
|
||||||
|
options: <String>[
|
||||||
|
'--d', 'macos',
|
||||||
|
'--flavor', 'free'
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final String stderrString = stderr.toString();
|
||||||
|
if (!stderrString.contains('Host and target are the same. Nothing to install.')) {
|
||||||
|
print(stderrString);
|
||||||
|
return TaskResult.failure('Installing a macOS app on macOS should no-op');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return TaskResult.success(null);
|
||||||
|
});
|
||||||
|
}
|
|
@ -651,6 +651,7 @@
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.flavors.free;
|
PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.flavors.free;
|
||||||
|
PRODUCT_FLAVOR = free;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
@ -673,6 +674,7 @@
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.flavors.free;
|
PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.flavors.free;
|
||||||
|
PRODUCT_FLAVOR = free;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
|
|
|
@ -17,6 +17,32 @@ EchoError() {
|
||||||
echo "$@" 1>&2
|
echo "$@" 1>&2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParseFlutterBuildMode() {
|
||||||
|
# Use FLUTTER_BUILD_MODE if it's set, otherwise use the Xcode build configuration name
|
||||||
|
# This means that if someone wants to use an Xcode build config other than Debug/Profile/Release,
|
||||||
|
# they _must_ set FLUTTER_BUILD_MODE so we know what type of artifact to build.
|
||||||
|
local build_mode="$(echo "${FLUTTER_BUILD_MODE:-${CONFIGURATION}}" | tr "[:upper:]" "[:lower:]")"
|
||||||
|
|
||||||
|
case "$build_mode" in
|
||||||
|
*release*) build_mode="release";;
|
||||||
|
*profile*) build_mode="profile";;
|
||||||
|
*debug*) build_mode="debug";;
|
||||||
|
*)
|
||||||
|
EchoError "========================================================================"
|
||||||
|
EchoError "ERROR: Unknown FLUTTER_BUILD_MODE: ${build_mode}."
|
||||||
|
EchoError "Valid values are 'Debug', 'Profile', or 'Release' (case insensitive)."
|
||||||
|
EchoError "This is controlled by the FLUTTER_BUILD_MODE environment variable."
|
||||||
|
EchoError "If that is not set, the CONFIGURATION environment variable is used."
|
||||||
|
EchoError ""
|
||||||
|
EchoError "You can fix this by either adding an appropriately named build"
|
||||||
|
EchoError "configuration, or adding an appropriate value for FLUTTER_BUILD_MODE to the"
|
||||||
|
EchoError ".xcconfig file for the current build configuration (${CONFIGURATION})."
|
||||||
|
EchoError "========================================================================"
|
||||||
|
exit -1;;
|
||||||
|
esac
|
||||||
|
echo "${build_mode}"
|
||||||
|
}
|
||||||
|
|
||||||
BuildApp() {
|
BuildApp() {
|
||||||
# Set the working directory to the project root
|
# Set the working directory to the project root
|
||||||
local project_path="${SOURCE_ROOT}/.."
|
local project_path="${SOURCE_ROOT}/.."
|
||||||
|
@ -28,8 +54,10 @@ BuildApp() {
|
||||||
target_path="${FLUTTER_TARGET}"
|
target_path="${FLUTTER_TARGET}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Set the build mode
|
# Use FLUTTER_BUILD_MODE if it's set, otherwise use the Xcode build configuration name
|
||||||
local build_mode="$(echo "${FLUTTER_BUILD_MODE:-${CONFIGURATION}}" | tr "[:upper:]" "[:lower:]")"
|
# This means that if someone wants to use an Xcode build config other than Debug/Profile/Release,
|
||||||
|
# they _must_ set FLUTTER_BUILD_MODE so we know what type of artifact to build.
|
||||||
|
local build_mode="$(ParseFlutterBuildMode)"
|
||||||
|
|
||||||
if [[ -n "$LOCAL_ENGINE" ]]; then
|
if [[ -n "$LOCAL_ENGINE" ]]; then
|
||||||
if [[ $(echo "$LOCAL_ENGINE" | tr "[:upper:]" "[:lower:]") != *"$build_mode"* ]]; then
|
if [[ $(echo "$LOCAL_ENGINE" | tr "[:upper:]" "[:lower:]") != *"$build_mode"* ]]; then
|
||||||
|
|
|
@ -50,6 +50,11 @@ class InstallCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
throwToolExit('No target device found');
|
throwToolExit('No target device found');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!device!.supportsInstall) {
|
||||||
|
throwToolExit('Host and target are the same. Nothing to install.');
|
||||||
|
}
|
||||||
|
|
||||||
if (userIdentifier != null && device is! AndroidDevice) {
|
if (userIdentifier != null && device is! AndroidDevice) {
|
||||||
throwToolExit('--${FlutterOptions.kDeviceUser} is only supported for Android');
|
throwToolExit('--${FlutterOptions.kDeviceUser} is only supported for Android');
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,9 @@ abstract class DesktopDevice extends Device {
|
||||||
@override
|
@override
|
||||||
void clearLogs() {}
|
void clearLogs() {}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get supportsInstall => false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<LaunchResult> startApp(
|
Future<LaunchResult> startApp(
|
||||||
ApplicationPackage package, {
|
ApplicationPackage package, {
|
||||||
|
@ -123,9 +126,9 @@ abstract class DesktopDevice extends Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the executable is locatable.
|
// Ensure that the executable is locatable.
|
||||||
final BuildMode buildMode = debuggingOptions.buildInfo.mode;
|
final BuildInfo buildInfo = debuggingOptions.buildInfo;
|
||||||
final bool traceStartup = platformArgs['trace-startup'] as bool? ?? false;
|
final bool traceStartup = platformArgs['trace-startup'] as bool? ?? false;
|
||||||
final String? executable = executablePathForDevice(package, buildMode);
|
final String? executable = executablePathForDevice(package, buildInfo);
|
||||||
if (executable == null) {
|
if (executable == null) {
|
||||||
_logger.printError('Unable to find executable to run');
|
_logger.printError('Unable to find executable to run');
|
||||||
return LaunchResult.failed();
|
return LaunchResult.failed();
|
||||||
|
@ -161,7 +164,7 @@ abstract class DesktopDevice extends Device {
|
||||||
try {
|
try {
|
||||||
final Uri? observatoryUri = await observatoryDiscovery.uri;
|
final Uri? observatoryUri = await observatoryDiscovery.uri;
|
||||||
if (observatoryUri != null) {
|
if (observatoryUri != null) {
|
||||||
onAttached(package, buildMode, process);
|
onAttached(package, buildInfo, process);
|
||||||
return LaunchResult.succeeded(observatoryUri: observatoryUri);
|
return LaunchResult.succeeded(observatoryUri: observatoryUri);
|
||||||
}
|
}
|
||||||
_logger.printError(
|
_logger.printError(
|
||||||
|
@ -203,11 +206,11 @@ abstract class DesktopDevice extends Device {
|
||||||
|
|
||||||
/// Returns the path to the executable to run for [package] on this device for
|
/// Returns the path to the executable to run for [package] on this device for
|
||||||
/// the given [buildMode].
|
/// the given [buildMode].
|
||||||
String? executablePathForDevice(ApplicationPackage package, BuildMode buildMode);
|
String? executablePathForDevice(ApplicationPackage package, BuildInfo buildInfo);
|
||||||
|
|
||||||
/// Called after a process is attached, allowing any device-specific extra
|
/// Called after a process is attached, allowing any device-specific extra
|
||||||
/// steps to be run.
|
/// steps to be run.
|
||||||
void onAttached(ApplicationPackage package, BuildMode buildMode, Process process) {}
|
void onAttached(ApplicationPackage package, BuildInfo buildInfo, Process process) {}
|
||||||
|
|
||||||
/// Computes a set of environment variables used to pass debugging information
|
/// Computes a set of environment variables used to pass debugging information
|
||||||
/// to the engine without interfering with application level command line
|
/// to the engine without interfering with application level command line
|
||||||
|
|
|
@ -579,6 +579,10 @@ abstract class Device {
|
||||||
/// Whether the device supports the '--fast-start' development mode.
|
/// Whether the device supports the '--fast-start' development mode.
|
||||||
bool get supportsFastStart => false;
|
bool get supportsFastStart => false;
|
||||||
|
|
||||||
|
/// Whether this device supports the installation of a flutter app via
|
||||||
|
/// `flutter install`.
|
||||||
|
bool get supportsInstall => true;
|
||||||
|
|
||||||
/// Stop an app package on the current device.
|
/// Stop an app package on the current device.
|
||||||
///
|
///
|
||||||
/// Specify [userIdentifier] to stop app installed to a profile (Android only).
|
/// Specify [userIdentifier] to stop app installed to a profile (Android only).
|
||||||
|
|
|
@ -70,8 +70,8 @@ class LinuxDevice extends DesktopDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String executablePathForDevice(covariant LinuxApp package, BuildMode buildMode) {
|
String executablePathForDevice(covariant LinuxApp package, BuildInfo buildInfo) {
|
||||||
return package.executable(buildMode);
|
return package.executable(buildInfo.mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,9 +106,9 @@ abstract class MacOSApp extends ApplicationPackage {
|
||||||
@override
|
@override
|
||||||
String get displayName => id;
|
String get displayName => id;
|
||||||
|
|
||||||
String? applicationBundle(BuildMode buildMode);
|
String? applicationBundle(BuildInfo buildInfo);
|
||||||
|
|
||||||
String? executable(BuildMode buildMode);
|
String? executable(BuildInfo buildInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
class PrebuiltMacOSApp extends MacOSApp implements PrebuiltApplicationPackage {
|
class PrebuiltMacOSApp extends MacOSApp implements PrebuiltApplicationPackage {
|
||||||
|
@ -135,10 +135,10 @@ class PrebuiltMacOSApp extends MacOSApp implements PrebuiltApplicationPackage {
|
||||||
String get name => bundleName;
|
String get name => bundleName;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? applicationBundle(BuildMode buildMode) => uncompressedBundle.path;
|
String? applicationBundle(BuildInfo buildInfo) => uncompressedBundle.path;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? executable(BuildMode buildMode) => _executable;
|
String? executable(BuildInfo buildInfo) => _executable;
|
||||||
|
|
||||||
/// A [File] or [Directory] pointing to the application bundle.
|
/// A [File] or [Directory] pointing to the application bundle.
|
||||||
///
|
///
|
||||||
|
@ -156,23 +156,30 @@ class BuildableMacOSApp extends MacOSApp {
|
||||||
String get name => 'macOS';
|
String get name => 'macOS';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? applicationBundle(BuildMode buildMode) {
|
String? applicationBundle(BuildInfo buildInfo) {
|
||||||
final File appBundleNameFile = project.nameFile;
|
final File appBundleNameFile = project.nameFile;
|
||||||
if (!appBundleNameFile.existsSync()) {
|
if (!appBundleNameFile.existsSync()) {
|
||||||
globals.printError('Unable to find app name. ${appBundleNameFile.path} does not exist');
|
globals.printError('Unable to find app name. ${appBundleNameFile.path} does not exist');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return globals.fs.path.join(
|
return globals.fs.path.join(
|
||||||
getMacOSBuildDirectory(),
|
getMacOSBuildDirectory(),
|
||||||
'Build',
|
'Build',
|
||||||
'Products',
|
'Products',
|
||||||
sentenceCase(getNameForBuildMode(buildMode)),
|
bundleDirectory(buildInfo),
|
||||||
appBundleNameFile.readAsStringSync().trim());
|
appBundleNameFile.readAsStringSync().trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String bundleDirectory(BuildInfo buildInfo) {
|
||||||
|
return sentenceCase(buildInfo.mode.name) + (buildInfo.flavor != null
|
||||||
|
? ' ${sentenceCase(buildInfo.flavor!)}'
|
||||||
|
: '');
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? executable(BuildMode buildMode) {
|
String? executable(BuildInfo buildInfo) {
|
||||||
final String? directory = applicationBundle(buildMode);
|
final String? directory = applicationBundle(buildInfo);
|
||||||
if (directory == null) {
|
if (directory == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ Future<void> buildMacOS({
|
||||||
'xcodebuild',
|
'xcodebuild',
|
||||||
'-workspace', xcodeWorkspace.path,
|
'-workspace', xcodeWorkspace.path,
|
||||||
'-configuration', configuration,
|
'-configuration', configuration,
|
||||||
'-scheme', 'Runner',
|
'-scheme', scheme,
|
||||||
'-derivedDataPath', flutterBuildDir.absolute.path,
|
'-derivedDataPath', flutterBuildDir.absolute.path,
|
||||||
'-destination', 'platform=macOS',
|
'-destination', 'platform=macOS',
|
||||||
'OBJROOT=${globals.fs.path.join(flutterBuildDir.absolute.path, 'Build', 'Intermediates.noindex')}',
|
'OBJROOT=${globals.fs.path.join(flutterBuildDir.absolute.path, 'Build', 'Intermediates.noindex')}',
|
||||||
|
|
|
@ -78,17 +78,17 @@ class MacOSDevice extends DesktopDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? executablePathForDevice(covariant MacOSApp package, BuildMode buildMode) {
|
String? executablePathForDevice(covariant MacOSApp package, BuildInfo buildInfo) {
|
||||||
return package.executable(buildMode);
|
return package.executable(buildInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onAttached(covariant MacOSApp package, BuildMode buildMode, Process process) {
|
void onAttached(covariant MacOSApp package, BuildInfo buildInfo, Process process) {
|
||||||
// Bring app to foreground. Ideally this would be done post-launch rather
|
// Bring app to foreground. Ideally this would be done post-launch rather
|
||||||
// than post-attach, since this won't run for release builds, but there's
|
// than post-attach, since this won't run for release builds, but there's
|
||||||
// no general-purpose way of knowing when a process is far enough along in
|
// no general-purpose way of knowing when a process is far enough along in
|
||||||
// the launch process for 'open' to foreground it.
|
// the launch process for 'open' to foreground it.
|
||||||
final String? applicationBundle = package.applicationBundle(buildMode);
|
final String? applicationBundle = package.applicationBundle(buildInfo);
|
||||||
if (applicationBundle == null) {
|
if (applicationBundle == null) {
|
||||||
_logger.printError('Failed to foreground app; application bundle not found');
|
_logger.printError('Failed to foreground app; application bundle not found');
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -54,7 +54,7 @@ class MacOSDesignedForIPadDevice extends DesktopDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? executablePathForDevice(ApplicationPackage package, BuildMode buildMode) => null;
|
String? executablePathForDevice(ApplicationPackage package, BuildInfo buildInfo) => null;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<LaunchResult> startApp(
|
Future<LaunchResult> startApp(
|
||||||
|
|
|
@ -61,8 +61,8 @@ class WindowsDevice extends DesktopDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String executablePathForDevice(covariant WindowsApp package, BuildMode buildMode) {
|
String executablePathForDevice(covariant WindowsApp package, BuildInfo buildInfo) {
|
||||||
return package.executable(buildMode);
|
return package.executable(buildInfo.mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -157,6 +157,12 @@ class FakeIOSDevice extends Fake implements IOSDevice {
|
||||||
IOSApp app, {
|
IOSApp app, {
|
||||||
String? userIdentifier,
|
String? userIdentifier,
|
||||||
}) async => true;
|
}) async => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get name => 'iOS';
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get supportsInstall => true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unfortunately Device, despite not being immutable, has an `operator ==`.
|
// Unfortunately Device, despite not being immutable, has an `operator ==`.
|
||||||
|
@ -177,4 +183,10 @@ class FakeAndroidDevice extends Fake implements AndroidDevice {
|
||||||
AndroidApk app, {
|
AndroidApk app, {
|
||||||
String? userIdentifier,
|
String? userIdentifier,
|
||||||
}) async => true;
|
}) async => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get name => 'Android';
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get supportsInstall => true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ void main() {
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
final FakeDesktopDevice device = setUpDesktopDevice(processManager: processManager, fileSystem: fileSystem);
|
final FakeDesktopDevice device = setUpDesktopDevice(processManager: processManager, fileSystem: fileSystem);
|
||||||
final String? executableName = device.executablePathForDevice(FakeApplicationPackage(), BuildMode.debug);
|
final String? executableName = device.executablePathForDevice(FakeApplicationPackage(), BuildInfo.debug);
|
||||||
fileSystem.file(executableName).writeAsStringSync('\n');
|
fileSystem.file(executableName).writeAsStringSync('\n');
|
||||||
final FakeApplicationPackage package = FakeApplicationPackage();
|
final FakeApplicationPackage package = FakeApplicationPackage();
|
||||||
final LaunchResult result = await device.startApp(
|
final LaunchResult result = await device.startApp(
|
||||||
|
@ -367,11 +367,11 @@ class FakeDesktopDevice extends DesktopDevice {
|
||||||
|
|
||||||
// Dummy implementation that just returns the build mode name.
|
// Dummy implementation that just returns the build mode name.
|
||||||
@override
|
@override
|
||||||
String? executablePathForDevice(ApplicationPackage package, BuildMode buildMode) {
|
String? executablePathForDevice(ApplicationPackage package, BuildInfo buildInfo) {
|
||||||
if (nullExecutablePathForDevice) {
|
if (nullExecutablePathForDevice) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return buildMode == null ? 'null' : getNameForBuildMode(buildMode);
|
return buildInfo == null ? 'null' : getNameForBuildMode(buildInfo.mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,9 +154,9 @@ void main() {
|
||||||
operatingSystemUtils: FakeOperatingSystemUtils(),
|
operatingSystemUtils: FakeOperatingSystemUtils(),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(device.executablePathForDevice(mockApp, BuildMode.debug), 'debug/executable');
|
expect(device.executablePathForDevice(mockApp, BuildInfo.debug), 'debug/executable');
|
||||||
expect(device.executablePathForDevice(mockApp, BuildMode.profile), 'profile/executable');
|
expect(device.executablePathForDevice(mockApp, BuildInfo.profile), 'profile/executable');
|
||||||
expect(device.executablePathForDevice(mockApp, BuildMode.release), 'release/executable');
|
expect(device.executablePathForDevice(mockApp, BuildInfo.release), 'release/executable');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
import 'package:flutter_tools/src/base/logger.dart';
|
import 'package:flutter_tools/src/base/logger.dart';
|
||||||
import 'package:flutter_tools/src/base/os.dart';
|
import 'package:flutter_tools/src/base/os.dart';
|
||||||
import 'package:flutter_tools/src/base/utils.dart';
|
import 'package:flutter_tools/src/base/utils.dart';
|
||||||
|
import 'package:flutter_tools/src/build_info.dart';
|
||||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||||
import 'package:flutter_tools/src/ios/plist_parser.dart';
|
import 'package:flutter_tools/src/ios/plist_parser.dart';
|
||||||
import 'package:flutter_tools/src/macos/application_package.dart';
|
import 'package:flutter_tools/src/macos/application_package.dart';
|
||||||
|
@ -155,6 +156,20 @@ group('PrebuiltMacOSApp', () {
|
||||||
expect(macosApp.id, 'com.example.placeholder');
|
expect(macosApp.id, 'com.example.placeholder');
|
||||||
expect(macosApp.name, 'macOS');
|
expect(macosApp.name, 'macOS');
|
||||||
}, overrides: overrides);
|
}, overrides: overrides);
|
||||||
|
|
||||||
|
testUsingContext('Chooses the correct directory for application.', () {
|
||||||
|
final MacOSProject project = FlutterProject.fromDirectory(globals.fs.currentDirectory).macos;
|
||||||
|
final BuildableMacOSApp macosApp = MacOSApp.fromMacOSProject(project) as BuildableMacOSApp;
|
||||||
|
|
||||||
|
const BuildInfo vanillaApp = BuildInfo(BuildMode.debug, null, treeShakeIcons: false);
|
||||||
|
String? applicationBundle = macosApp.bundleDirectory(vanillaApp);
|
||||||
|
expect(applicationBundle, 'Debug');
|
||||||
|
|
||||||
|
const BuildInfo flavoredApp = BuildInfo(BuildMode.release, 'flavor', treeShakeIcons: false);
|
||||||
|
applicationBundle = macosApp.bundleDirectory(flavoredApp);
|
||||||
|
expect(applicationBundle, 'Release Flavor');
|
||||||
|
|
||||||
|
}, overrides: overrides);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -235,9 +235,9 @@ void main() {
|
||||||
const String profilePath = 'profile/executable';
|
const String profilePath = 'profile/executable';
|
||||||
const String releasePath = 'release/executable';
|
const String releasePath = 'release/executable';
|
||||||
|
|
||||||
expect(device.executablePathForDevice(package, BuildMode.debug), debugPath);
|
expect(device.executablePathForDevice(package, BuildInfo.debug), debugPath);
|
||||||
expect(device.executablePathForDevice(package, BuildMode.profile), profilePath);
|
expect(device.executablePathForDevice(package, BuildInfo.profile), profilePath);
|
||||||
expect(device.executablePathForDevice(package, BuildMode.release), releasePath);
|
expect(device.executablePathForDevice(package, BuildInfo.release), releasePath);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,13 +251,13 @@ FlutterProject setUpFlutterProject(Directory directory) {
|
||||||
|
|
||||||
class FakeMacOSApp extends Fake implements MacOSApp {
|
class FakeMacOSApp extends Fake implements MacOSApp {
|
||||||
@override
|
@override
|
||||||
String executable(BuildMode buildMode) {
|
String executable(BuildInfo buildInfo) {
|
||||||
switch (buildMode) {
|
switch (buildInfo) {
|
||||||
case BuildMode.debug:
|
case BuildInfo.debug:
|
||||||
return 'debug/executable';
|
return 'debug/executable';
|
||||||
case BuildMode.profile:
|
case BuildInfo.profile:
|
||||||
return 'profile/executable';
|
return 'profile/executable';
|
||||||
case BuildMode.release:
|
case BuildInfo.release:
|
||||||
return 'release/executable';
|
return 'release/executable';
|
||||||
default:
|
default:
|
||||||
throw StateError('');
|
throw StateError('');
|
||||||
|
|
|
@ -142,7 +142,7 @@ void main() {
|
||||||
throwsA(isA<UnimplementedError>()),
|
throwsA(isA<UnimplementedError>()),
|
||||||
);
|
);
|
||||||
await expectLater(() => device.buildForDevice(buildInfo: BuildInfo.debug), throwsA(isA<UnimplementedError>()));
|
await expectLater(() => device.buildForDevice(buildInfo: BuildInfo.debug), throwsA(isA<UnimplementedError>()));
|
||||||
expect(device.executablePathForDevice(FakeIOSApp(), BuildMode.debug), null);
|
expect(device.executablePathForDevice(FakeIOSApp(), BuildInfo.debug), null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,9 +101,9 @@ void main() {
|
||||||
final WindowsDevice windowsDevice = setUpWindowsDevice();
|
final WindowsDevice windowsDevice = setUpWindowsDevice();
|
||||||
final FakeWindowsApp fakeApp = FakeWindowsApp();
|
final FakeWindowsApp fakeApp = FakeWindowsApp();
|
||||||
|
|
||||||
expect(windowsDevice.executablePathForDevice(fakeApp, BuildMode.debug), 'debug/executable');
|
expect(windowsDevice.executablePathForDevice(fakeApp, BuildInfo.debug), 'debug/executable');
|
||||||
expect(windowsDevice.executablePathForDevice(fakeApp, BuildMode.profile), 'profile/executable');
|
expect(windowsDevice.executablePathForDevice(fakeApp, BuildInfo.profile), 'profile/executable');
|
||||||
expect(windowsDevice.executablePathForDevice(fakeApp, BuildMode.release), 'release/executable');
|
expect(windowsDevice.executablePathForDevice(fakeApp, BuildInfo.release), 'release/executable');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue