|
34 | 34 | #include "llvm/Support/raw_ostream.h" |
35 | 35 | #include "llvm/TargetParser/Host.h" |
36 | 36 | #include "llvm/TargetParser/Triple.h" |
| 37 | +#include "toolchain/base/kind_switch.h" |
37 | 38 | #include "toolchain/base/runtime_sources.h" |
38 | 39 | #include "toolchain/driver/clang_runner.h" |
39 | 40 | #include "toolchain/driver/runtimes_cache.h" |
@@ -210,6 +211,126 @@ auto ClangRuntimesBuilderBase::ArchiveBuilder::CompileMember( |
210 | 211 | return std::move(*obj_result); |
211 | 212 | } |
212 | 213 |
|
| 214 | +template <Runtimes::Component Component> |
| 215 | + requires(Component == Runtimes::LibUnwind) |
| 216 | +ClangArchiveRuntimesBuilder<Component>::ClangArchiveRuntimesBuilder( |
| 217 | + ClangRunner* clang, llvm::ThreadPoolInterface* threads, |
| 218 | + llvm::Triple target_triple, Runtimes* runtimes) |
| 219 | + : ClangRuntimesBuilderBase(clang, threads, std::move(target_triple)) { |
| 220 | + // Ensure we're on a platform where we _can_ build a working runtime. |
| 221 | + if (target_triple_.isOSWindows()) { |
| 222 | + result_ = |
| 223 | + Error("TODO: Windows runtimes are untested and not yet supported."); |
| 224 | + return; |
| 225 | + } |
| 226 | + |
| 227 | + auto build_dir_or_error = runtimes->Build(Component); |
| 228 | + if (!build_dir_or_error.ok()) { |
| 229 | + result_ = std::move(build_dir_or_error).error(); |
| 230 | + return; |
| 231 | + } |
| 232 | + auto build_dir = *(std::move(build_dir_or_error)); |
| 233 | + CARBON_KIND_SWITCH(std::move(build_dir)) { |
| 234 | + case CARBON_KIND(std::filesystem::path build_dir_path): { |
| 235 | + // Found cached build. |
| 236 | + result_ = std::move(build_dir_path); |
| 237 | + return; |
| 238 | + } |
| 239 | + case CARBON_KIND(Runtimes::Builder builder): { |
| 240 | + runtimes_builder_ = std::move(builder); |
| 241 | + // Building the runtimes is handled below. |
| 242 | + break; |
| 243 | + } |
| 244 | + } |
| 245 | + |
| 246 | + if constexpr (Component == Runtimes::LibUnwind) { |
| 247 | + srcs_path_ = installation().libunwind_path(); |
| 248 | + include_path_ = installation().libunwind_path() / "include"; |
| 249 | + archive_path_ = std::filesystem::path("lib") / "libunwind.a"; |
| 250 | + } else { |
| 251 | + static_assert(false, |
| 252 | + "Invalid runtimes component for an archive runtime builder."); |
| 253 | + } |
| 254 | + |
| 255 | + archive_.emplace(this, archive_path_, srcs_path_, CollectSrcFiles(), |
| 256 | + CollectCflags()); |
| 257 | + tasks_.async([this]() mutable { Setup(); }); |
| 258 | +} |
| 259 | + |
| 260 | +template <Runtimes::Component Component> |
| 261 | + requires(Component == Runtimes::LibUnwind) |
| 262 | +auto ClangArchiveRuntimesBuilder<Component>::CollectSrcFiles() |
| 263 | + -> llvm::SmallVector<llvm::StringRef> { |
| 264 | + if constexpr (Component == Runtimes::LibUnwind) { |
| 265 | + return llvm::SmallVector<llvm::StringRef>(llvm::make_filter_range( |
| 266 | + RuntimeSources::LibunwindSrcs, [](llvm::StringRef src) { |
| 267 | + return src.ends_with(".c") || src.ends_with(".cpp") || |
| 268 | + src.ends_with(".S"); |
| 269 | + })); |
| 270 | + } else { |
| 271 | + static_assert(false, |
| 272 | + "Invalid runtimes component for an archive runtime builder."); |
| 273 | + } |
| 274 | +} |
| 275 | + |
| 276 | +template <Runtimes::Component Component> |
| 277 | + requires(Component == Runtimes::LibUnwind) |
| 278 | +auto ClangArchiveRuntimesBuilder<Component>::CollectCflags() |
| 279 | + -> llvm::SmallVector<llvm::StringRef> { |
| 280 | + if constexpr (Component == Runtimes::LibUnwind) { |
| 281 | + return { |
| 282 | + "-no-canonical-prefixes", |
| 283 | + "-O3", |
| 284 | + "-fPIC", |
| 285 | + "-funwind-tables", |
| 286 | + "-fno-exceptions", |
| 287 | + "-fno-rtti", |
| 288 | + "-nostdinc++", |
| 289 | + "-I", |
| 290 | + include_path_.native(), |
| 291 | + "-D_LIBUNWIND_IS_NATIVE_ONLY", |
| 292 | + "-w", |
| 293 | + }; |
| 294 | + } else { |
| 295 | + static_assert(false, |
| 296 | + "Invalid runtimes component for an archive runtime builder."); |
| 297 | + } |
| 298 | +} |
| 299 | + |
| 300 | +template <Runtimes::Component Component> |
| 301 | + requires(Component == Runtimes::LibUnwind) |
| 302 | +auto ClangArchiveRuntimesBuilder<Component>::Setup() -> void { |
| 303 | + // Symlink the installation's `include` into the runtime. |
| 304 | + CARBON_CHECK(include_path_.is_absolute(), |
| 305 | + "Unexpected relative include path: {0}", include_path_); |
| 306 | + if (auto result = runtimes_builder_->dir().Symlink("include", include_path_); |
| 307 | + !result.ok()) { |
| 308 | + result_ = std::move(result).error(); |
| 309 | + return; |
| 310 | + } |
| 311 | + |
| 312 | + // Finish building the runtime once the archive is built. |
| 313 | + Latch::Handle latch_handle = step_counter_.Init( |
| 314 | + [this]() mutable { tasks_.async([this]() mutable { Finish(); }); }); |
| 315 | + |
| 316 | + // Start building the archive itself with a handle to detect when complete. |
| 317 | + archive_->Setup(std::move(latch_handle)); |
| 318 | +} |
| 319 | + |
| 320 | +template <Runtimes::Component Component> |
| 321 | + requires(Component == Runtimes::LibUnwind) |
| 322 | +auto ClangArchiveRuntimesBuilder<Component>::Finish() -> void { |
| 323 | + CARBON_VLOG("Finished building {0}...\n", archive_path_); |
| 324 | + if (!archive_->result().ok()) { |
| 325 | + result_ = std::move(archive_->result()).error(); |
| 326 | + return; |
| 327 | + } |
| 328 | + |
| 329 | + result_ = (*std::move(runtimes_builder_)).Commit(); |
| 330 | +} |
| 331 | + |
| 332 | +template class ClangArchiveRuntimesBuilder<Runtimes::LibUnwind>; |
| 333 | + |
213 | 334 | ClangResourceDirBuilder::ClangResourceDirBuilder( |
214 | 335 | ClangRunner* clang, llvm::ThreadPoolInterface* threads, |
215 | 336 | llvm::Triple target_triple, Runtimes* runtimes) |
|
0 commit comments