File: HostInfoMacOSXSwift.cpp

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (294 lines) | stat: -rw-r--r-- 10,971 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
//===-- HostInfoMacOSSwift.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/Host/HostInfo.h"

#include "Plugins/Platform/MacOSX/PlatformDarwin.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/posix/HostInfoPosix.h"
#include "lldb/Host/common/HostInfoSwift.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include <regex>
#include <string>

using namespace lldb_private;

#ifdef LLDB_ENABLE_SWIFT

bool HostInfoMacOSX::ComputeSwiftResourceDirectory(FileSpec &lldb_shlib_spec,
                                                   FileSpec &file_spec,
                                                   bool verify) {
  if (!lldb_shlib_spec)
    return false;

  std::string raw_path = lldb_shlib_spec.GetPath();
  size_t framework_pos = raw_path.find("LLDB.framework");
  if (framework_pos == std::string::npos)
    return HostInfoPosix::ComputeSwiftResourceDirectory(lldb_shlib_spec,
                                                           file_spec, verify);

  framework_pos += strlen("LLDB.framework");
  raw_path.resize(framework_pos);
  raw_path.append("/Resources/Swift");
  if (!verify || VerifySwiftPath(raw_path)) {
    file_spec.SetDirectory(raw_path);
    FileSystem::Instance().Resolve(file_spec);
    return true;
  }
  return true;
}

FileSpec HostInfoMacOSX::GetSwiftResourceDir() {
  static std::once_flag g_once_flag;
  static FileSpec g_swift_resource_dir;
  std::call_once(g_once_flag, []() {
    FileSpec lldb_file_spec = HostInfo::GetShlibDir();
    ComputeSwiftResourceDirectory(lldb_file_spec, g_swift_resource_dir, true);
    Log *log = GetLog(LLDBLog::Host);
    LLDB_LOG(log, "swift dir -> '{0}'", g_swift_resource_dir);
  });
  return g_swift_resource_dir;
}

/// Return the Xcode sdk type for the target triple, if that makes sense.
/// Otherwise, return the unknown sdk type.
static XcodeSDK::Type GetSDKType(const llvm::Triple &target,
                                 const llvm::Triple &host) {
  // Only Darwin platforms know the concept of an SDK.
  auto host_os = host.getOS();
  if (host_os != llvm::Triple::OSType::MacOSX)
    return XcodeSDK::Type::unknown;

  auto is_simulator = [&]() -> bool {
    return target.getEnvironment() == llvm::Triple::Simulator ||
           !target.getArchName().startswith("arm");
  };

  switch (target.getOS()) {
  case llvm::Triple::OSType::MacOSX:
  case llvm::Triple::OSType::Darwin:
    return XcodeSDK::Type::MacOSX;
  case llvm::Triple::OSType::IOS:
    if (is_simulator())
      return XcodeSDK::Type::iPhoneSimulator;
    return XcodeSDK::Type::iPhoneOS;
  case llvm::Triple::OSType::TvOS:
    if (is_simulator())
      return XcodeSDK::Type::AppleTVSimulator;
    return XcodeSDK::Type::AppleTVOS;
  case llvm::Triple::OSType::WatchOS:
    if (is_simulator())
      return XcodeSDK::Type::WatchSimulator;
    return XcodeSDK::Type::watchOS;
  default:
    return XcodeSDK::Type::unknown;
  }
}

std::string HostInfoMacOSX::GetSwiftStdlibOSDir(llvm::Triple target,
                                                llvm::Triple host) {
  XcodeSDK::Info sdk_info;
  sdk_info.type = GetSDKType(target, host);
  std::string sdk_name = XcodeSDK::GetCanonicalName(sdk_info);
  if (!sdk_name.empty())
    return sdk_name;
  return target.getOSName().str();
}

static bool IsDirectory(const FileSpec &spec) {
  return llvm::sys::fs::is_directory(spec.GetPath());
}

std::string HostInfoMacOSX::DetectSwiftResourceDir(
    llvm::StringRef platform_sdk_path, llvm::StringRef swift_stdlib_os_dir,
    std::string swift_dir, std::string xcode_contents_path,
    std::string toolchain_path, std::string cl_tools_path) {
  llvm::SmallString<16> m_description("SwiftASTContext");
  // First, check if there's something in our bundle.
  {
    FileSpec swift_dir_spec(swift_dir);
    if (swift_dir_spec) {
      LLDB_LOGF(GetLog(LLDBLog::Types), "trying ePathTypeSwiftDir: %s",
                swift_dir_spec.GetPath().c_str());
      // We can't just check for the Swift directory, because that
      // always exists.  We have to look for "clang" inside that.
      FileSpec swift_clang_dir_spec = swift_dir_spec;
      swift_clang_dir_spec.AppendPathComponent("clang");

      if (IsDirectory(swift_clang_dir_spec)) {
        LLDB_LOGF(GetLog(LLDBLog::Types),
                  "found Swift resource dir via ePathTypeSwiftDir': %s",
                  swift_dir_spec.GetPath().c_str());
        return swift_dir_spec.GetPath();
      }
    }
  }

  // Nothing in our bundle. Are we in a toolchain that has its own Swift
  // compiler resource dir?

  {
    llvm::SmallString<256> path(toolchain_path);
    LLDB_LOGF(GetLog(LLDBLog::Types), "trying toolchain path: %s",
               path.c_str());

    if (!path.empty()) {
      llvm::sys::path::append(path, "usr/lib/swift");
      LLDB_LOGF(GetLog(LLDBLog::Types), "trying toolchain-based lib path: %s",
                 path.c_str());

      if (IsDirectory(FileSpec(path))) {
        LLDB_LOGF(GetLog(LLDBLog::Types),
                   "found Swift resource dir via "
                   "toolchain path + 'usr/lib/swift': %s",
                   path.c_str());
        return std::string(path);
      }
    }
  }

  // We're not in a toolchain that has one. Use the Xcode default toolchain.

  {
    llvm::SmallString<256> path(xcode_contents_path);
    LLDB_LOGF(GetLog(LLDBLog::Types), "trying Xcode path: %s", path.c_str());

    if (!path.empty()) {
      llvm::sys::path::append(path, "Developer",
                              "Toolchains/XcodeDefault.xctoolchain",
                              "usr/lib/swift");
      LLDB_LOGF(GetLog(LLDBLog::Types), "trying Xcode-based lib path: %s",
                 path.c_str());

      if (IsDirectory(FileSpec(path))) {
        llvm::StringRef resource_dir = path;
        llvm::sys::path::append(path, swift_stdlib_os_dir);
        std::string s(path);
        if (IsDirectory(FileSpec(path))) {
          LLDB_LOGF(GetLog(LLDBLog::Types),
                     "found Swift resource dir via "
                     "Xcode contents path + default toolchain "
                     "relative dir: %s",
                     resource_dir.str().c_str());
          return resource_dir.str();
        } else {
          // Search the SDK for a matching cross-SDK.
          path = platform_sdk_path;
          llvm::sys::path::append(path, "usr/lib/swift");
          llvm::StringRef resource_dir = path;
          llvm::sys::path::append(path, swift_stdlib_os_dir);
          if (IsDirectory(FileSpec(path))) {
            LLDB_LOGF(GetLog(LLDBLog::Types),
                       "found Swift resource dir via "
                       "Xcode contents path + cross-compilation SDK "
                       "relative dir: %s",
                       resource_dir.str().c_str());
            return resource_dir.str();
          }
        }
      }
    }
  }

  // We're not in Xcode. We might be in the command-line tools.

  {
    llvm::SmallString<256> path(cl_tools_path);
    LLDB_LOGF(GetLog(LLDBLog::Types), "trying command-line tools path: %s",
               path.c_str());

    if (!path.empty()) {
      llvm::sys::path::append(path, "usr/lib/swift");
      LLDB_LOGF(GetLog(LLDBLog::Types),
                 "trying command-line tools-based lib path: %s", path.c_str());

      if (IsDirectory(FileSpec(path))) {
        LLDB_LOGF(GetLog(LLDBLog::Types),
                   "found Swift resource dir via command-line tools "
                   "path + usr/lib/swift: %s",
                   path.c_str());
        return std::string(path);
      }
    }
  }

  // We might be in the build-dir configuration for a
  // build-script-driven LLDB build, which has the Swift build dir as
  // a sibling directory to the lldb build dir.  This looks much
  // different than the install- dir layout that the previous checks
  // would try.
  {
    FileSpec faux_swift_dir_spec(swift_dir);
    if (faux_swift_dir_spec) {
      // Let's try to regex this.
      // We're looking for /some/path/lldb-{os}-{arch}, and want to
      // build the following:
      //    /some/path/swift-{os}-{arch}/lib/swift/{os}/{arch}
      // In a match, these are the following assignments for
      // backrefs:
      //   $1 - first part of path before swift build dir
      //   $2 - the host OS path separator character
      //   $3 - all the stuff that should come after changing
      //        lldb to swift for the lib dir.
      auto match_regex =
          std::regex("^(.+([/\\\\]))lldb-(.+)$");
      const std::string replace_format = "$1swift-$3";
      const std::string faux_swift_dir = faux_swift_dir_spec.GetPath();
      const std::string build_tree_resource_dir =
          std::regex_replace(faux_swift_dir, match_regex,
                             replace_format);
      LLDB_LOGF(GetLog(LLDBLog::Types),
                 "trying ePathTypeSwiftDir regex-based build dir: %s",
                 build_tree_resource_dir.c_str());
      FileSpec swift_resource_dir_spec(build_tree_resource_dir.c_str());
      if (IsDirectory(swift_resource_dir_spec)) {
        LLDB_LOGF(GetLog(LLDBLog::Types),
                  "found Swift resource dir via "
                  "ePathTypeSwiftDir + inferred build-tree dir: %s",
                  swift_resource_dir_spec.GetPath().c_str());
        return swift_resource_dir_spec.GetPath();
      }
    }
  }

  // We failed to find a reasonable Swift resource dir.
  LLDB_LOGF(GetLog(LLDBLog::Types), "failed to find a Swift resource dir");

  return {};
}

std::string
HostInfoMacOSX::GetSwiftResourceDir(llvm::Triple triple,
                                    llvm::StringRef platform_sdk_path) {
  static std::mutex g_mutex;
  std::lock_guard<std::mutex> locker(g_mutex);
  std::string swift_stdlib_os_dir =
      GetSwiftStdlibOSDir(triple, HostInfo::GetArchitecture().GetTriple());

  // The resource dir depends on the SDK path and the expected OS name.
  llvm::SmallString<128> key(platform_sdk_path);
  key.append(swift_stdlib_os_dir);
  static llvm::StringMap<std::string> g_resource_dir_cache;
  auto it = g_resource_dir_cache.find(key);
  if (it != g_resource_dir_cache.end())
    return it->getValue();

  auto value = DetectSwiftResourceDir(
      platform_sdk_path, swift_stdlib_os_dir,
      HostInfo::GetSwiftResourceDir().GetPath(),
      HostInfo::GetXcodeContentsDirectory().GetPath(),
      PlatformDarwin::GetCurrentToolchainDirectory().GetPath(),
      PlatformDarwin::GetCurrentCommandLineToolsDirectory().GetPath());
  g_resource_dir_cache.insert({key, value});
  return g_resource_dir_cache[key];
}

#endif