//===- DTLTODistributionDriver.cpp - DTLTO Distribution Driver ---------===// // // 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 // //===----------------------------------------------------------------------===// // // \file // This file implements the Integrated Distributed ThinLTO driver that prepares // the compilation job descriptions and invokes the external distributor. // //===----------------------------------------------------------------------===// #include "llvm/DTLTO/DTLTO.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/JSON.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" #include using namespace llvm; // Generates a JSON file describing the backend compilations, for the // distributor. Error lto::DistributionDriver::emitJson() { using json::Array; std::error_code EC; raw_fd_ostream OS(DistributorJsonFile, EC); if (EC) return createStringError(EC, "Error while creating Json file"); json::OStream JOS(OS); JOS.object([&]() { // Information common to all jobs. JOS.attributeObject("common", [&]() { JOS.attribute("linker_output", Params.LinkerOutputFile); JOS.attributeArray("args", [&]() { JOS.value(Params.RemoteCompiler); // Forward any supplied prepend options. if (!Params.RemoteCompilerPrependArgs.empty()) for (auto &A : Params.RemoteCompilerPrependArgs) JOS.value(A); JOS.value("-c"); JOS.value(std::string("--target=") + Params.TargetTriple.str()); for (const auto &A : Params.CodegenOptions) JOS.value(A); }); JOS.attribute("inputs", Array(Params.CommonInputs)); }); // Per-compilation-job information. JOS.attributeArray("jobs", [&]() { for (const auto &J : Jobs) { assert(J.Task != 0); if (J.Cached) { continue; } SmallVector Inputs; SmallVector Outputs; JOS.object([&]() { JOS.attributeArray("args", [&]() { JOS.value(J.ModuleID); Inputs.push_back(J.ModuleID); JOS.value( std::string("-fthinlto-index=" + J.SummaryIndexPath.str())); Inputs.push_back(J.SummaryIndexPath); JOS.value("-o"); JOS.value(J.NativeObjectPath); Outputs.push_back(J.NativeObjectPath); }); // Add the bitcode files from which imports will be made. These do // not explicitly appear on the backend compilation command lines // but are recorded in the summary index shards. append_range(Inputs, J.ImportsFilesList); JOS.attribute("inputs", Array(Inputs)); JOS.attribute("outputs", Array(Outputs)); }); } }); }); return Error::success(); } // Saves JSON file on a filesystem. Error lto::DistributionDriver::saveJson() { DistributorJsonFile = sys::path::parent_path(Params.LinkerOutputFile); TimeTraceScope TimeScope("Emit DTLTO JSON"); sys::path::append(DistributorJsonFile, sys::path::stem(Params.LinkerOutputFile) + "." + itostr(sys::Process::getProcessId()) + ".dist-file.json"); if (Error E = emitJson()) return make_error( BCError + "failed to generate distributor JSON script: " + DistributorJsonFile, errorToErrorCode(std::move(E))); // Add JSON file to the cleanup files list. if (!SaveTemps) AddToCleanup(DistributorJsonFile); return Error::success(); } // Invokes the distributor to compile uncached ThinLTO modules remotely. Error lto::DistributionDriver::operator()() { if (Error E = saveJson()) return E; TimeTraceScope TimeScope("Execute DTLTO distributor", Params.DistributorPath); SmallVector Args = {Params.DistributorPath}; append_range(Args, Params.DistributorArgs); Args.push_back(DistributorJsonFile); std::string ErrMsg; if (sys::ExecuteAndWait(Args[0], Args, /*Env=*/std::nullopt, /*Redirects=*/{}, /*SecondsToWait=*/0, /*MemoryLimit=*/0, &ErrMsg)) { return make_error( BCError + "distributor execution failed" + (!ErrMsg.empty() ? ": " + ErrMsg + Twine(".") : Twine(".")), inconvertibleErrorCode()); } return Error::success(); }