33 "usage: ninja -t msvc [options] -- cl.exe /showIncludes /otherArgs\n"
35 " -e ENVFILE load environment block from ENVFILE as environment\n"
36 " -o FILE write output dependency information to FILE.d\n"
37 " -p STRING localized prefix of msvc's /showIncludes output\n"
41 void PushPathIntoEnvironment(
const string& env_block) {
42 const char* as_str = env_block.c_str();
44 if (_strnicmp(as_str,
"path=", 5) == 0) {
48 as_str = &as_str[strlen(as_str) + 1];
53 void WriteDepFileOrDie(
const char* object_path,
const CLParser& parse) {
54 string depfile_path = string(object_path) +
".d";
55 FILE* depfile = fopen(depfile_path.c_str(),
"w");
58 Fatal(
"opening %s: %s", depfile_path.c_str(),
59 GetLastErrorString().c_str());
61 if (fprintf(depfile,
"%s: ", object_path) < 0) {
65 Fatal(
"writing %s", depfile_path.c_str());
67 const set<string>& headers = parse.
includes_;
68 for (set<string>::const_iterator i = headers.begin();
69 i != headers.end(); ++i) {
74 Fatal(
"writing %s", depfile_path.c_str());
83 const char* output_filename = NULL;
84 const char* envfile = NULL;
86 const option kLongOptions[] = {
92 while ((opt =
getopt_long(argc, argv,
"e:o:p:h", kLongOptions, NULL)) != -1) {
113 if (
ReadFile(envfile, &env, &err) != 0)
114 Fatal(
"couldn't open %s: %s", envfile, err.c_str());
115 PushPathIntoEnvironment(env);
118 char* command = GetCommandLineA();
119 command = strstr(command,
" -- ");
121 Fatal(
"expected command line to end with \" -- command args\"");
129 int exit_code = cl.
Run(command, &output);
131 if (output_filename) {
134 if (!parser.
Parse(output, deps_prefix, &output, &err))
135 Fatal(
"%s\n", err.c_str());
136 WriteDepFileOrDie(output_filename, parser);
144 _setmode(_fileno(stdout), _O_BINARY);
147 fwrite(&output[0], 1, output.size(), stdout);
int getopt_long(int argc, char **argv, const char *shortopts, const GETOPT_LONG_OPTION_T *longopts, int *longind)
string EscapeForDepfile(const string &path)
int MSVCHelperMain(int argc, char **argv)
Visual Studio's cl.exe requires some massaging to work with Ninja; for example, it emits include info...
std::set< std::string > includes_
bool Parse(const std::string &output, const std::string &deps_prefix, std::string *filtered_output, std::string *err)
Parse the full output of cl, filling filtered_output with the text that should be printed (if any).
Wraps a synchronous execution of a CL subprocess.
int Run(const std::string &command, std::string *output)
Start a process and gather its raw output.
void SetEnvBlock(void *env_block)
Set the environment block (as suitable for CreateProcess) to be used by Run().
int platformAwareUnlink(const char *filename)
void Fatal(const char *msg,...)
Log a fatal message and exit.
int ReadFile(const string &path, string *contents, string *err)