1 //===-- PlatformAppleSimulator.cpp ----------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "PlatformAppleSimulator.h" 10 11 #if defined(__APPLE__) 12 #include <dlfcn.h> 13 #endif 14 15 #include "lldb/Core/Module.h" 16 #include "lldb/Core/PluginManager.h" 17 #include "lldb/Host/HostInfo.h" 18 #include "lldb/Host/PseudoTerminal.h" 19 #include "lldb/Target/Process.h" 20 #include "lldb/Utility/LLDBAssert.h" 21 #include "lldb/Utility/LLDBLog.h" 22 #include "lldb/Utility/Log.h" 23 #include "lldb/Utility/Status.h" 24 #include "lldb/Utility/StreamString.h" 25 26 #include "llvm/Support/Threading.h" 27 28 #include <mutex> 29 #include <thread> 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 #if !defined(__APPLE__) 35 #define UNSUPPORTED_ERROR ("Apple simulators aren't supported on this platform") 36 #endif 37 38 /// Default Constructor 39 PlatformAppleSimulator::PlatformAppleSimulator( 40 const char *class_name, const char *description, ConstString plugin_name, 41 llvm::Triple::OSType preferred_os, 42 llvm::SmallVector<llvm::StringRef, 4> supported_triples, 43 llvm::StringRef sdk, lldb_private::XcodeSDK::Type sdk_type, 44 CoreSimulatorSupport::DeviceType::ProductFamilyID kind) 45 : PlatformDarwin(true), m_class_name(class_name), 46 m_description(description), m_plugin_name(plugin_name), m_kind(kind), 47 m_os_type(preferred_os), m_supported_triples(supported_triples), 48 m_sdk(sdk), m_sdk_type(sdk_type) {} 49 50 /// Destructor. 51 /// 52 /// The destructor is virtual since this class is designed to be 53 /// inherited from by the plug-in instance. 54 PlatformAppleSimulator::~PlatformAppleSimulator() = default; 55 56 lldb_private::Status PlatformAppleSimulator::LaunchProcess( 57 lldb_private::ProcessLaunchInfo &launch_info) { 58 #if defined(__APPLE__) 59 LoadCoreSimulator(); 60 CoreSimulatorSupport::Device device(GetSimulatorDevice()); 61 62 if (device.GetState() != CoreSimulatorSupport::Device::State::Booted) { 63 Status boot_err; 64 device.Boot(boot_err); 65 if (boot_err.Fail()) 66 return boot_err; 67 } 68 69 auto spawned = device.Spawn(launch_info); 70 71 if (spawned) { 72 launch_info.SetProcessID(spawned.GetPID()); 73 return Status(); 74 } else 75 return spawned.GetError(); 76 #else 77 Status err; 78 err.SetErrorString(UNSUPPORTED_ERROR); 79 return err; 80 #endif 81 } 82 83 void PlatformAppleSimulator::GetStatus(Stream &strm) { 84 Platform::GetStatus(strm); 85 if (!m_sdk.empty()) 86 strm << " SDK Path: \"" << m_sdk << "\"\n"; 87 else 88 strm << " SDK Path: error: unable to locate SDK\n"; 89 90 #if defined(__APPLE__) 91 // This will get called by subclasses, so just output status on the current 92 // simulator 93 PlatformAppleSimulator::LoadCoreSimulator(); 94 95 std::string developer_dir = HostInfo::GetXcodeDeveloperDirectory().GetPath(); 96 CoreSimulatorSupport::DeviceSet devices = 97 CoreSimulatorSupport::DeviceSet::GetAvailableDevices( 98 developer_dir.c_str()); 99 const size_t num_devices = devices.GetNumDevices(); 100 if (num_devices) { 101 strm.Printf("Available devices:\n"); 102 for (size_t i = 0; i < num_devices; ++i) { 103 CoreSimulatorSupport::Device device = devices.GetDeviceAtIndex(i); 104 strm << " " << device.GetUDID() << ": " << device.GetName() << "\n"; 105 } 106 107 if (m_device.hasValue() && m_device->operator bool()) { 108 strm << "Current device: " << m_device->GetUDID() << ": " 109 << m_device->GetName(); 110 if (m_device->GetState() == CoreSimulatorSupport::Device::State::Booted) { 111 strm << " state = booted"; 112 } 113 strm << "\nType \"platform connect <ARG>\" where <ARG> is a device " 114 "UDID or a device name to disconnect and connect to a " 115 "different device.\n"; 116 117 } else { 118 strm << "No current device is selected, \"platform connect <ARG>\" " 119 "where <ARG> is a device UDID or a device name to connect to " 120 "a specific device.\n"; 121 } 122 123 } else { 124 strm << "No devices are available.\n"; 125 } 126 #else 127 strm << UNSUPPORTED_ERROR; 128 #endif 129 } 130 131 Status PlatformAppleSimulator::ConnectRemote(Args &args) { 132 #if defined(__APPLE__) 133 Status error; 134 if (args.GetArgumentCount() == 1) { 135 if (m_device) 136 DisconnectRemote(); 137 PlatformAppleSimulator::LoadCoreSimulator(); 138 const char *arg_cstr = args.GetArgumentAtIndex(0); 139 if (arg_cstr) { 140 std::string arg_str(arg_cstr); 141 std::string developer_dir = HostInfo::GetXcodeDeveloperDirectory().GetPath(); 142 CoreSimulatorSupport::DeviceSet devices = 143 CoreSimulatorSupport::DeviceSet::GetAvailableDevices( 144 developer_dir.c_str()); 145 devices.ForEach( 146 [this, &arg_str](const CoreSimulatorSupport::Device &device) -> bool { 147 if (arg_str == device.GetUDID() || arg_str == device.GetName()) { 148 m_device = device; 149 return false; // Stop iterating 150 } else { 151 return true; // Keep iterating 152 } 153 }); 154 if (!m_device) 155 error.SetErrorStringWithFormat( 156 "no device with UDID or name '%s' was found", arg_cstr); 157 } 158 } else { 159 error.SetErrorString("this command take a single UDID argument of the " 160 "device you want to connect to."); 161 } 162 return error; 163 #else 164 Status err; 165 err.SetErrorString(UNSUPPORTED_ERROR); 166 return err; 167 #endif 168 } 169 170 Status PlatformAppleSimulator::DisconnectRemote() { 171 #if defined(__APPLE__) 172 m_device.reset(); 173 return Status(); 174 #else 175 Status err; 176 err.SetErrorString(UNSUPPORTED_ERROR); 177 return err; 178 #endif 179 } 180 181 lldb::ProcessSP 182 PlatformAppleSimulator::DebugProcess(ProcessLaunchInfo &launch_info, 183 Debugger &debugger, Target &target, 184 Status &error) { 185 #if defined(__APPLE__) 186 ProcessSP process_sp; 187 // Make sure we stop at the entry point 188 launch_info.GetFlags().Set(eLaunchFlagDebug); 189 // We always launch the process we are going to debug in a separate process 190 // group, since then we can handle ^C interrupts ourselves w/o having to 191 // worry about the target getting them as well. 192 launch_info.SetLaunchInSeparateProcessGroup(true); 193 194 error = LaunchProcess(launch_info); 195 if (error.Success()) { 196 if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { 197 ProcessAttachInfo attach_info(launch_info); 198 process_sp = Attach(attach_info, debugger, &target, error); 199 if (process_sp) { 200 launch_info.SetHijackListener(attach_info.GetHijackListener()); 201 202 // Since we attached to the process, it will think it needs to detach 203 // if the process object just goes away without an explicit call to 204 // Process::Kill() or Process::Detach(), so let it know to kill the 205 // process if this happens. 206 process_sp->SetShouldDetach(false); 207 208 // If we didn't have any file actions, the pseudo terminal might have 209 // been used where the secondary side was given as the file to open for 210 // stdin/out/err after we have already opened the primary so we can 211 // read/write stdin/out/err. 212 int pty_fd = launch_info.GetPTY().ReleasePrimaryFileDescriptor(); 213 if (pty_fd != PseudoTerminal::invalid_fd) { 214 process_sp->SetSTDIOFileDescriptor(pty_fd); 215 } 216 } 217 } 218 } 219 220 return process_sp; 221 #else 222 return ProcessSP(); 223 #endif 224 } 225 226 FileSpec PlatformAppleSimulator::GetCoreSimulatorPath() { 227 #if defined(__APPLE__) 228 std::lock_guard<std::mutex> guard(m_core_sim_path_mutex); 229 if (!m_core_simulator_framework_path.hasValue()) { 230 m_core_simulator_framework_path = 231 FileSpec("/Library/Developer/PrivateFrameworks/CoreSimulator.framework/" 232 "CoreSimulator"); 233 FileSystem::Instance().Resolve(*m_core_simulator_framework_path); 234 } 235 return m_core_simulator_framework_path.getValue(); 236 #else 237 return FileSpec(); 238 #endif 239 } 240 241 void PlatformAppleSimulator::LoadCoreSimulator() { 242 #if defined(__APPLE__) 243 static llvm::once_flag g_load_core_sim_flag; 244 llvm::call_once(g_load_core_sim_flag, [this] { 245 const std::string core_sim_path(GetCoreSimulatorPath().GetPath()); 246 if (core_sim_path.size()) 247 dlopen(core_sim_path.c_str(), RTLD_LAZY); 248 }); 249 #endif 250 } 251 252 #if defined(__APPLE__) 253 CoreSimulatorSupport::Device PlatformAppleSimulator::GetSimulatorDevice() { 254 if (!m_device.hasValue()) { 255 const CoreSimulatorSupport::DeviceType::ProductFamilyID dev_id = m_kind; 256 std::string developer_dir = HostInfo::GetXcodeDeveloperDirectory().GetPath(); 257 m_device = CoreSimulatorSupport::DeviceSet::GetAvailableDevices( 258 developer_dir.c_str()) 259 .GetFanciest(dev_id); 260 } 261 262 if (m_device.hasValue()) 263 return m_device.getValue(); 264 else 265 return CoreSimulatorSupport::Device(); 266 } 267 #endif 268 269 std::vector<ArchSpec> PlatformAppleSimulator::GetSupportedArchitectures() { 270 std::vector<ArchSpec> result(m_supported_triples.size()); 271 llvm::transform(m_supported_triples, result.begin(), 272 [](llvm::StringRef triple) { return ArchSpec(triple); }); 273 return result; 274 } 275 276 PlatformSP PlatformAppleSimulator::CreateInstance( 277 const char *class_name, const char *description, ConstString plugin_name, 278 llvm::SmallVector<llvm::Triple::ArchType, 4> supported_arch, 279 llvm::Triple::OSType preferred_os, 280 llvm::SmallVector<llvm::Triple::OSType, 4> supported_os, 281 llvm::SmallVector<llvm::StringRef, 4> supported_triples, 282 llvm::StringRef sdk, lldb_private::XcodeSDK::Type sdk_type, 283 CoreSimulatorSupport::DeviceType::ProductFamilyID kind, bool force, 284 const ArchSpec *arch) { 285 Log *log = GetLog(LLDBLog::Platform); 286 if (log) { 287 const char *arch_name; 288 if (arch && arch->GetArchitectureName()) 289 arch_name = arch->GetArchitectureName(); 290 else 291 arch_name = "<null>"; 292 293 const char *triple_cstr = 294 arch ? arch->GetTriple().getTriple().c_str() : "<null>"; 295 296 LLDB_LOGF(log, "%s::%s(force=%s, arch={%s,%s})", class_name, __FUNCTION__, 297 force ? "true" : "false", arch_name, triple_cstr); 298 } 299 300 bool create = force; 301 if (!create && arch && arch->IsValid()) { 302 if (std::count(supported_arch.begin(), supported_arch.end(), 303 arch->GetMachine())) { 304 const llvm::Triple &triple = arch->GetTriple(); 305 switch (triple.getVendor()) { 306 case llvm::Triple::Apple: 307 create = true; 308 break; 309 310 #if defined(__APPLE__) 311 // Only accept "unknown" for the vendor if the host is Apple and if 312 // "unknown" wasn't specified (it was just returned because it was NOT 313 // specified) 314 case llvm::Triple::UnknownVendor: 315 create = !arch->TripleVendorWasSpecified(); 316 break; 317 #endif 318 default: 319 break; 320 } 321 322 if (create) { 323 if (std::count(supported_os.begin(), supported_os.end(), triple.getOS())) 324 create = true; 325 #if defined(__APPLE__) 326 // Only accept "unknown" for the OS if the host is Apple and it 327 // "unknown" wasn't specified (it was just returned because it was NOT 328 // specified) 329 else if (triple.getOS() == llvm::Triple::UnknownOS) 330 create = !arch->TripleOSWasSpecified(); 331 #endif 332 else 333 create = false; 334 } 335 } 336 } 337 if (create) { 338 LLDB_LOGF(log, "%s::%s() creating platform", class_name, __FUNCTION__); 339 340 return PlatformSP(new PlatformAppleSimulator( 341 class_name, description, plugin_name, preferred_os, supported_triples, 342 sdk, sdk_type, kind)); 343 } 344 345 LLDB_LOGF(log, "%s::%s() aborting creation of platform", class_name, 346 __FUNCTION__); 347 348 return PlatformSP(); 349 } 350 351 Status PlatformAppleSimulator::ResolveExecutable( 352 const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, 353 const FileSpecList *module_search_paths_ptr) { 354 Status error; 355 // Nothing special to do here, just use the actual file and architecture 356 357 ModuleSpec resolved_module_spec(module_spec); 358 359 // If we have "ls" as the exe_file, resolve the executable loation based on 360 // the current path variables 361 // TODO: resolve bare executables in the Platform SDK 362 // if (!resolved_exe_file.Exists()) 363 // resolved_exe_file.ResolveExecutableLocation (); 364 365 // Resolve any executable within a bundle on MacOSX 366 // TODO: verify that this handles shallow bundles, if not then implement one 367 // ourselves 368 Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec()); 369 370 if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) { 371 if (resolved_module_spec.GetArchitecture().IsValid()) { 372 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 373 NULL, NULL, NULL); 374 375 if (exe_module_sp && exe_module_sp->GetObjectFile()) 376 return error; 377 exe_module_sp.reset(); 378 } 379 // No valid architecture was specified or the exact ARM slice wasn't found 380 // so ask the platform for the architectures that we should be using (in 381 // the correct order) and see if we can find a match that way 382 StreamString arch_names; 383 llvm::ListSeparator LS; 384 ArchSpec platform_arch; 385 for (const ArchSpec &arch : GetSupportedArchitectures()) { 386 resolved_module_spec.GetArchitecture() = arch; 387 388 // Only match x86 with x86 and x86_64 with x86_64... 389 if (!module_spec.GetArchitecture().IsValid() || 390 module_spec.GetArchitecture().GetCore() == 391 resolved_module_spec.GetArchitecture().GetCore()) { 392 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 393 NULL, NULL, NULL); 394 // Did we find an executable using one of the 395 if (error.Success()) { 396 if (exe_module_sp && exe_module_sp->GetObjectFile()) 397 break; 398 else 399 error.SetErrorToGenericError(); 400 } 401 402 arch_names << LS << platform_arch.GetArchitectureName(); 403 } 404 } 405 406 if (error.Fail() || !exe_module_sp) { 407 if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) { 408 error.SetErrorStringWithFormatv( 409 "'{0}' doesn't contain any '{1}' platform architectures: {2}", 410 resolved_module_spec.GetFileSpec(), GetPluginName(), 411 arch_names.GetString()); 412 } else { 413 error.SetErrorStringWithFormat( 414 "'%s' is not readable", 415 resolved_module_spec.GetFileSpec().GetPath().c_str()); 416 } 417 } 418 } else { 419 error.SetErrorStringWithFormat("'%s' does not exist", 420 module_spec.GetFileSpec().GetPath().c_str()); 421 } 422 423 return error; 424 } 425 426 Status PlatformAppleSimulator::GetSymbolFile(const FileSpec &platform_file, 427 const UUID *uuid_ptr, 428 FileSpec &local_file) { 429 Status error; 430 char platform_file_path[PATH_MAX]; 431 if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { 432 char resolved_path[PATH_MAX]; 433 434 if (!m_sdk.empty()) { 435 ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", 436 m_sdk.str().c_str(), platform_file_path); 437 438 // First try in the SDK and see if the file is in there 439 local_file.SetFile(resolved_path, FileSpec::Style::native); 440 FileSystem::Instance().Resolve(local_file); 441 if (FileSystem::Instance().Exists(local_file)) 442 return error; 443 444 // Else fall back to the actual path itself 445 local_file.SetFile(platform_file_path, FileSpec::Style::native); 446 FileSystem::Instance().Resolve(local_file); 447 if (FileSystem::Instance().Exists(local_file)) 448 return error; 449 } 450 error.SetErrorStringWithFormatv( 451 "unable to locate a platform file for '{0}' in platform '{1}'", 452 platform_file_path, GetPluginName()); 453 } else { 454 error.SetErrorString("invalid platform file argument"); 455 } 456 return error; 457 } 458 459 Status PlatformAppleSimulator::GetSharedModule( 460 const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, 461 const FileSpecList *module_search_paths_ptr, 462 llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr) { 463 // For iOS/tvOS/watchOS, the SDK files are all cached locally on the 464 // host system. So first we ask for the file in the cached SDK, then 465 // we attempt to get a shared module for the right architecture with 466 // the right UUID. 467 Status error; 468 ModuleSpec platform_module_spec(module_spec); 469 const FileSpec &platform_file = module_spec.GetFileSpec(); 470 error = GetSymbolFile(platform_file, module_spec.GetUUIDPtr(), 471 platform_module_spec.GetFileSpec()); 472 if (error.Success()) { 473 error = ResolveExecutable(platform_module_spec, module_sp, 474 module_search_paths_ptr); 475 } else { 476 const bool always_create = false; 477 error = ModuleList::GetSharedModule(module_spec, module_sp, 478 module_search_paths_ptr, old_modules, 479 did_create_ptr, always_create); 480 } 481 if (module_sp) 482 module_sp->SetPlatformFileSpec(platform_file); 483 484 return error; 485 } 486 487 uint32_t PlatformAppleSimulator::FindProcesses( 488 const ProcessInstanceInfoMatch &match_info, 489 ProcessInstanceInfoList &process_infos) { 490 ProcessInstanceInfoList all_osx_process_infos; 491 // First we get all OSX processes 492 const uint32_t n = Host::FindProcesses(match_info, all_osx_process_infos); 493 494 // Now we filter them down to only the matching triples. 495 for (uint32_t i = 0; i < n; ++i) { 496 const ProcessInstanceInfo &proc_info = all_osx_process_infos[i]; 497 const llvm::Triple &triple = proc_info.GetArchitecture().GetTriple(); 498 if (triple.getOS() == m_os_type && 499 triple.getEnvironment() == llvm::Triple::Simulator) { 500 process_infos.push_back(proc_info); 501 } 502 } 503 return process_infos.size(); 504 } 505 506 /// Whether to skip creating a simulator platform. 507 static bool shouldSkipSimulatorPlatform(bool force, const ArchSpec *arch) { 508 // If the arch is known not to specify a simulator environment, skip creating 509 // the simulator platform (we can create it later if there's a matching arch). 510 // This avoids very slow xcrun queries for non-simulator archs (the slowness 511 // is due to xcrun not caching negative queries (rdar://74882205)). 512 return !force && arch && arch->IsValid() && 513 !arch->TripleEnvironmentWasSpecified(); 514 } 515 516 static llvm::StringRef GetXcodeSDKDir(std::string preferred, 517 std::string secondary) { 518 llvm::StringRef sdk; 519 sdk = HostInfo::GetXcodeSDKPath(XcodeSDK(std::move(preferred))); 520 if (sdk.empty()) 521 sdk = HostInfo::GetXcodeSDKPath(XcodeSDK(std::move(secondary))); 522 return sdk; 523 } 524 525 static const char *g_ios_plugin_name = "ios-simulator"; 526 static const char *g_ios_description = "iPhone simulator platform plug-in."; 527 528 /// IPhone Simulator Plugin. 529 struct PlatformiOSSimulator { 530 static void Initialize() { 531 PluginManager::RegisterPlugin(g_ios_plugin_name, g_ios_description, 532 PlatformiOSSimulator::CreateInstance); 533 } 534 535 static void Terminate() { 536 PluginManager::UnregisterPlugin(PlatformiOSSimulator::CreateInstance); 537 } 538 539 static PlatformSP CreateInstance(bool force, const ArchSpec *arch) { 540 if (shouldSkipSimulatorPlatform(force, arch)) 541 return nullptr; 542 llvm::StringRef sdk; 543 sdk = HostInfo::GetXcodeSDKPath(XcodeSDK("iPhoneSimulator.Internal.sdk")); 544 if (sdk.empty()) 545 sdk = HostInfo::GetXcodeSDKPath(XcodeSDK("iPhoneSimulator.sdk")); 546 547 return PlatformAppleSimulator::CreateInstance( 548 "PlatformiOSSimulator", g_ios_description, 549 ConstString(g_ios_plugin_name), 550 {llvm::Triple::aarch64, llvm::Triple::x86_64, llvm::Triple::x86}, 551 llvm::Triple::IOS, 552 {// Deprecated, but still support Darwin for historical reasons. 553 llvm::Triple::Darwin, llvm::Triple::MacOSX, 554 // IOS is not used for simulator triples, but accept it just in 555 // case. 556 llvm::Triple::IOS}, 557 { 558 #ifdef __APPLE__ 559 #if __arm64__ 560 "arm64e-apple-ios-simulator", "arm64-apple-ios-simulator", 561 "x86_64-apple-ios-simulator", "x86_64h-apple-ios-simulator", 562 #else 563 "x86_64h-apple-ios-simulator", "x86_64-apple-ios-simulator", 564 "i386-apple-ios-simulator", 565 #endif 566 #endif 567 }, 568 GetXcodeSDKDir("iPhoneSimulator.Internal.sdk", "iPhoneSimulator.sdk"), 569 XcodeSDK::Type::iPhoneSimulator, 570 CoreSimulatorSupport::DeviceType::ProductFamilyID::iPhone, force, arch); 571 } 572 }; 573 574 static const char *g_tvos_plugin_name = "tvos-simulator"; 575 static const char *g_tvos_description = "tvOS simulator platform plug-in."; 576 577 /// Apple TV Simulator Plugin. 578 struct PlatformAppleTVSimulator { 579 static void Initialize() { 580 PluginManager::RegisterPlugin(g_tvos_plugin_name, g_tvos_description, 581 PlatformAppleTVSimulator::CreateInstance); 582 } 583 584 static void Terminate() { 585 PluginManager::UnregisterPlugin(PlatformAppleTVSimulator::CreateInstance); 586 } 587 588 static PlatformSP CreateInstance(bool force, const ArchSpec *arch) { 589 if (shouldSkipSimulatorPlatform(force, arch)) 590 return nullptr; 591 return PlatformAppleSimulator::CreateInstance( 592 "PlatformAppleTVSimulator", g_tvos_description, 593 ConstString(g_tvos_plugin_name), 594 {llvm::Triple::aarch64, llvm::Triple::x86_64}, llvm::Triple::TvOS, 595 {llvm::Triple::TvOS}, 596 { 597 #ifdef __APPLE__ 598 #if __arm64__ 599 "arm64e-apple-tvos-simulator", "arm64-apple-tvos-simulator", 600 "x86_64h-apple-tvos-simulator", "x86_64-apple-tvos-simulator", 601 #else 602 "x86_64h-apple-tvos-simulator", "x86_64-apple-tvos-simulator", 603 #endif 604 #endif 605 }, 606 GetXcodeSDKDir("AppleTVSimulator.Internal.sdk", "AppleTVSimulator.sdk"), 607 XcodeSDK::Type::AppleTVSimulator, 608 CoreSimulatorSupport::DeviceType::ProductFamilyID::appleTV, force, 609 arch); 610 } 611 }; 612 613 614 static const char *g_watchos_plugin_name = "watchos-simulator"; 615 static const char *g_watchos_description = 616 "Apple Watch simulator platform plug-in."; 617 618 /// Apple Watch Simulator Plugin. 619 struct PlatformAppleWatchSimulator { 620 static void Initialize() { 621 PluginManager::RegisterPlugin(g_watchos_plugin_name, g_watchos_description, 622 PlatformAppleWatchSimulator::CreateInstance); 623 } 624 625 static void Terminate() { 626 PluginManager::UnregisterPlugin( 627 PlatformAppleWatchSimulator::CreateInstance); 628 } 629 630 static PlatformSP CreateInstance(bool force, const ArchSpec *arch) { 631 if (shouldSkipSimulatorPlatform(force, arch)) 632 return nullptr; 633 return PlatformAppleSimulator::CreateInstance( 634 "PlatformAppleWatchSimulator", g_watchos_description, 635 ConstString(g_watchos_plugin_name), 636 {llvm::Triple::aarch64, llvm::Triple::x86_64, llvm::Triple::x86}, 637 llvm::Triple::WatchOS, {llvm::Triple::WatchOS}, 638 { 639 #ifdef __APPLE__ 640 #if __arm64__ 641 "arm64e-apple-watchos-simulator", "arm64-apple-watchos-simulator", 642 #else 643 "x86_64-apple-watchos-simulator", "x86_64h-apple-watchos-simulator", 644 "i386-apple-watchos-simulator", 645 #endif 646 #endif 647 }, 648 GetXcodeSDKDir("WatchSimulator.Internal.sdk", "WatchSimulator.sdk"), 649 XcodeSDK::Type::WatchSimulator, 650 CoreSimulatorSupport::DeviceType::ProductFamilyID::appleWatch, force, 651 arch); 652 } 653 }; 654 655 656 static unsigned g_initialize_count = 0; 657 658 // Static Functions 659 void PlatformAppleSimulator::Initialize() { 660 if (g_initialize_count++ == 0) { 661 PlatformDarwin::Initialize(); 662 PlatformiOSSimulator::Initialize(); 663 PlatformAppleTVSimulator::Initialize(); 664 PlatformAppleWatchSimulator::Initialize(); 665 } 666 } 667 668 void PlatformAppleSimulator::Terminate() { 669 if (g_initialize_count > 0) 670 if (--g_initialize_count == 0) { 671 PlatformAppleWatchSimulator::Terminate(); 672 PlatformAppleTVSimulator::Terminate(); 673 PlatformiOSSimulator::Terminate(); 674 PlatformDarwin::Terminate(); 675 } 676 } 677 678