Skip to content

Commit 73096fd

Browse files
a-wallena-wallenjmagman
authored
[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 <[email protected]> * 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 <[email protected]> Co-authored-by: Jenn Magder <[email protected]>
1 parent 09bd0f6 commit 73096fd

File tree

21 files changed

+173
-43
lines changed

21 files changed

+173
-43
lines changed

.ci.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2668,6 +2668,20 @@ targets:
26682668
- bin/**
26692669
- .ci.yaml
26702670

2671+
- name: Mac flavors_test_macos
2672+
bringup: true
2673+
recipe: devicelab/devicelab_drone
2674+
timeout: 60
2675+
properties:
2676+
dependencies: >-
2677+
[
2678+
{"dependency": "xcode", "version": "14a5294e"},
2679+
{"dependency": "gems", "version": "v3.3.14"}
2680+
]
2681+
tags: >
2682+
["devicelab", "hostonly", "mac"]
2683+
task_name: flavors_test_macos
2684+
26712685
- name: Mac flutter_gallery_macos__compile
26722686
presubmit: false
26732687
recipe: devicelab/devicelab_drone

TESTOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@
220220
/dev/devicelab/bin/tasks/complex_layout_win_desktop__start_up.dart @yaakovschectman @flutter/desktop
221221
/dev/devicelab/bin/tasks/dart_plugin_registry_test.dart @stuartmorgan @flutter/plugin
222222
/dev/devicelab/bin/tasks/entrypoint_dart_registrant.dart @aaclarke @flutter/plugin
223+
/dev/devicelab/bin/tasks/flavors_test_macos.dart @a-wallen @flutter/desktop
223224
/dev/devicelab/bin/tasks/flutter_gallery_macos__compile.dart @a-wallen @flutter/desktop
224225
/dev/devicelab/bin/tasks/flutter_gallery_macos__start_up.dart @a-wallen @flutter/desktop
225226
/dev/devicelab/bin/tasks/flutter_gallery_win_desktop__compile.dart @yaakovschectman @flutter/desktop
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter_devicelab/framework/devices.dart';
6+
import 'package:flutter_devicelab/framework/framework.dart';
7+
import 'package:flutter_devicelab/framework/task_result.dart';
8+
import 'package:flutter_devicelab/framework/utils.dart';
9+
import 'package:flutter_devicelab/tasks/integration_tests.dart';
10+
11+
Future<void> main() async {
12+
deviceOperatingSystem = DeviceOperatingSystem.macos;
13+
await task(() async {
14+
await createFlavorsTest().call();
15+
await createIntegrationTestFlavorsTest().call();
16+
17+
await inDirectory('${flutterDirectory.path}/dev/integration_tests/flavors', () async {
18+
final StringBuffer stderr = StringBuffer();
19+
20+
await evalFlutter(
21+
'install',
22+
canFail: true,
23+
stderr: stderr,
24+
options: <String>[
25+
'--d', 'macos',
26+
'--flavor', 'free'
27+
],
28+
);
29+
30+
final String stderrString = stderr.toString();
31+
if (!stderrString.contains('Host and target are the same. Nothing to install.')) {
32+
print(stderrString);
33+
return TaskResult.failure('Installing a macOS app on macOS should no-op');
34+
}
35+
});
36+
37+
return TaskResult.success(null);
38+
});
39+
}

dev/integration_tests/flavors/macos/Runner.xcodeproj/project.pbxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,7 @@
651651
"@executable_path/../Frameworks",
652652
);
653653
PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.flavors.free;
654+
PRODUCT_FLAVOR = free;
654655
PRODUCT_NAME = "$(TARGET_NAME)";
655656
PROVISIONING_PROFILE_SPECIFIER = "";
656657
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -673,6 +674,7 @@
673674
"@executable_path/../Frameworks",
674675
);
675676
PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.flavors.free;
677+
PRODUCT_FLAVOR = free;
676678
PRODUCT_NAME = "$(TARGET_NAME)";
677679
PROVISIONING_PROFILE_SPECIFIER = "";
678680
SWIFT_VERSION = 5.0;

packages/flutter_tools/bin/macos_assemble.sh

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,32 @@ EchoError() {
1717
echo "$@" 1>&2
1818
}
1919

20+
ParseFlutterBuildMode() {
21+
# Use FLUTTER_BUILD_MODE if it's set, otherwise use the Xcode build configuration name
22+
# This means that if someone wants to use an Xcode build config other than Debug/Profile/Release,
23+
# they _must_ set FLUTTER_BUILD_MODE so we know what type of artifact to build.
24+
local build_mode="$(echo "${FLUTTER_BUILD_MODE:-${CONFIGURATION}}" | tr "[:upper:]" "[:lower:]")"
25+
26+
case "$build_mode" in
27+
*release*) build_mode="release";;
28+
*profile*) build_mode="profile";;
29+
*debug*) build_mode="debug";;
30+
*)
31+
EchoError "========================================================================"
32+
EchoError "ERROR: Unknown FLUTTER_BUILD_MODE: ${build_mode}."
33+
EchoError "Valid values are 'Debug', 'Profile', or 'Release' (case insensitive)."
34+
EchoError "This is controlled by the FLUTTER_BUILD_MODE environment variable."
35+
EchoError "If that is not set, the CONFIGURATION environment variable is used."
36+
EchoError ""
37+
EchoError "You can fix this by either adding an appropriately named build"
38+
EchoError "configuration, or adding an appropriate value for FLUTTER_BUILD_MODE to the"
39+
EchoError ".xcconfig file for the current build configuration (${CONFIGURATION})."
40+
EchoError "========================================================================"
41+
exit -1;;
42+
esac
43+
echo "${build_mode}"
44+
}
45+
2046
BuildApp() {
2147
# Set the working directory to the project root
2248
local project_path="${SOURCE_ROOT}/.."
@@ -28,8 +54,10 @@ BuildApp() {
2854
target_path="${FLUTTER_TARGET}"
2955
fi
3056

31-
# Set the build mode
32-
local build_mode="$(echo "${FLUTTER_BUILD_MODE:-${CONFIGURATION}}" | tr "[:upper:]" "[:lower:]")"
57+
# Use FLUTTER_BUILD_MODE if it's set, otherwise use the Xcode build configuration name
58+
# This means that if someone wants to use an Xcode build config other than Debug/Profile/Release,
59+
# they _must_ set FLUTTER_BUILD_MODE so we know what type of artifact to build.
60+
local build_mode="$(ParseFlutterBuildMode)"
3361

3462
if [[ -n "$LOCAL_ENGINE" ]]; then
3563
if [[ $(echo "$LOCAL_ENGINE" | tr "[:upper:]" "[:lower:]") != *"$build_mode"* ]]; then

packages/flutter_tools/lib/src/commands/install.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ class InstallCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts
5050
if (device == null) {
5151
throwToolExit('No target device found');
5252
}
53+
54+
if (!device!.supportsInstall) {
55+
throwToolExit('Host and target are the same. Nothing to install.');
56+
}
57+
5358
if (userIdentifier != null && device is! AndroidDevice) {
5459
throwToolExit('--${FlutterOptions.kDeviceUser} is only supported for Android');
5560
}

packages/flutter_tools/lib/src/desktop_device.dart

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ abstract class DesktopDevice extends Device {
104104
@override
105105
void clearLogs() {}
106106

107+
@override
108+
bool get supportsInstall => false;
109+
107110
@override
108111
Future<LaunchResult> startApp(
109112
ApplicationPackage package, {
@@ -123,9 +126,9 @@ abstract class DesktopDevice extends Device {
123126
}
124127

125128
// Ensure that the executable is locatable.
126-
final BuildMode buildMode = debuggingOptions.buildInfo.mode;
129+
final BuildInfo buildInfo = debuggingOptions.buildInfo;
127130
final bool traceStartup = platformArgs['trace-startup'] as bool? ?? false;
128-
final String? executable = executablePathForDevice(package, buildMode);
131+
final String? executable = executablePathForDevice(package, buildInfo);
129132
if (executable == null) {
130133
_logger.printError('Unable to find executable to run');
131134
return LaunchResult.failed();
@@ -161,7 +164,7 @@ abstract class DesktopDevice extends Device {
161164
try {
162165
final Uri? observatoryUri = await observatoryDiscovery.uri;
163166
if (observatoryUri != null) {
164-
onAttached(package, buildMode, process);
167+
onAttached(package, buildInfo, process);
165168
return LaunchResult.succeeded(observatoryUri: observatoryUri);
166169
}
167170
_logger.printError(
@@ -203,11 +206,11 @@ abstract class DesktopDevice extends Device {
203206

204207
/// Returns the path to the executable to run for [package] on this device for
205208
/// the given [buildMode].
206-
String? executablePathForDevice(ApplicationPackage package, BuildMode buildMode);
209+
String? executablePathForDevice(ApplicationPackage package, BuildInfo buildInfo);
207210

208211
/// Called after a process is attached, allowing any device-specific extra
209212
/// steps to be run.
210-
void onAttached(ApplicationPackage package, BuildMode buildMode, Process process) {}
213+
void onAttached(ApplicationPackage package, BuildInfo buildInfo, Process process) {}
211214

212215
/// Computes a set of environment variables used to pass debugging information
213216
/// to the engine without interfering with application level command line

packages/flutter_tools/lib/src/device.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,10 @@ abstract class Device {
579579
/// Whether the device supports the '--fast-start' development mode.
580580
bool get supportsFastStart => false;
581581

582+
/// Whether this device supports the installation of a flutter app via
583+
/// `flutter install`.
584+
bool get supportsInstall => true;
585+
582586
/// Stop an app package on the current device.
583587
///
584588
/// Specify [userIdentifier] to stop app installed to a profile (Android only).

packages/flutter_tools/lib/src/linux/linux_device.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ class LinuxDevice extends DesktopDevice {
7070
}
7171

7272
@override
73-
String executablePathForDevice(covariant LinuxApp package, BuildMode buildMode) {
74-
return package.executable(buildMode);
73+
String executablePathForDevice(covariant LinuxApp package, BuildInfo buildInfo) {
74+
return package.executable(buildInfo.mode);
7575
}
7676
}
7777

packages/flutter_tools/lib/src/macos/application_package.dart

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ abstract class MacOSApp extends ApplicationPackage {
106106
@override
107107
String get displayName => id;
108108

109-
String? applicationBundle(BuildMode buildMode);
109+
String? applicationBundle(BuildInfo buildInfo);
110110

111-
String? executable(BuildMode buildMode);
111+
String? executable(BuildInfo buildInfo);
112112
}
113113

114114
class PrebuiltMacOSApp extends MacOSApp implements PrebuiltApplicationPackage {
@@ -135,10 +135,10 @@ class PrebuiltMacOSApp extends MacOSApp implements PrebuiltApplicationPackage {
135135
String get name => bundleName;
136136

137137
@override
138-
String? applicationBundle(BuildMode buildMode) => uncompressedBundle.path;
138+
String? applicationBundle(BuildInfo buildInfo) => uncompressedBundle.path;
139139

140140
@override
141-
String? executable(BuildMode buildMode) => _executable;
141+
String? executable(BuildInfo buildInfo) => _executable;
142142

143143
/// A [File] or [Directory] pointing to the application bundle.
144144
///
@@ -156,23 +156,30 @@ class BuildableMacOSApp extends MacOSApp {
156156
String get name => 'macOS';
157157

158158
@override
159-
String? applicationBundle(BuildMode buildMode) {
159+
String? applicationBundle(BuildInfo buildInfo) {
160160
final File appBundleNameFile = project.nameFile;
161161
if (!appBundleNameFile.existsSync()) {
162162
globals.printError('Unable to find app name. ${appBundleNameFile.path} does not exist');
163163
return null;
164164
}
165+
165166
return globals.fs.path.join(
166167
getMacOSBuildDirectory(),
167168
'Build',
168169
'Products',
169-
sentenceCase(getNameForBuildMode(buildMode)),
170+
bundleDirectory(buildInfo),
170171
appBundleNameFile.readAsStringSync().trim());
171172
}
172173

174+
String bundleDirectory(BuildInfo buildInfo) {
175+
return sentenceCase(buildInfo.mode.name) + (buildInfo.flavor != null
176+
? ' ${sentenceCase(buildInfo.flavor!)}'
177+
: '');
178+
}
179+
173180
@override
174-
String? executable(BuildMode buildMode) {
175-
final String? directory = applicationBundle(buildMode);
181+
String? executable(BuildInfo buildInfo) {
182+
final String? directory = applicationBundle(buildInfo);
176183
if (directory == null) {
177184
return null;
178185
}

0 commit comments

Comments
 (0)