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