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