#ifndef CLANG_DRIVER_DRIVER_H_
#define CLANG_DRIVER_DRIVER_H_
+#include <list>
+#include <set>
+#include <string>
+
namespace clang {
namespace driver {
class ArgList;
class Compilation;
+ class HostInfo;
class OptTable;
/// Driver - Encapsulate logic for constructing compilation processes
/// ArgList.
ArgList *ParseArgStrings(const char **ArgBegin, const char **ArgEnd);
+ // FIXME: Privatize once interface is stable.
+public:
+ /// The name the driver was invoked as.
+ std::string Name;
+
+ /// The path the driver executable was in, as invoked from the
+ /// command line.
+ std::string Dir;
+
+ /// Host information for the platform the driver is running as. This
+ /// will generally be the actual host platform, but not always.
+ HostInfo *Host;
+
+ /// Information about the host which can be overriden by the user.
+ std::string HostBits, HostMachine, HostSystem, HostRelease;
+
+ /// Whether the driver should follow g++ like behavior.
+ bool CCCIsCXX : 1;
+
+ /// Echo commands while executing (in -v style).
+ bool CCCEcho : 1;
+
+ /// Don't use clang for any tasks.
+ bool CCCNoClang : 1;
+
+ /// Don't use clang for handling C++ and Objective-C++ inputs.
+ bool CCCNoClangCXX : 1;
+
+ /// Don't use clang as a preprocessor (clang's preprocessor will
+ /// still be used where an integrated CPP would).
+ bool CCCNoClangCPP : 1;
+
+ /// Only use clang for the given architectures. Only used when
+ /// non-empty.
+ std::set<std::string> CCCClangArchs;
+
+ /// Certain options suppress the 'no input files' warning.
+ bool SuppressMissingInputWarning : 1;
+
+ std::list<std::string> TempFiles;
+ std::list<std::string> ResultFiles;
+
public:
- Driver();
+ Driver(const char *_Name, const char *_Dir);
~Driver();
+
const OptTable &getOpts() const { return *Opts; }
/// BuildCompilation - Construct a compilation object for a command
/// line argument vector.
Compilation *BuildCompilation(int argc, const char **argv);
+
+ /// PrintOptions - Print the given list of arguments.
+ void PrintOptions(const ArgList *Args);
};
} // end namespace driver
#include "llvm/Support/raw_ostream.h"
using namespace clang::driver;
-Driver::Driver() : Opts(new OptTable()) {
+Driver::Driver(const char *_Name, const char *_Dir)
+ : Opts(new OptTable()),
+ Name(_Name), Dir(_Dir), Host(0),
+ CCCIsCXX(false), CCCEcho(false),
+ CCCNoClang(false), CCCNoClangCXX(false), CCCNoClangCPP(false)
+{
}
}
Compilation *Driver::BuildCompilation(int argc, const char **argv) {
- ArgList *Args = ParseArgStrings(argv + 1, argv + argc);
+ // FIXME: This stuff needs to go into the Compilation, not the
+ // driver.
+ bool CCCPrintOptions = false, CCCPrintPhases = false;
- // Hard coded to print-options behavior.
+ const char **Start = argv + 1, **End = argv + argc;
+
+ // Read -ccc args.
+ //
+ // FIXME: We need to figure out where this behavior should
+ // live. Most of it should be outside in the client; the parts that
+ // aren't should have proper options, either by introducing new ones
+ // or by overloading gcc ones like -V or -b.
+ for (; Start != End && memcmp(*Start, "-ccc-", 5) == 0; ++Start) {
+ const char *Opt = *Start + 5;
+
+ if (!strcmp(Opt, "print-options")) {
+ CCCPrintOptions = true;
+ } else if (!strcmp(Opt, "print-phases")) {
+ CCCPrintPhases = true;
+ } else if (!strcmp(Opt, "cxx")) {
+ CCCIsCXX = true;
+ } else if (!strcmp(Opt, "echo")) {
+ CCCEcho = true;
+
+ } else if (!strcmp(Opt, "no-clang")) {
+ CCCNoClang = true;
+ } else if (!strcmp(Opt, "no-clang-cxx")) {
+ CCCNoClangCXX = true;
+ } else if (!strcmp(Opt, "no-clang-cpp")) {
+ CCCNoClangCPP = true;
+ } else if (!strcmp(Opt, "clang-archs")) {
+ assert(Start+1 < End && "FIXME: -ccc- argument handling.");
+ const char *Cur = *++Start;
+
+ for (;;) {
+ const char *Next = strchr(Cur, ',');
+
+ if (Next) {
+ CCCClangArchs.insert(std::string(Cur, Next));
+ Cur = Next + 1;
+ } else {
+ CCCClangArchs.insert(std::string(Cur));
+ break;
+ }
+ }
+
+ } else if (!strcmp(Opt, "host-bits")) {
+ assert(Start+1 < End && "FIXME: -ccc- argument handling.");
+ HostBits = *++Start;
+ } else if (!strcmp(Opt, "host-machine")) {
+ assert(Start+1 < End && "FIXME: -ccc- argument handling.");
+ HostMachine = *++Start;
+ } else if (!strcmp(Opt, "host-release")) {
+ assert(Start+1 < End && "FIXME: -ccc- argument handling.");
+ HostRelease = *++Start;
+ } else if (!strcmp(Opt, "host-system")) {
+ assert(Start+1 < End && "FIXME: -ccc- argument handling.");
+ HostSystem = *++Start;
+
+ } else {
+ // FIXME: Error handling.
+ llvm::errs() << "invalid option: " << *Start << "\n";
+ exit(1);
+ }
+ }
+
+ ArgList *Args = ParseArgStrings(Start, End);
+
+ // FIXME: This behavior shouldn't be here.
+ if (CCCPrintOptions) {
+ PrintOptions(Args);
+ exit(0);
+ }
+
+ assert(0 && "FIXME: Implement");
+
+ return new Compilation();
+}
+
+void Driver::PrintOptions(const ArgList *Args) {
unsigned i = 0;
- for (ArgList::iterator it = Args->begin(), ie = Args->end();
+ for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
it != ie; ++it, ++i) {
Arg *A = *it;
llvm::errs() << "Option " << i << " - "
}
llvm::errs() << "}\n";
}
-
- return new Compilation();
}
#include "clang/Driver/Options.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/System/Path.h"
#include "llvm/System/Signals.h"
using namespace clang::driver;
int main(int argc, const char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal();
- llvm::OwningPtr<Driver> TheDriver(new Driver());
+ // FIXME: We should use GetMainExecutable here, probably, but we may
+ // want to handle symbolic links slightly differently. The problem
+ // is that the path derived from this will influence search paths.
+ llvm::sys::Path Path(argv[0]);
+
+ llvm::OwningPtr<Driver> TheDriver(new Driver(Path.getBasename().c_str(),
+ Path.getDirname().c_str()));
llvm::OwningPtr<Compilation> C(TheDriver->BuildCompilation(argc, argv));