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
|
//===- Driver.cpp - A C Interface for the Clang 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
//
//===----------------------------------------------------------------------===//
//
// This file provides a C API for extracting information from the clang driver.
//
//===----------------------------------------------------------------------===//
#include "clang-c/Driver.h"
#include "CIndexDiagnostic.h"
#include "CXDiagnosticSetDiagnosticConsumer.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Frontend/CompilerInstance.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/TargetParser/Host.h"
using namespace clang;
CXExternalActionList *
clang_Driver_getExternalActionsForCommand_v0(int ArgC, const char **ArgV,
const char **Environment,
const char *WorkingDirectory,
CXDiagnosticSet *OutDiags) {
if (OutDiags)
*OutDiags = nullptr;
// Non empty environments are not currently supported.
if (Environment)
return nullptr;
// ArgV must at least include the compiler executable name.
if (ArgC < 1)
return nullptr;
CXDiagnosticSetDiagnosticConsumer DiagConsumer;
auto DiagOpts = CreateAndPopulateDiagOpts(ArrayRef(ArgV, ArgC));
auto Diags = CompilerInstance::createDiagnostics(DiagOpts.release(),
&DiagConsumer, false);
// Use createPhysicalFileSystem instead of getRealFileSystem so that
// setCurrentWorkingDirectory doesn't change the working directory of the
// process.
std::unique_ptr<llvm::vfs::FileSystem> VFS =
llvm::vfs::createPhysicalFileSystem();
if (WorkingDirectory)
if (std::error_code EC =
VFS->setCurrentWorkingDirectory(WorkingDirectory)) {
Diags->Report(diag::err_drv_unable_to_set_working_directory) <<
WorkingDirectory;
if (OutDiags)
*OutDiags = DiagConsumer.getDiagnosticSet();
return nullptr;
}
driver::Driver TheDriver(ArgV[0], llvm::sys::getDefaultTargetTriple(), *Diags, "clang LLVM compiler",
VFS.release());
TheDriver.setCheckInputsExist(false);
std::unique_ptr<driver::Compilation> C(
TheDriver.BuildCompilation(ArrayRef(ArgV, ArgC)));
if (!C || Diags->hasErrorOccurred()) {
if (OutDiags)
*OutDiags = DiagConsumer.getDiagnosticSet();
return nullptr;
}
const driver::JobList &Jobs = C->getJobs();
CXExternalAction **Actions = new CXExternalAction *[Jobs.size()];
int AI = 0;
for (auto &&J : Jobs) {
// First calculate the total space we'll need for this action's arguments.
llvm::opt::ArgStringList Args = J.getArguments();
Args.insert(Args.begin(), J.getExecutable());
int ArgSpace = (Args.size() + 1) * sizeof(const char *);
for (auto &&Arg : Args)
ArgSpace += strlen(Arg) + 1; // Null terminator
// Tail allocate the space for the strings.
auto Action =
new ((CXExternalAction *)malloc(sizeof(CXExternalAction) + ArgSpace))
CXExternalAction;
Action->ArgC = Args.size();
Action->ArgV = reinterpret_cast<const char **>(Action + 1);
Action->ArgV[Args.size()] = nullptr;
char *StrTable = ((char *)Action) + sizeof(CXExternalAction) +
(Args.size() + 1) * sizeof(const char *);
int I = 0;
for (auto &&Arg : Args) {
Action->ArgV[I++] = strcpy(StrTable, Arg);
StrTable += strlen(Arg) + 1;
}
Actions[AI++] = Action;
}
return new CXExternalActionList{(int)Jobs.size(), Actions};
}
void clang_Driver_ExternalActionList_dispose(CXExternalActionList *EAL) {
if (!EAL)
return;
for (int I = 0; I < EAL->Count; ++I)
free(EAL->Actions[I]);
delete[] EAL->Actions;
delete EAL;
}
|