mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Ensure Xcode project is setup to start debugger (#136977)
Some users have their Xcode settings set to not debug (see example here https://github.com/flutter/flutter/issues/136197#issuecomment-1766834195). This will cause the [engine check for a debugger](22ce5c6a45/runtime/ptrace_check.cc (L56-L71)
) to fail, which will cause an error and cause the app to crash.
This PR parses the scheme file to ensure the scheme is set to start a debugger and warn the user if it's not.
Fixes https://github.com/flutter/flutter/issues/136197.
This commit is contained in:
parent
9366170e84
commit
5dd2a4e0aa
10
.ci.yaml
10
.ci.yaml
@ -3926,6 +3926,16 @@ targets:
|
||||
["devicelab", "ios", "mac"]
|
||||
task_name: flavors_test_ios
|
||||
|
||||
- name: Mac_arm64_ios flavors_test_ios_xcode_debug
|
||||
recipe: devicelab/devicelab_drone
|
||||
presubmit: false
|
||||
timeout: 60
|
||||
properties:
|
||||
tags: >
|
||||
["devicelab", "ios", "mac"]
|
||||
task_name: flavors_test_ios_xcode_debug
|
||||
bringup: true
|
||||
|
||||
- name: Mac_ios flutter_gallery_ios__compile
|
||||
recipe: devicelab/devicelab_drone
|
||||
presubmit: false
|
||||
|
@ -174,6 +174,7 @@
|
||||
/dev/devicelab/bin/tasks/cubic_bezier_perf_ios_sksl_warmup__timeline_summary.dart @zanderso @flutter/engine
|
||||
/dev/devicelab/bin/tasks/external_ui_integration_test_ios.dart @zanderso @flutter/engine
|
||||
/dev/devicelab/bin/tasks/flavors_test_ios.dart @vashworth @flutter/tool
|
||||
/dev/devicelab/bin/tasks/flavors_test_ios_xcode_debug.dart @vashworth @flutter/tool
|
||||
/dev/devicelab/bin/tasks/flutter_gallery__transition_perf_e2e_ios.dart @zanderso @flutter/engine
|
||||
/dev/devicelab/bin/tasks/flutter_gallery_ios__compile.dart @vashworth @flutter/engine
|
||||
/dev/devicelab/bin/tasks/flutter_gallery_ios__start_up.dart @vashworth @flutter/engine
|
||||
|
52
dev/devicelab/bin/tasks/flavors_test_ios_xcode_debug.dart
Normal file
52
dev/devicelab/bin/tasks/flavors_test_ios_xcode_debug.dart
Normal file
@ -0,0 +1,52 @@
|
||||
// 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.ios;
|
||||
await task(() async {
|
||||
await createFlavorsTest(environment: <String, String>{
|
||||
'FORCE_XCODE_DEBUG': 'true',
|
||||
}).call();
|
||||
await createIntegrationTestFlavorsTest(environment: <String, String>{
|
||||
'FORCE_XCODE_DEBUG': 'true',
|
||||
}).call();
|
||||
// test install and uninstall of flavors app
|
||||
final TaskResult installTestsResult = await inDirectory(
|
||||
'${flutterDirectory.path}/dev/integration_tests/flavors',
|
||||
() async {
|
||||
await flutter(
|
||||
'install',
|
||||
options: <String>['--flavor', 'paid'],
|
||||
);
|
||||
await flutter(
|
||||
'install',
|
||||
options: <String>['--flavor', 'paid', '--uninstall-only'],
|
||||
);
|
||||
final StringBuffer stderr = StringBuffer();
|
||||
await evalFlutter(
|
||||
'install',
|
||||
canFail: true,
|
||||
stderr: stderr,
|
||||
options: <String>['--flavor', 'bogus'],
|
||||
);
|
||||
|
||||
final String stderrString = stderr.toString();
|
||||
if (!stderrString.contains('The Xcode project defines schemes: free, paid')) {
|
||||
print(stderrString);
|
||||
return TaskResult.failure('Should not succeed with bogus flavor');
|
||||
}
|
||||
|
||||
return TaskResult.success(null);
|
||||
},
|
||||
);
|
||||
|
||||
return installTestsResult;
|
||||
});
|
||||
}
|
@ -22,19 +22,21 @@ TaskFunction createPlatformInteractionTest() {
|
||||
).call;
|
||||
}
|
||||
|
||||
TaskFunction createFlavorsTest() {
|
||||
TaskFunction createFlavorsTest({Map<String, String>? environment}) {
|
||||
return DriverTest(
|
||||
'${flutterDirectory.path}/dev/integration_tests/flavors',
|
||||
'lib/main.dart',
|
||||
extraOptions: <String>['--flavor', 'paid'],
|
||||
environment: environment,
|
||||
).call;
|
||||
}
|
||||
|
||||
TaskFunction createIntegrationTestFlavorsTest() {
|
||||
TaskFunction createIntegrationTestFlavorsTest({Map<String, String>? environment}) {
|
||||
return IntegrationTest(
|
||||
'${flutterDirectory.path}/dev/integration_tests/flavors',
|
||||
'integration_test/integration_test.dart',
|
||||
extraOptions: <String>['--flavor', 'paid'],
|
||||
environment: environment,
|
||||
).call;
|
||||
}
|
||||
|
||||
@ -219,6 +221,7 @@ class IntegrationTest {
|
||||
this.extraOptions = const <String>[],
|
||||
this.createPlatforms = const <String>[],
|
||||
this.withTalkBack = false,
|
||||
this.environment,
|
||||
}
|
||||
);
|
||||
|
||||
@ -227,6 +230,7 @@ class IntegrationTest {
|
||||
final List<String> extraOptions;
|
||||
final List<String> createPlatforms;
|
||||
final bool withTalkBack;
|
||||
final Map<String, String>? environment;
|
||||
|
||||
Future<TaskResult> call() {
|
||||
return inDirectory<TaskResult>(testDirectory, () async {
|
||||
@ -258,7 +262,7 @@ class IntegrationTest {
|
||||
testTarget,
|
||||
...extraOptions,
|
||||
];
|
||||
await flutter('test', options: options);
|
||||
await flutter('test', options: options, environment: environment);
|
||||
|
||||
if (withTalkBack) {
|
||||
await disableTalkBack();
|
||||
|
@ -877,6 +877,8 @@ class IOSDevice extends Device {
|
||||
projectInfo.reportFlavorNotFoundAndExit();
|
||||
}
|
||||
|
||||
_xcodeDebug.ensureXcodeDebuggerLaunchAction(project.xcodeProjectSchemeFile(scheme: scheme));
|
||||
|
||||
debugProject = XcodeDebugProject(
|
||||
scheme: scheme,
|
||||
xcodeProject: project.xcodeProject,
|
||||
|
@ -6,7 +6,10 @@ import 'dart:async';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:process/process.dart';
|
||||
import 'package:xml/xml.dart';
|
||||
import 'package:xml/xpath.dart';
|
||||
|
||||
import '../base/common.dart';
|
||||
import '../base/error_handling_io.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../base/io.dart';
|
||||
@ -58,7 +61,6 @@ class XcodeDebug {
|
||||
required String deviceId,
|
||||
required List<String> launchArguments,
|
||||
}) async {
|
||||
|
||||
// If project is not already opened in Xcode, open it.
|
||||
if (!await _isProjectOpenInXcode(project: project)) {
|
||||
final bool openResult = await _openProjectInXcode(xcodeWorkspace: project.xcodeWorkspace);
|
||||
@ -411,6 +413,49 @@ class XcodeDebug {
|
||||
verboseLogging: verboseLogging,
|
||||
);
|
||||
}
|
||||
|
||||
/// Ensure the Xcode project is set up to launch an LLDB debugger. If these
|
||||
/// settings are not set, the launch will fail with a "Cannot create a
|
||||
/// FlutterEngine instance in debug mode without Flutter tooling or Xcode."
|
||||
/// error message. These settings should be correct by default, but some users
|
||||
/// reported them not being so after upgrading to Xcode 15.
|
||||
void ensureXcodeDebuggerLaunchAction(File schemeFile) {
|
||||
if (!schemeFile.existsSync()) {
|
||||
_logger.printError('Failed to find ${schemeFile.path}');
|
||||
return;
|
||||
}
|
||||
|
||||
final String schemeXml = schemeFile.readAsStringSync();
|
||||
try {
|
||||
final XmlDocument document = XmlDocument.parse(schemeXml);
|
||||
final Iterable<XmlNode> nodes = document.xpath('/Scheme/LaunchAction');
|
||||
if (nodes.isEmpty) {
|
||||
_logger.printError('Failed to find LaunchAction for the Scheme in ${schemeFile.path}.');
|
||||
return;
|
||||
}
|
||||
final XmlNode launchAction = nodes.first;
|
||||
final XmlAttribute? debuggerIdentifer = launchAction.attributes
|
||||
.where((XmlAttribute attribute) =>
|
||||
attribute.localName == 'selectedDebuggerIdentifier')
|
||||
.firstOrNull;
|
||||
final XmlAttribute? launcherIdentifer = launchAction.attributes
|
||||
.where((XmlAttribute attribute) =>
|
||||
attribute.localName == 'selectedLauncherIdentifier')
|
||||
.firstOrNull;
|
||||
if (debuggerIdentifer == null ||
|
||||
launcherIdentifer == null ||
|
||||
!debuggerIdentifer.value.contains('LLDB') ||
|
||||
!launcherIdentifer.value.contains('LLDB')) {
|
||||
throwToolExit('''
|
||||
Your Xcode project is not setup to start a debugger. To fix this, launch Xcode
|
||||
and select "Product > Scheme > Edit Scheme", select "Run" in the sidebar,
|
||||
and ensure "Debug executable" is checked in the "Info" tab.
|
||||
''');
|
||||
}
|
||||
} on XmlException catch (exception) {
|
||||
_logger.printError('Failed to parse ${schemeFile.path}: $exception');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
|
@ -12,7 +12,7 @@ class XcodeProjectObjectVersionMigration extends ProjectMigrator {
|
||||
XcodeBasedProject project,
|
||||
super.logger,
|
||||
) : _xcodeProjectInfoFile = project.xcodeProjectInfoFile,
|
||||
_xcodeProjectSchemeFile = project.xcodeProjectSchemeFile;
|
||||
_xcodeProjectSchemeFile = project.xcodeProjectSchemeFile();
|
||||
|
||||
final File _xcodeProjectInfoFile;
|
||||
final File _xcodeProjectSchemeFile;
|
||||
|
@ -68,8 +68,10 @@ abstract class XcodeBasedProject extends FlutterProjectPlatform {
|
||||
File get xcodeProjectInfoFile => xcodeProject.childFile('project.pbxproj');
|
||||
|
||||
/// The 'Runner.xcscheme' file of [xcodeProject].
|
||||
File get xcodeProjectSchemeFile =>
|
||||
xcodeProject.childDirectory('xcshareddata').childDirectory('xcschemes').childFile('Runner.xcscheme');
|
||||
File xcodeProjectSchemeFile({String? scheme}) {
|
||||
final String schemeName = scheme ?? 'Runner';
|
||||
return xcodeProject.childDirectory('xcshareddata').childDirectory('xcschemes').childFile('$schemeName.xcscheme');
|
||||
}
|
||||
|
||||
File get xcodeProjectWorkspaceData =>
|
||||
xcodeProject
|
||||
|
@ -520,6 +520,81 @@ void main() {
|
||||
Xcode: () => xcode,
|
||||
});
|
||||
|
||||
group('with flavor', () {
|
||||
setUp(() {
|
||||
projectInfo = XcodeProjectInfo(
|
||||
<String>['Runner'],
|
||||
<String>['Debug', 'Release', 'Debug-free', 'Release-free'],
|
||||
<String>['Runner', 'free'],
|
||||
logger,
|
||||
);
|
||||
fakeXcodeProjectInterpreter = FakeXcodeProjectInterpreter(projectInfo: projectInfo);
|
||||
xcode = Xcode.test(processManager: FakeProcessManager.any(), xcodeProjectInterpreter: fakeXcodeProjectInterpreter);
|
||||
});
|
||||
|
||||
testUsingContext('succeeds', () async {
|
||||
final IOSDevice iosDevice = setUpIOSDevice(
|
||||
fileSystem: fileSystem,
|
||||
processManager: FakeProcessManager.any(),
|
||||
logger: logger,
|
||||
artifacts: artifacts,
|
||||
isCoreDevice: true,
|
||||
coreDeviceControl: FakeIOSCoreDeviceControl(),
|
||||
xcodeDebug: FakeXcodeDebug(
|
||||
expectedProject: XcodeDebugProject(
|
||||
scheme: 'free',
|
||||
xcodeWorkspace: fileSystem.directory('/ios/Runner.xcworkspace'),
|
||||
xcodeProject: fileSystem.directory('/ios/Runner.xcodeproj'),
|
||||
hostAppProjectName: 'Runner',
|
||||
),
|
||||
expectedDeviceId: '123',
|
||||
expectedLaunchArguments: <String>['--enable-dart-profiling'],
|
||||
expectedSchemeFilePath: '/ios/Runner.xcodeproj/xcshareddata/xcschemes/free.xcscheme',
|
||||
),
|
||||
);
|
||||
|
||||
setUpIOSProject(fileSystem);
|
||||
final FlutterProject flutterProject = FlutterProject.fromDirectory(fileSystem.currentDirectory);
|
||||
final BuildableIOSApp buildableIOSApp = BuildableIOSApp(flutterProject.ios, 'flutter', 'My Super Awesome App.app');
|
||||
fileSystem.directory('build/ios/Release-iphoneos/My Super Awesome App.app').createSync(recursive: true);
|
||||
|
||||
final FakeDeviceLogReader deviceLogReader = FakeDeviceLogReader();
|
||||
|
||||
iosDevice.portForwarder = const NoOpDevicePortForwarder();
|
||||
iosDevice.setLogReader(buildableIOSApp, deviceLogReader);
|
||||
|
||||
// Start writing messages to the log reader.
|
||||
Timer.run(() {
|
||||
deviceLogReader.addLine('Foo');
|
||||
deviceLogReader.addLine('The Dart VM service is listening on http://127.0.0.1:456');
|
||||
});
|
||||
|
||||
final LaunchResult launchResult = await iosDevice.startApp(
|
||||
buildableIOSApp,
|
||||
debuggingOptions: DebuggingOptions.enabled(const BuildInfo(
|
||||
BuildMode.debug,
|
||||
'free',
|
||||
buildName: '1.2.3',
|
||||
buildNumber: '4',
|
||||
treeShakeIcons: false,
|
||||
)),
|
||||
platformArgs: <String, Object>{},
|
||||
);
|
||||
|
||||
expect(logger.errorText, isEmpty);
|
||||
expect(fileSystem.directory('build/ios/iphoneos'), exists);
|
||||
expect(launchResult.started, true);
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
}, overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
FileSystem: () => fileSystem,
|
||||
Logger: () => logger,
|
||||
Platform: () => macPlatform,
|
||||
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
|
||||
Xcode: () => xcode,
|
||||
});
|
||||
});
|
||||
|
||||
testUsingContext('updates Generated.xcconfig before and after launch', () async {
|
||||
final Completer<void> debugStartedCompleter = Completer<void>();
|
||||
final Completer<void> debugEndedCompleter = Completer<void>();
|
||||
@ -829,6 +904,7 @@ class FakeXcodeDebug extends Fake implements XcodeDebug {
|
||||
this.expectedProject,
|
||||
this.expectedDeviceId,
|
||||
this.expectedLaunchArguments,
|
||||
this.expectedSchemeFilePath = '/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme',
|
||||
this.debugStartedCompleter,
|
||||
this.debugEndedCompleter,
|
||||
});
|
||||
@ -840,6 +916,7 @@ class FakeXcodeDebug extends Fake implements XcodeDebug {
|
||||
final List<String>? expectedLaunchArguments;
|
||||
final Completer<void>? debugStartedCompleter;
|
||||
final Completer<void>? debugEndedCompleter;
|
||||
final String expectedSchemeFilePath;
|
||||
|
||||
@override
|
||||
Future<bool> debugApp({
|
||||
@ -863,6 +940,11 @@ class FakeXcodeDebug extends Fake implements XcodeDebug {
|
||||
await debugEndedCompleter?.future;
|
||||
return debugSuccess;
|
||||
}
|
||||
|
||||
@override
|
||||
void ensureXcodeDebuggerLaunchAction(File schemeFile) {
|
||||
expect(schemeFile.path, expectedSchemeFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
class FakeIOSCoreDeviceControl extends Fake implements IOSCoreDeviceControl {
|
||||
|
@ -662,7 +662,7 @@ platform :ios, '11.0'
|
||||
project.xcodeProjectInfoFile = xcodeProjectInfoFile;
|
||||
|
||||
xcodeProjectSchemeFile = memoryFileSystem.file('Runner.xcscheme');
|
||||
project.xcodeProjectSchemeFile = xcodeProjectSchemeFile;
|
||||
project.schemeFile = xcodeProjectSchemeFile;
|
||||
});
|
||||
|
||||
testWithoutContext('skipped if files are missing', () {
|
||||
@ -1370,8 +1370,10 @@ class FakeIosProject extends Fake implements IosProject {
|
||||
@override
|
||||
File xcodeProjectInfoFile = MemoryFileSystem.test().file('xcodeProjectInfoFile');
|
||||
|
||||
File? schemeFile;
|
||||
|
||||
@override
|
||||
File xcodeProjectSchemeFile = MemoryFileSystem.test().file('xcodeProjectSchemeFile');
|
||||
File xcodeProjectSchemeFile({String? scheme}) => schemeFile ?? MemoryFileSystem.test().file('xcodeProjectSchemeFile');
|
||||
|
||||
@override
|
||||
File appFrameworkInfoPlist = MemoryFileSystem.test().file('appFrameworkInfoPlist');
|
||||
|
@ -1064,6 +1064,96 @@ void main() {
|
||||
expect(status, isFalse);
|
||||
});
|
||||
});
|
||||
|
||||
group('ensureXcodeDebuggerLaunchAction', () {
|
||||
late Xcode xcode;
|
||||
|
||||
setUp(() {
|
||||
xcode = setupXcode(
|
||||
fakeProcessManager: fakeProcessManager,
|
||||
fileSystem: fileSystem,
|
||||
flutterRoot: flutterRoot,
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('succeeds', () async {
|
||||
final XcodeDebug xcodeDebug = XcodeDebug(
|
||||
logger: logger,
|
||||
processManager: fakeProcessManager,
|
||||
xcode: xcode,
|
||||
fileSystem: fileSystem,
|
||||
);
|
||||
|
||||
final File schemeFile = fileSystem.file('ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme');
|
||||
schemeFile.createSync(recursive: true);
|
||||
schemeFile.writeAsStringSync(validSchemeXml);
|
||||
|
||||
xcodeDebug.ensureXcodeDebuggerLaunchAction(schemeFile);
|
||||
expect(logger.errorText, isEmpty);
|
||||
});
|
||||
|
||||
testWithoutContext('prints error if scheme file not found', () async {
|
||||
final XcodeDebug xcodeDebug = XcodeDebug(
|
||||
logger: logger,
|
||||
processManager: fakeProcessManager,
|
||||
xcode: xcode,
|
||||
fileSystem: fileSystem,
|
||||
);
|
||||
|
||||
final File schemeFile = fileSystem.file('ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme');
|
||||
|
||||
xcodeDebug.ensureXcodeDebuggerLaunchAction(schemeFile);
|
||||
expect(logger.errorText.contains('Failed to find'), isTrue);
|
||||
});
|
||||
|
||||
testWithoutContext('throws error if launch action is missing debugger info', () async {
|
||||
final XcodeDebug xcodeDebug = XcodeDebug(
|
||||
logger: logger,
|
||||
processManager: fakeProcessManager,
|
||||
xcode: xcode,
|
||||
fileSystem: fileSystem,
|
||||
);
|
||||
|
||||
final File schemeFile = fileSystem.file('ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme');
|
||||
schemeFile.createSync(recursive: true);
|
||||
schemeFile.writeAsStringSync(disabledDebugExecutableSchemeXml);
|
||||
|
||||
expect(() => xcodeDebug.ensureXcodeDebuggerLaunchAction(schemeFile),
|
||||
throwsToolExit(message: 'Your Xcode project is not setup to start a debugger.'));
|
||||
});
|
||||
|
||||
testWithoutContext('prints error if unable to find launch action', () async {
|
||||
final XcodeDebug xcodeDebug = XcodeDebug(
|
||||
logger: logger,
|
||||
processManager: fakeProcessManager,
|
||||
xcode: xcode,
|
||||
fileSystem: fileSystem,
|
||||
);
|
||||
|
||||
final File schemeFile = fileSystem.file('ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme');
|
||||
schemeFile.createSync(recursive: true);
|
||||
schemeFile.writeAsStringSync('<?xml version="1.0" encoding="UTF-8"?><Scheme></Scheme>');
|
||||
|
||||
xcodeDebug.ensureXcodeDebuggerLaunchAction(schemeFile);
|
||||
expect(logger.errorText.contains('Failed to find LaunchAction for the Scheme'), isTrue);
|
||||
});
|
||||
|
||||
testWithoutContext('prints error if invalid xml', () async {
|
||||
final XcodeDebug xcodeDebug = XcodeDebug(
|
||||
logger: logger,
|
||||
processManager: fakeProcessManager,
|
||||
xcode: xcode,
|
||||
fileSystem: fileSystem,
|
||||
);
|
||||
|
||||
final File schemeFile = fileSystem.file('ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme');
|
||||
schemeFile.createSync(recursive: true);
|
||||
schemeFile.writeAsStringSync('<?xml version="1.0" encoding="UTF-8"?><Scheme>');
|
||||
|
||||
xcodeDebug.ensureXcodeDebuggerLaunchAction(schemeFile);
|
||||
expect(logger.errorText.contains('Failed to parse'), isTrue);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group('Debug project through Xcode with app bundle', () {
|
||||
@ -1161,3 +1251,89 @@ class FakeProcess extends Fake implements Process {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const String validSchemeXml = '''
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Profile"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
''';
|
||||
|
||||
const String disabledDebugExecutableSchemeXml = '''
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = ""
|
||||
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Profile"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
''';
|
||||
|
Loading…
Reference in New Issue
Block a user