-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Minimal example to get debugging to work with iOS 17 #25
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ import { randomString } from './lib/utils'; | |
import * as targetCommand from './targetCommand'; | ||
import { getTargetFromUDID, pickTarget, getOrPickTarget } from './targetPicker'; | ||
import * as simulatorFocus from './simulatorFocus'; | ||
import { _execFile } from './lib/utils'; | ||
|
||
let context: vscode.ExtensionContext; | ||
|
||
|
@@ -32,7 +33,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv | |
else if (typeof iosTarget === "string") { | ||
return await getTargetFromUDID(iosTarget); | ||
} | ||
|
||
return undefined; | ||
} | ||
|
||
|
@@ -89,14 +90,14 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv | |
let target: Target = dbgConfig.iosTarget; | ||
|
||
if (target.type === "Simulator") | ||
{ | ||
{ | ||
let pid: string|void; | ||
|
||
// Check if we have enough permissions for the simulator focus monitor. | ||
let enableSimulatorFocusMonitor = vscode.workspace.getConfiguration().get('ios-debug.focusSimulator') && await simulatorFocus.tryEnsurePermissions(); | ||
|
||
if (dbgConfig.iosRequest === "launch") | ||
{ | ||
if (dbgConfig.iosRequest === "launch") | ||
{ | ||
let outputBasename = getOutputBasename(); | ||
let stdout = `${outputBasename}-stdout`; | ||
let stderr = `${outputBasename}-stderr`; | ||
|
@@ -125,7 +126,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv | |
dbgConfig.initCommands.push(`follow ${stdout}`); | ||
dbgConfig.initCommands.push(`follow ${stderr}`); | ||
} | ||
else | ||
else | ||
{ | ||
pid = await targetCommand.simulatorGetPidFor({ | ||
target: target as Simulator, | ||
|
@@ -145,11 +146,11 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv | |
delete dbgConfig.env; | ||
delete dbgConfig.args; | ||
} | ||
else if (target.type === "Device") | ||
{ | ||
let platformPath: string|void; | ||
if (dbgConfig.iosRequest === "launch") | ||
else if (target.type === "Device") | ||
{ | ||
let platformPath: string|void; | ||
if (dbgConfig.iosRequest === "launch") | ||
{ | ||
if (dbgConfig.iosInstallApp) { | ||
platformPath = await targetCommand.deviceInstall({ | ||
target: target as Device, | ||
|
@@ -162,7 +163,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv | |
}); | ||
} | ||
} | ||
else | ||
else | ||
{ | ||
platformPath = await targetCommand.deviceAppPath({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this still work? Doesn't this also use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At the moment, getting the platform path still works with One can also do it with |
||
target: target as Device, | ||
|
@@ -181,16 +182,37 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv | |
|
||
if (!platformPath) { return null; } | ||
|
||
let debugserverPort = await targetCommand.deviceDebugserver({ | ||
target: target as Device, | ||
}); | ||
if (!debugserverPort) { return null; } | ||
|
||
dbgConfig.iosDebugserverPort = debugserverPort; | ||
|
||
dbgConfig.preRunCommands = (dbgConfig.preRunCommands instanceof Array) ? dbgConfig.preRunCommands : []; | ||
dbgConfig.preRunCommands.push(`script lldb.target.module[0].SetPlatformFileSpec(lldb.SBFileSpec('${platformPath}'))`); | ||
dbgConfig.preRunCommands.push(`process connect connect://127.0.0.1:${debugserverPort}`); | ||
|
||
// iOS 17+ uses Apple LLDB directly to create and attach to the debugserver, | ||
// below iOS 17 spawn debugserver with ios-deploy | ||
let iosMajorVersion = dbgConfig.iosTarget.version.split('.')[0] as number; | ||
if (iosMajorVersion < 17) { | ||
let debugserverPort = await targetCommand.deviceDebugserver({ | ||
target: target as Device, | ||
}); | ||
if (!debugserverPort) { return null; } | ||
|
||
dbgConfig.iosDebugserverPort = debugserverPort; | ||
dbgConfig.preRunCommands.push(`process connect connect://127.0.0.1:${debugserverPort}`); | ||
} else { | ||
// launch the app via devicectl | ||
await _execFile( | ||
'xcrun', | ||
['devicectl', 'device', 'process', 'launch', '--device', target.udid, '--start-stopped', this.ensureBundleId(dbgConfig)], | ||
); | ||
|
||
// attach to the app via LLDB | ||
dbgConfig.processCreateCommands = (dbgConfig.postRunCommands instanceof Array) ? dbgConfig.processCreateCommands : []; | ||
// LLDB `device` command needs Apple's beta LLDB set as backend for CodeLLDB | ||
// e.g. set vscode://settings/lldb.library to /Applications/Xcode-beta.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/LLDB | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an interesting requirement and will hamper normal usage. Maybe we should find a way to specify this always dynamically for a debug session. Again, not directly for this PR, but as a future improvement. Until now, I believe this was optional and the in-built lldb version in CodeLLDB also used to work well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that it is an additional hurdle, but I can not think of an easy or clean way to programmatically set this, since we'd be messing with the settings of another extension, and the path to Apple's LLDB library might also vary? |
||
dbgConfig.processCreateCommands.push(`script lldb.debugger.HandleCommand("device select ${target.udid}")`); | ||
// using detour with `script` command, as direct evocation causes CodeLLDB to crash at the moment | ||
// probably due to a bug in CodeLLDB / unusal exit results from the `device` command | ||
let processName = path.basename(platformPath).split('.')[0]; | ||
dbgConfig.processCreateCommands.push(`script lldb.debugger.HandleCommand("device process attach --name '${processName}'")`); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How reliable attaching by name? Can the process have different name than binary? Should we try attaching to pid instead of name, if we can get pid from the process launch command above? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure, pid might be cleaner. It gets returned as Cleanest option imo would be to use |
||
} | ||
} | ||
|
||
logger.log("resolved debug configuration", dbgConfig); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'd also need to replace
deviceInstall
, right? Just noting, we can do this incrementally in a different PR as well.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Installing the app still works with
ios-deploy
. Only getting the pid of a running process and spawning the debug server seems to requireDeveloperDiskImage.dmg
and hence is retired since iOS 17.Of course long-term it would be sort of cleaner to use
xcrun devicectl
instead as well, but this will only work with XCode >= 15 installed, so at the time beingios-deploy
actually provides the highest compatibility.