vscode-ios-debug icon indicating copy to clipboard operation
vscode-ios-debug copied to clipboard

Add support for watchOS simulator

Open FelixLisczyk opened this issue 7 months ago • 7 comments

Hi,

I'm trying to set up a development environment for iOS, macOS, and watchOS development in VS Code. I enjoy using this extension for launching and debugging iOS apps. macOS apps also work great because I can attach VS Code to the executable directly.

I'm currently struggling to get other simulators like watchOS to work. I've tried to replicate the workflow by creating tasks and launch configurations in VS Code. This involves multiple steps (booting the simulator, installing the app, launching the app), and the simulator creates a new app directory for every run. This forces me to update the executable path in my launch.json file every time I run the app.

Since this extension already handles the complexity for iOS simulators, I'm wondering if it would be feasible to support other simulator platforms like watchOS (and maybe tvOS) as well. Thank you for your consideration!

FelixLisczyk avatar Nov 27 '23 11:11 FelixLisczyk

Yes, we should be able to make some of the things work with other simulators or devices, though I've never directly worked with watchOS. Could you please explain your setup on what all needs to be done to attach vscode to watchOS simulator and we can see what all needs to be done in the extension to incorporate that?

nisargjhaveri avatar Nov 27 '23 18:11 nisargjhaveri

Yeah, thanks! I've created the following tasks to build the app, boot the simulator, install and launch the app:

tasks.json

{
  "version": "2.0.0",
  "options": {
    "env": {
      "WATCH_SIM_UUID": "25BC9961-2AF3-40A6-BCF5-EDF0843299F8" // Run `xcrun simctl list` to retrieve the simulator's UUID
    }
  },
  "tasks": [
    {
      "label": "Build watchOS App",
      "type": "shell",
      "command": "xcodebuild",
      "args": [
        "-scheme",
        "Demo_watchOS",
        "-configuration",
        "Debug",
        "-sdk",
        "watchsimulator",
        "-derivedDataPath",
        "${workspaceFolder}/.build-xcode",
        "-allowProvisioningUpdates",
        "build"
      ],
      "group": {
        "kind": "build"
      }
    },
    {
      "label": "Boot watchOS Simulator",
      "type": "shell",
      "command": "xcrun simctl boot ${WATCH_SIM_UUID} && sleep 10 || echo 0", // Ignore error if the simulator is already booted
      "dependsOn": "Build watchOS App"
    },
    {
      "label": "Install watchOS App in Simulator",
      "type": "shell",
      "command": "xcrun",
      "args": [
        "simctl",
        "install",
        "booted",
        "${workspaceFolder}/.build-xcode/Build/Products/Debug-watchsimulator/Demo_watchOS.app"
      ],
      "dependsOn": "Boot watchOS Simulator"
    },
    {
      "label": "Launch watchOS App in Simulator",
      "type": "shell",
      "command": "xcrun",
      "args": [
        "simctl",
        "launch",
        "--terminate-running-process",
        "--console-pty",
        "${WATCH_SIM_UUID}",
        "dev.mt.Demo-iOS.watchkitapp"
      ],
      "dependsOn": "Install watchOS App in Simulator",
      "problemMatcher": []
    }
  ]
}

After the last task has finished, I open Simulator.app and see my app running. Console output also works. The tricky part is to attach the debugger to the watchOS simulator. There are two possible ways:

launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "watchOS - Attach to Binary",
      "type": "lldb",
      "request": "attach",
      "program": "~/Library/Developer/CoreSimulator/Devices/25BC9961-2AF3-40A6-BCF5-EDF0843299F8/data/Containers/Bundle/Application/534A34BE-B613-4035-B68E-7DE3E31BE3E4/Demo_watchOS.app/Demo_watchOS"
    },
    {
      "name": "watchOS - Attach to Process ID",
      "type": "lldb",
      "request": "attach",
      "pid": "${command:pickProcess}"
    }
  ]
}

The first configuration attaches the debugger to the app binary inside the simulator directory. The problem is that the second UUID (after Application/) changes on every run.

The second configuration attaches the debugger to the app's process ID. simctl launch prints this ID into the terminal. ${command:pickProcess} opens a dialog that allows me to pick the correct process.

Currently, I have to run the "Launch watchOS App in Simulator" task and the launch configuration separately. I've tried to run the task as part of the launch configuration and parse the process ID with the Tasks Shell Input extension:

launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "watchOS - Attach to Process ID",
      "type": "lldb",
      "request": "attach",
      "pid": "${input:WatchPID}",
      "preLaunchTask": "Launch watchOS App in Simulator"
    }
  ],
  "inputs": [
    {
      "id": "WatchPID",
      "type": "command",
      "command": "shellCommand.execute",
      "args": {
        "command": "pgrep 'Demo_watchOS'",
        "useFirstResult": true
      }
    }
  ]
}

The problem is that the pid value is evaluated before the preLaunchTask runs. This causes my pgrep command to fail because the process is not yet running. There is a open bug ticket for this issue.

FelixLisczyk avatar Nov 28 '23 17:11 FelixLisczyk

Hi, are there any updates on this issue? I would be happy to help with testing.

FelixLisczyk avatar Dec 28 '23 15:12 FelixLisczyk

The steps you described above are very similar to how we work with iOS simulators. I expect we should be able to support watchOS simulator as well with some changes. Though I haven't been able to look into it.

How would we support debugging on watchos devices?

nisargjhaveri avatar Dec 29 '23 19:12 nisargjhaveri

I haven't tried to install or debug apps on my Apple Watch using VS Code yet.

How does your extension handle physical iOS devices? I can check if this approach also works for the Apple Watch.

FelixLisczyk avatar Dec 30 '23 14:12 FelixLisczyk

We internally use ios-deploy for most of the steps, e.g. install and launch the app, starting a debugserver on the device. And use the debugserver port to attach the debugger. I expect install should work fine, not sure how the debugging would work.

nisargjhaveri avatar Dec 30 '23 19:12 nisargjhaveri

Thanks for the info! I've tried to use ios-deploy to install my watch app but it looks like watchOS is not supported at the moment.

ios-deploy[94208:6981399] [ !! ] Error 0xe8000080: This application does not support this kind of device. AMDeviceSecureInstallApplication(0, device, url, options, install_callback, 0)

I also didn't find any command line utilities from Apple (outside of Xcode) to install apps on real hardware.

It would be more than enough for me if your extension supported the Apple Watch simulator. Debugging on a physical Apple Watch is very slow and unstable, even in Xcode.

FelixLisczyk avatar Dec 31 '23 15:12 FelixLisczyk