@@ -373,84 +373,86 @@ static void ParseOSVersion(llvm::VersionTuple &version, NSString *Key) {
373
373
return g_developer_directory;
374
374
}
375
375
376
- llvm::Expected<std::string> GetXcodeSDK (XcodeSDK sdk) {
377
- XcodeSDK::Info info = sdk.Parse ();
378
- std::string sdk_name = XcodeSDK::GetCanonicalName (info);
379
- if (sdk_name.empty ())
380
- return llvm::createStringError (llvm::inconvertibleErrorCode (),
381
- " Unrecognized SDK type: " + sdk.GetString ());
376
+ static llvm::Expected<std::string>
377
+ xcrun (const std::string &sdk, llvm::ArrayRef<llvm::StringRef> arguments,
378
+ llvm::StringRef developer_dir = " " ) {
379
+ Args args;
380
+ if (!developer_dir.empty ()) {
381
+ args.AppendArgument (" /usr/bin/env" );
382
+ args.AppendArgument (" DEVELOPER_DIR=" + developer_dir.str ());
383
+ }
384
+ args.AppendArgument (" /usr/bin/xcrun" );
385
+ args.AppendArgument (" --sdk" );
386
+ args.AppendArgument (sdk);
387
+ for (auto arg: arguments)
388
+ args.AppendArgument (arg);
382
389
383
390
Log *log = GetLog (LLDBLog::Host);
391
+ if (log) {
392
+ std::string cmdstr;
393
+ args.GetCommandString (cmdstr);
394
+ log->Printf (" GetXcodeSDK() running shell cmd '%s'" , cmdstr.c_str ());
395
+ }
384
396
385
- auto xcrun = [](const std::string &sdk,
386
- llvm::StringRef developer_dir =
387
- " " ) -> llvm::Expected<std::string> {
388
- Args args;
389
- if (!developer_dir.empty ()) {
390
- args.AppendArgument (" /usr/bin/env" );
391
- args.AppendArgument (" DEVELOPER_DIR=" + developer_dir.str ());
392
- }
393
- args.AppendArgument (" /usr/bin/xcrun" );
394
- args.AppendArgument (" --show-sdk-path" );
395
- args.AppendArgument (" --sdk" );
396
- args.AppendArgument (sdk);
397
-
398
- Log *log = GetLog (LLDBLog::Host);
399
- if (log) {
400
- std::string cmdstr;
401
- args.GetCommandString (cmdstr);
402
- log->Printf (" GetXcodeSDK() running shell cmd '%s'" , cmdstr.c_str ());
403
- }
397
+ int status = 0 ;
398
+ int signo = 0 ;
399
+ std::string output_str;
400
+ // The first time after Xcode was updated or freshly installed,
401
+ // xcrun can take surprisingly long to build up its database.
402
+ auto timeout = std::chrono::seconds (60 );
403
+ bool run_in_shell = false ;
404
+ lldb_private::Status error = Host::RunShellCommand (
405
+ args, FileSpec (), &status, &signo, &output_str, timeout, run_in_shell);
406
+
407
+ // Check that xcrun returned something useful.
408
+ if (error.Fail ()) {
409
+ // Catastrophic error.
410
+ LLDB_LOG (log, " xcrun failed to execute: %s" , error.AsCString ());
411
+ return error.ToError ();
412
+ }
413
+ if (status != 0 ) {
414
+ // xcrun didn't find a matching SDK. Not an error, we'll try
415
+ // different spellings.
416
+ LLDB_LOG (log, " xcrun returned exit code %d" , status);
417
+ return " " ;
418
+ }
419
+ if (output_str.empty ()) {
420
+ LLDB_LOG (log, " xcrun returned no results" );
421
+ return " " ;
422
+ }
404
423
405
- int status = 0 ;
406
- int signo = 0 ;
407
- std::string output_str;
408
- // The first time after Xcode was updated or freshly installed,
409
- // xcrun can take surprisingly long to build up its database.
410
- auto timeout = std::chrono::seconds (60 );
411
- bool run_in_shell = false ;
412
- lldb_private::Status error = Host::RunShellCommand (
413
- args, FileSpec (), &status, &signo, &output_str, timeout, run_in_shell);
414
-
415
- // Check that xcrun returned something useful.
416
- if (error.Fail ()) {
417
- // Catastrophic error.
418
- LLDB_LOG (log, " xcrun failed to execute: %s" , error.AsCString ());
419
- return error.ToError ();
420
- }
421
- if (status != 0 ) {
422
- // xcrun didn't find a matching SDK. Not an error, we'll try
423
- // different spellings.
424
- LLDB_LOG (log, " xcrun returned exit code %d" , status);
425
- return " " ;
426
- }
427
- if (output_str.empty ()) {
428
- LLDB_LOG (log, " xcrun returned no results" );
429
- return " " ;
430
- }
424
+ // Convert to a StringRef so we can manipulate the string without modifying
425
+ // the underlying data.
426
+ llvm::StringRef output (output_str);
431
427
432
- // Convert to a StringRef so we can manipulate the string without modifying
433
- // the underlying data.
434
- llvm::StringRef output (output_str);
428
+ // Remove any trailing newline characters.
429
+ output = output.rtrim ();
435
430
436
- // Remove any trailing newline characters.
437
- output = output.rtrim ();
431
+ // Strip any leading newline characters and everything before them.
432
+ const size_t last_newline = output.rfind (' \n ' );
433
+ if (last_newline != llvm::StringRef::npos)
434
+ output = output.substr (last_newline + 1 );
438
435
439
- // Strip any leading newline characters and everything before them.
440
- const size_t last_newline = output.rfind (' \n ' );
441
- if (last_newline != llvm::StringRef::npos)
442
- output = output.substr (last_newline + 1 );
436
+ return output.str ();
437
+ }
443
438
444
- return output.str ();
445
- };
439
+ static llvm::Expected<std::string> GetXcodeSDK (XcodeSDK sdk) {
440
+ XcodeSDK::Info info = sdk.Parse ();
441
+ std::string sdk_name = XcodeSDK::GetCanonicalName (info);
442
+ if (sdk_name.empty ())
443
+ return llvm::createStringError (llvm::inconvertibleErrorCode (),
444
+ " Unrecognized SDK type: " + sdk.GetString ());
445
+
446
+ Log *log = GetLog (LLDBLog::Host);
446
447
447
448
auto find_sdk =
448
- [&xcrun](const std::string &sdk_name) -> llvm::Expected<std::string> {
449
+ [](const std::string &sdk_name) -> llvm::Expected<std::string> {
450
+ llvm::SmallVector<llvm::StringRef, 1 > show_sdk_path = {" --show-sdk-path" };
449
451
// Invoke xcrun with the developer dir specified in the environment.
450
452
std::string developer_dir = GetEnvDeveloperDir ();
451
453
if (!developer_dir.empty ()) {
452
454
// Don't fallback if DEVELOPER_DIR was set.
453
- return xcrun (sdk_name, developer_dir);
455
+ return xcrun (sdk_name, show_sdk_path, developer_dir);
454
456
}
455
457
456
458
// Invoke xcrun with the shlib dir.
@@ -461,7 +463,8 @@ static void ParseOSVersion(llvm::VersionTuple &version, NSString *Key) {
461
463
llvm::StringRef shlib_developer_dir =
462
464
llvm::sys::path::parent_path (contents_dir);
463
465
if (!shlib_developer_dir.empty ()) {
464
- auto sdk = xcrun (sdk_name, std::move (shlib_developer_dir));
466
+ auto sdk =
467
+ xcrun (sdk_name, show_sdk_path, std::move (shlib_developer_dir));
465
468
if (!sdk)
466
469
return sdk.takeError ();
467
470
if (!sdk->empty ())
@@ -471,7 +474,7 @@ static void ParseOSVersion(llvm::VersionTuple &version, NSString *Key) {
471
474
}
472
475
473
476
// Invoke xcrun without a developer dir as a last resort.
474
- return xcrun (sdk_name);
477
+ return xcrun (sdk_name, show_sdk_path );
475
478
};
476
479
477
480
auto path_or_err = find_sdk (sdk_name);
@@ -519,41 +522,69 @@ static void ParseOSVersion(llvm::VersionTuple &version, NSString *Key) {
519
522
return path;
520
523
}
521
524
522
- llvm::Expected<llvm::StringRef> HostInfoMacOSX::GetSDKRoot (SDKOptions options) {
523
- struct ErrorOrPath {
524
- std::string str;
525
- bool is_error;
526
- };
527
- static llvm::StringMap<ErrorOrPath> g_sdk_path;
528
- static std::mutex g_sdk_path_mutex;
525
+ namespace {
526
+ struct ErrorOrPath {
527
+ std::string str;
528
+ bool is_error;
529
+ };
530
+ } // namespace
529
531
530
- std::lock_guard<std::mutex> guard (g_sdk_path_mutex);
532
+ static llvm::Expected<llvm::StringRef>
533
+ find_cached_path (llvm::StringMap<ErrorOrPath> &cache, std::mutex &mutex,
534
+ llvm::StringRef key,
535
+ std::function<llvm::Expected<std::string>(void )> compute) {
536
+ std::lock_guard<std::mutex> guard (mutex);
531
537
LLDB_SCOPED_TIMER ();
532
538
533
- if (!options.XcodeSDK )
534
- return llvm::createStringError (llvm::inconvertibleErrorCode (),
535
- " XCodeSDK not specified" );
536
- XcodeSDK sdk = *options.XcodeSDK ;
537
-
538
- auto key = sdk.GetString ();
539
- auto it = g_sdk_path.find (key);
540
- if (it != g_sdk_path.end ()) {
539
+ auto it = cache.find (key);
540
+ if (it != cache.end ()) {
541
541
if (it->second .is_error )
542
542
return llvm::createStringError (llvm::inconvertibleErrorCode (),
543
543
it->second .str );
544
- else
545
- return it->second .str ;
544
+ return it->second .str ;
546
545
}
547
- auto path_or_err = GetXcodeSDK (sdk );
546
+ auto path_or_err = compute ( );
548
547
if (!path_or_err) {
549
548
std::string error = toString (path_or_err.takeError ());
550
- g_sdk_path .insert ({key, {error, true }});
549
+ cache .insert ({key, {error, true }});
551
550
return llvm::createStringError (llvm::inconvertibleErrorCode (), error);
552
551
}
553
- auto it_new = g_sdk_path .insert ({key, {*path_or_err, false }});
552
+ auto it_new = cache .insert ({key, {*path_or_err, false }});
554
553
return it_new.first ->second .str ;
555
554
}
556
555
556
+ llvm::Expected<llvm::StringRef> HostInfoMacOSX::GetSDKRoot (SDKOptions options) {
557
+ static llvm::StringMap<ErrorOrPath> g_sdk_path;
558
+ static std::mutex g_sdk_path_mutex;
559
+ if (!options.XcodeSDK )
560
+ return llvm::createStringError (llvm::inconvertibleErrorCode (),
561
+ " XCodeSDK not specified" );
562
+ XcodeSDK sdk = *options.XcodeSDK ;
563
+ auto key = sdk.GetString ();
564
+ return find_cached_path (g_sdk_path, g_sdk_path_mutex, key, [&](){
565
+ return GetXcodeSDK (sdk);
566
+ });
567
+ }
568
+
569
+ llvm::Expected<llvm::StringRef>
570
+ HostInfoMacOSX::FindSDKTool (XcodeSDK sdk, llvm::StringRef tool) {
571
+ static llvm::StringMap<ErrorOrPath> g_tool_path;
572
+ static std::mutex g_tool_path_mutex;
573
+ std::string key;
574
+ llvm::raw_string_ostream (key) << sdk.GetString () << " :" << tool;
575
+ return find_cached_path (
576
+ g_tool_path, g_tool_path_mutex, key,
577
+ [&]() -> llvm::Expected<std::string> {
578
+ std::string sdk_name = XcodeSDK::GetCanonicalName (sdk.Parse ());
579
+ if (sdk_name.empty ())
580
+ return llvm::createStringError (llvm::inconvertibleErrorCode (),
581
+ " Unrecognized SDK type: " +
582
+ sdk.GetString ());
583
+ llvm::SmallVector<llvm::StringRef, 2 > find = {" -find" , tool};
584
+ return xcrun (sdk_name, find);
585
+ });
586
+ }
587
+
557
588
namespace {
558
589
struct dyld_shared_cache_dylib_text_info {
559
590
uint64_t version; // current version 1
0 commit comments