1221339Sdim//===--- CreateInvocationFromCommandLine.cpp - CompilerInvocation from Args ==// 2221339Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6221339Sdim// 7221339Sdim//===----------------------------------------------------------------------===// 8221339Sdim// 9221339Sdim// Construct a compiler invocation object for command line driver arguments 10221339Sdim// 11221339Sdim//===----------------------------------------------------------------------===// 12221339Sdim 13249423Sdim#include "clang/Frontend/Utils.h" 14243830Sdim#include "clang/Basic/DiagnosticOptions.h" 15221339Sdim#include "clang/Driver/Compilation.h" 16221339Sdim#include "clang/Driver/Driver.h" 17288943Sdim#include "clang/Driver/Action.h" 18221339Sdim#include "clang/Driver/Options.h" 19221339Sdim#include "clang/Driver/Tool.h" 20249423Sdim#include "clang/Frontend/CompilerInstance.h" 21249423Sdim#include "clang/Frontend/FrontendDiagnostic.h" 22261991Sdim#include "llvm/Option/ArgList.h" 23221339Sdim#include "llvm/Support/Host.h" 24221339Sdimusing namespace clang; 25261991Sdimusing namespace llvm::opt; 26221339Sdim 27314564Sdimstd::unique_ptr<CompilerInvocation> clang::createInvocationFromCommandLine( 28321369Sdim ArrayRef<const char *> ArgList, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, 29360784Sdim IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, bool ShouldRecoverOnErorrs, 30360784Sdim std::vector<std::string> *CC1Args) { 31276479Sdim if (!Diags.get()) { 32221339Sdim // No diagnostics engine was provided, so create our own diagnostics object 33221339Sdim // with the default options. 34249423Sdim Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions); 35221339Sdim } 36221339Sdim 37296417Sdim SmallVector<const char *, 16> Args(ArgList.begin(), ArgList.end()); 38221339Sdim 39239462Sdim // FIXME: Find a cleaner way to force the driver into restricted modes. 40221339Sdim Args.push_back("-fsyntax-only"); 41221339Sdim 42221339Sdim // FIXME: We shouldn't have to pass in the path info. 43296417Sdim driver::Driver TheDriver(Args[0], llvm::sys::getDefaultTargetTriple(), 44321369Sdim *Diags, VFS); 45221339Sdim 46221339Sdim // Don't check that inputs exist, they may have been remapped. 47221339Sdim TheDriver.setCheckInputsExist(false); 48221339Sdim 49276479Sdim std::unique_ptr<driver::Compilation> C(TheDriver.BuildCompilation(Args)); 50321369Sdim if (!C) 51321369Sdim return nullptr; 52221339Sdim 53221339Sdim // Just print the cc1 options if -### was present. 54221339Sdim if (C->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) { 55261991Sdim C->getJobs().Print(llvm::errs(), "\n", true); 56276479Sdim return nullptr; 57221339Sdim } 58221339Sdim 59221339Sdim // We expect to get back exactly one command job, if we didn't something 60309124Sdim // failed. Offload compilation is an exception as it creates multiple jobs. If 61309124Sdim // that's the case, we proceed with the first job. If caller needs a 62309124Sdim // particular job, it should be controlled via options (e.g. 63309124Sdim // --cuda-{host|device}-only for CUDA) passed to the driver. 64221339Sdim const driver::JobList &Jobs = C->getJobs(); 65309124Sdim bool OffloadCompilation = false; 66288943Sdim if (Jobs.size() > 1) { 67288943Sdim for (auto &A : C->getActions()){ 68288943Sdim // On MacOSX real actions may end up being wrapped in BindArchAction 69288943Sdim if (isa<driver::BindArchAction>(A)) 70309124Sdim A = *A->input_begin(); 71309124Sdim if (isa<driver::OffloadAction>(A)) { 72309124Sdim OffloadCompilation = true; 73288943Sdim break; 74288943Sdim } 75288943Sdim } 76288943Sdim } 77288943Sdim if (Jobs.size() == 0 || !isa<driver::Command>(*Jobs.begin()) || 78309124Sdim (Jobs.size() > 1 && !OffloadCompilation)) { 79234353Sdim SmallString<256> Msg; 80221339Sdim llvm::raw_svector_ostream OS(Msg); 81261991Sdim Jobs.Print(OS, "; ", true); 82221339Sdim Diags->Report(diag::err_fe_expected_compiler_job) << OS.str(); 83276479Sdim return nullptr; 84221339Sdim } 85221339Sdim 86280031Sdim const driver::Command &Cmd = cast<driver::Command>(*Jobs.begin()); 87280031Sdim if (StringRef(Cmd.getCreator().getName()) != "clang") { 88221339Sdim Diags->Report(diag::err_fe_expected_clang_command); 89276479Sdim return nullptr; 90221339Sdim } 91221339Sdim 92280031Sdim const ArgStringList &CCArgs = Cmd.getArguments(); 93360784Sdim if (CC1Args) 94360784Sdim *CC1Args = {CCArgs.begin(), CCArgs.end()}; 95360784Sdim auto CI = std::make_unique<CompilerInvocation>(); 96360784Sdim if (!CompilerInvocation::CreateFromArgs(*CI, CCArgs, *Diags) && 97360784Sdim !ShouldRecoverOnErorrs) 98276479Sdim return nullptr; 99314564Sdim return CI; 100221339Sdim} 101