Launch Playgound project on simulator

This commit is contained in:
Kylmakalle 2024-09-27 22:42:22 +03:00
parent 25ef69ffe1
commit f87a6c6706
2 changed files with 184 additions and 0 deletions

View File

@ -15,3 +15,17 @@ Small app to quickly iterate on components testing without building an entire me
```shell
./generate_project.py
```
## Run generated project on simulator
### From root
```shell
./Swiftgram/Playground/launch_on_simulator.py
```
### From current directory
```shell
./launch_on_simulator.py
```

View File

@ -0,0 +1,170 @@
#!/usr/bin/env python3
import subprocess
import json
import os
import time
def find_app(start_path):
for root, dirs, _ in os.walk(start_path):
for dir in dirs:
if dir.endswith(".app"):
return os.path.join(root, dir)
return None
def ensure_simulator_booted(device_name) -> str:
# List all devices
devices_json = subprocess.check_output(
["xcrun", "simctl", "list", "devices", "--json"]
).decode()
devices = json.loads(devices_json)
for runtime in devices["devices"]:
for device in devices["devices"][runtime]:
if device["name"] == device_name:
device_udid = device["udid"]
if device["state"] == "Booted":
print(f"Simulator {device_name} is already booted.")
return device_udid
break
if device_udid:
break
if not device_udid:
raise Exception(f"Simulator {device_name} not found")
# Boot the device
print(f"Booting simulator {device_name}...")
subprocess.run(["xcrun", "simctl", "boot", device_udid], check=True)
# Wait for the device to finish booting
print("Waiting for simulator to finish booting...")
while True:
boot_status = subprocess.check_output(
["xcrun", "simctl", "list", "devices"]
).decode()
if f"{device_name} ({device_udid}) (Booted)" in boot_status:
break
time.sleep(0.5)
print(f"Simulator {device_name} is now booted.")
return device_udid
def build_and_run_xcode_project(project_path, scheme_name, destination):
# Change to the directory containing the .xcodeproj file
os.chdir(os.path.dirname(project_path))
# Build the project
build_command = [
"xcodebuild",
"-project",
project_path,
"-scheme",
scheme_name,
"-destination",
destination,
"-sdk",
"iphonesimulator",
"build",
]
try:
subprocess.run(build_command, check=True)
print("Build successful!")
except subprocess.CalledProcessError as e:
print(f"Build failed with error: {e}")
return
# Get the bundle identifier and app path
settings_command = [
"xcodebuild",
"-project",
project_path,
"-scheme",
scheme_name,
"-sdk",
"iphonesimulator",
"-showBuildSettings",
]
try:
result = subprocess.run(
settings_command, capture_output=True, text=True, check=True
)
settings = result.stdout.split("\n")
bundle_id = next(
line.split("=")[1].strip()
for line in settings
if "PRODUCT_BUNDLE_IDENTIFIER" in line
)
build_dir = next(
line.split("=")[1].strip()
for line in settings
if "TARGET_BUILD_DIR" in line
)
app_path = find_app(build_dir)
if not app_path:
print(f"Could not find .app file in {build_dir}")
return
print(f"Found app at: {app_path}")
print(f"Bundle identifier: {bundle_id}")
print(f"App path: {app_path}")
except (subprocess.CalledProcessError, StopIteration) as e:
print(f"Failed to get build settings: {e}")
return
device_udid = ensure_simulator_booted(simulator_name)
# Install the app on the simulator
install_command = ["xcrun", "simctl", "install", device_udid, app_path]
try:
subprocess.run(install_command, check=True)
print("App installed on simulator successfully!")
except subprocess.CalledProcessError as e:
print(f"Failed to install app on simulator: {e}")
return
# List installed apps
try:
listapps_cmd = "/usr/bin/xcrun simctl listapps booted | /usr/bin/plutil -convert json -r -o - -- -"
result = subprocess.run(
listapps_cmd, shell=True, capture_output=True, text=True, check=True
)
apps = json.loads(result.stdout)
if bundle_id in apps:
print(f"App {bundle_id} is installed on the simulator")
else:
print(f"App {bundle_id} is not installed on the simulator")
print("Installed apps:", list(apps.keys()))
except subprocess.CalledProcessError as e:
print(f"Failed to list apps: {e}")
except json.JSONDecodeError as e:
print(f"Failed to parse app list: {e}")
# Focus simulator
subprocess.run(["open", "-a", "Simulator"], check=True)
# Run the project on the simulator
run_command = ["xcrun", "simctl", "launch", "booted", bundle_id]
try:
subprocess.run(run_command, check=True)
print("Application launched in simulator!")
except subprocess.CalledProcessError as e:
print(f"Failed to launch application in simulator: {e}")
# Usage
current_script_dir = os.path.dirname(os.path.abspath(__file__))
project_path = os.path.join(current_script_dir, "Playground.xcodeproj")
scheme_name = "Playground"
simulator_name = "iPhone 15"
destination = f"platform=iOS Simulator,name={simulator_name},OS=latest"
if __name__ == "__main__":
build_and_run_xcode_project(project_path, scheme_name, destination)