mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

Fix some places where Debug/Release was treated as a binary switch. Makes similar changes to Windows and Linux to simplify adding profile support to those platforms in the future. This means `--profile` builds will fail on Linux and Windows for now, but that's fine since they aren't actually supported, and unlike `--release` don't provide useful functionality at the native code level. Also fixes 'stopApp' always using Debug on macOS, to avoid showing an error when running Profile (or Release). Fixes #33203
156 lines
5.1 KiB
Dart
156 lines
5.1 KiB
Dart
// Copyright 2019 The Chromium 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:meta/meta.dart';
|
|
|
|
import '../application_package.dart';
|
|
import '../base/file_system.dart';
|
|
import '../base/utils.dart';
|
|
import '../build_info.dart';
|
|
import '../globals.dart';
|
|
import '../ios/plist_parser.dart';
|
|
import '../project.dart';
|
|
|
|
/// Tests whether a [FileSystemEntity] is an macOS bundle directory
|
|
bool _isBundleDirectory(FileSystemEntity entity) =>
|
|
entity is Directory && entity.path.endsWith('.app');
|
|
|
|
abstract class MacOSApp extends ApplicationPackage {
|
|
MacOSApp({@required String projectBundleId}) : super(id: projectBundleId);
|
|
|
|
/// Creates a new [MacOSApp] from a macOS project directory.
|
|
factory MacOSApp.fromMacOSProject(MacOSProject project) {
|
|
return BuildableMacOSApp(project);
|
|
}
|
|
|
|
/// Creates a new [MacOSApp] from an existing app bundle.
|
|
///
|
|
/// `applicationBinary` is the path to the framework directory created by an
|
|
/// Xcode build. By default, this is located under
|
|
/// "~/Library/Developer/Xcode/DerivedData/" and contains an executable
|
|
/// which is expected to start the application and send the observatory
|
|
/// port over stdout.
|
|
factory MacOSApp.fromPrebuiltApp(FileSystemEntity applicationBinary) {
|
|
final _ExecutableAndId executableAndId = _executableFromBundle(applicationBinary);
|
|
final Directory applicationBundle = fs.directory(applicationBinary);
|
|
return PrebuiltMacOSApp(
|
|
bundleDir: applicationBundle,
|
|
bundleName: applicationBundle.path,
|
|
projectBundleId: executableAndId.id,
|
|
executable: executableAndId.executable,
|
|
);
|
|
}
|
|
|
|
/// Look up the executable name for a macOS application bundle.
|
|
static _ExecutableAndId _executableFromBundle(Directory applicationBundle) {
|
|
final FileSystemEntityType entityType = fs.typeSync(applicationBundle.path);
|
|
if (entityType == FileSystemEntityType.notFound) {
|
|
printError('File "${applicationBundle.path}" does not exist.');
|
|
return null;
|
|
}
|
|
Directory bundleDir;
|
|
if (entityType == FileSystemEntityType.directory) {
|
|
final Directory directory = fs.directory(applicationBundle);
|
|
if (!_isBundleDirectory(directory)) {
|
|
printError('Folder "${applicationBundle.path}" is not an app bundle.');
|
|
return null;
|
|
}
|
|
bundleDir = fs.directory(applicationBundle);
|
|
} else {
|
|
printError('Folder "${applicationBundle.path}" is not an app bundle.');
|
|
return null;
|
|
}
|
|
final String plistPath = fs.path.join(bundleDir.path, 'Contents', 'Info.plist');
|
|
if (!fs.file(plistPath).existsSync()) {
|
|
printError('Invalid prebuilt macOS app. Does not contain Info.plist.');
|
|
return null;
|
|
}
|
|
final Map<String, dynamic> propertyValues = PlistParser.instance.parseFile(plistPath);
|
|
final String id = propertyValues[PlistParser.kCFBundleIdentifierKey];
|
|
final String executableName = propertyValues[PlistParser.kCFBundleExecutable];
|
|
if (id == null) {
|
|
printError('Invalid prebuilt macOS app. Info.plist does not contain bundle identifier');
|
|
return null;
|
|
}
|
|
final String executable = fs.path.join(bundleDir.path, 'Contents', 'MacOS', executableName);
|
|
if (!fs.file(executable).existsSync()) {
|
|
printError('Could not find macOS binary at $executable');
|
|
}
|
|
return _ExecutableAndId(executable, id);
|
|
}
|
|
|
|
@override
|
|
String get displayName => id;
|
|
|
|
String applicationBundle(BuildMode buildMode);
|
|
|
|
String executable(BuildMode buildMode);
|
|
}
|
|
|
|
class PrebuiltMacOSApp extends MacOSApp {
|
|
PrebuiltMacOSApp({
|
|
@required this.bundleDir,
|
|
@required this.bundleName,
|
|
@required this.projectBundleId,
|
|
@required String executable,
|
|
}) : _executable = executable,
|
|
super(projectBundleId: projectBundleId);
|
|
|
|
final Directory bundleDir;
|
|
final String bundleName;
|
|
final String projectBundleId;
|
|
|
|
final String _executable;
|
|
|
|
@override
|
|
String get name => bundleName;
|
|
|
|
@override
|
|
String applicationBundle(BuildMode buildMode) => bundleDir.path;
|
|
|
|
@override
|
|
String executable(BuildMode buildMode) => _executable;
|
|
}
|
|
|
|
class BuildableMacOSApp extends MacOSApp {
|
|
BuildableMacOSApp(this.project);
|
|
|
|
final MacOSProject project;
|
|
|
|
@override
|
|
String get name => 'macOS';
|
|
|
|
@override
|
|
String applicationBundle(BuildMode buildMode) {
|
|
final File appBundleNameFile = project.nameFile;
|
|
if (!appBundleNameFile.existsSync()) {
|
|
printError('Unable to find app name. ${appBundleNameFile.path} does not exist');
|
|
return null;
|
|
}
|
|
return fs.path.join(
|
|
getMacOSBuildDirectory(),
|
|
'Build',
|
|
'Products',
|
|
toTitleCase(getNameForBuildMode(buildMode)),
|
|
appBundleNameFile.readAsStringSync().trim());
|
|
}
|
|
|
|
@override
|
|
String executable(BuildMode buildMode) {
|
|
final String directory = applicationBundle(buildMode);
|
|
if (directory == null) {
|
|
return null;
|
|
}
|
|
final _ExecutableAndId executableAndId = MacOSApp._executableFromBundle(fs.directory(directory));
|
|
return executableAndId?.executable;
|
|
}
|
|
}
|
|
|
|
class _ExecutableAndId {
|
|
_ExecutableAndId(this.executable, this.id);
|
|
|
|
final String executable;
|
|
final String id;
|
|
}
|