1*7330f729Sjoerg //===--- CreateInvocationFromCommandLine.cpp - CompilerInvocation from Args ==// 2*7330f729Sjoerg // 3*7330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*7330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information. 5*7330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*7330f729Sjoerg // 7*7330f729Sjoerg //===----------------------------------------------------------------------===// 8*7330f729Sjoerg // 9*7330f729Sjoerg // Construct a compiler invocation object for command line driver arguments 10*7330f729Sjoerg // 11*7330f729Sjoerg //===----------------------------------------------------------------------===// 12*7330f729Sjoerg 13*7330f729Sjoerg #include "clang/Frontend/Utils.h" 14*7330f729Sjoerg #include "clang/Basic/DiagnosticOptions.h" 15*7330f729Sjoerg #include "clang/Driver/Compilation.h" 16*7330f729Sjoerg #include "clang/Driver/Driver.h" 17*7330f729Sjoerg #include "clang/Driver/Action.h" 18*7330f729Sjoerg #include "clang/Driver/Options.h" 19*7330f729Sjoerg #include "clang/Driver/Tool.h" 20*7330f729Sjoerg #include "clang/Frontend/CompilerInstance.h" 21*7330f729Sjoerg #include "clang/Frontend/FrontendDiagnostic.h" 22*7330f729Sjoerg #include "llvm/Option/ArgList.h" 23*7330f729Sjoerg #include "llvm/Support/Host.h" 24*7330f729Sjoerg using namespace clang; 25*7330f729Sjoerg using namespace llvm::opt; 26*7330f729Sjoerg 27*7330f729Sjoerg std::unique_ptr<CompilerInvocation> clang::createInvocationFromCommandLine( 28*7330f729Sjoerg ArrayRef<const char *> ArgList, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, 29*7330f729Sjoerg IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, bool ShouldRecoverOnErorrs) { 30*7330f729Sjoerg if (!Diags.get()) { 31*7330f729Sjoerg // No diagnostics engine was provided, so create our own diagnostics object 32*7330f729Sjoerg // with the default options. 33*7330f729Sjoerg Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions); 34*7330f729Sjoerg } 35*7330f729Sjoerg 36*7330f729Sjoerg SmallVector<const char *, 16> Args(ArgList.begin(), ArgList.end()); 37*7330f729Sjoerg 38*7330f729Sjoerg // FIXME: Find a cleaner way to force the driver into restricted modes. 39*7330f729Sjoerg Args.push_back("-fsyntax-only"); 40*7330f729Sjoerg 41*7330f729Sjoerg // FIXME: We shouldn't have to pass in the path info. 42*7330f729Sjoerg driver::Driver TheDriver(Args[0], llvm::sys::getDefaultTargetTriple(), 43*7330f729Sjoerg *Diags, VFS); 44*7330f729Sjoerg 45*7330f729Sjoerg // Don't check that inputs exist, they may have been remapped. 46*7330f729Sjoerg TheDriver.setCheckInputsExist(false); 47*7330f729Sjoerg 48*7330f729Sjoerg std::unique_ptr<driver::Compilation> C(TheDriver.BuildCompilation(Args)); 49*7330f729Sjoerg if (!C) 50*7330f729Sjoerg return nullptr; 51*7330f729Sjoerg 52*7330f729Sjoerg // Just print the cc1 options if -### was present. 53*7330f729Sjoerg if (C->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) { 54*7330f729Sjoerg C->getJobs().Print(llvm::errs(), "\n", true); 55*7330f729Sjoerg return nullptr; 56*7330f729Sjoerg } 57*7330f729Sjoerg 58*7330f729Sjoerg // We expect to get back exactly one command job, if we didn't something 59*7330f729Sjoerg // failed. Offload compilation is an exception as it creates multiple jobs. If 60*7330f729Sjoerg // that's the case, we proceed with the first job. If caller needs a 61*7330f729Sjoerg // particular job, it should be controlled via options (e.g. 62*7330f729Sjoerg // --cuda-{host|device}-only for CUDA) passed to the driver. 63*7330f729Sjoerg const driver::JobList &Jobs = C->getJobs(); 64*7330f729Sjoerg bool OffloadCompilation = false; 65*7330f729Sjoerg if (Jobs.size() > 1) { 66*7330f729Sjoerg for (auto &A : C->getActions()){ 67*7330f729Sjoerg // On MacOSX real actions may end up being wrapped in BindArchAction 68*7330f729Sjoerg if (isa<driver::BindArchAction>(A)) 69*7330f729Sjoerg A = *A->input_begin(); 70*7330f729Sjoerg if (isa<driver::OffloadAction>(A)) { 71*7330f729Sjoerg OffloadCompilation = true; 72*7330f729Sjoerg break; 73*7330f729Sjoerg } 74*7330f729Sjoerg } 75*7330f729Sjoerg } 76*7330f729Sjoerg if (Jobs.size() == 0 || !isa<driver::Command>(*Jobs.begin()) || 77*7330f729Sjoerg (Jobs.size() > 1 && !OffloadCompilation)) { 78*7330f729Sjoerg SmallString<256> Msg; 79*7330f729Sjoerg llvm::raw_svector_ostream OS(Msg); 80*7330f729Sjoerg Jobs.Print(OS, "; ", true); 81*7330f729Sjoerg Diags->Report(diag::err_fe_expected_compiler_job) << OS.str(); 82*7330f729Sjoerg return nullptr; 83*7330f729Sjoerg } 84*7330f729Sjoerg 85*7330f729Sjoerg const driver::Command &Cmd = cast<driver::Command>(*Jobs.begin()); 86*7330f729Sjoerg if (StringRef(Cmd.getCreator().getName()) != "clang") { 87*7330f729Sjoerg Diags->Report(diag::err_fe_expected_clang_command); 88*7330f729Sjoerg return nullptr; 89*7330f729Sjoerg } 90*7330f729Sjoerg 91*7330f729Sjoerg const ArgStringList &CCArgs = Cmd.getArguments(); 92*7330f729Sjoerg auto CI = std::make_unique<CompilerInvocation>(); 93*7330f729Sjoerg if (!CompilerInvocation::CreateFromArgs(*CI, CCArgs, *Diags) && 94*7330f729Sjoerg !ShouldRecoverOnErorrs) 95*7330f729Sjoerg return nullptr; 96*7330f729Sjoerg return CI; 97*7330f729Sjoerg } 98