31 "usage: ninja -t msvc [options] -- cl.exe /showIncludes /otherArgs\n" 33 " -e ENVFILE load environment block from ENVFILE as environment\n" 34 " -o FILE write output dependency information to FILE.d\n" 35 " -p STRING localized prefix of msvc's /showIncludes output\n" 39 void PushPathIntoEnvironment(
const string& env_block) {
40 const char* as_str = env_block.c_str();
42 if (_strnicmp(as_str,
"path=", 5) == 0) {
46 as_str = &as_str[strlen(as_str) + 1];
51 void WriteDepFileOrDie(
const char* object_path,
const CLParser& parse) {
52 string depfile_path = string(object_path) +
".d";
53 FILE* depfile = fopen(depfile_path.c_str(),
"w");
56 Fatal(
"opening %s: %s", depfile_path.c_str(),
57 GetLastErrorString().c_str());
59 if (fprintf(depfile,
"%s: ", object_path) < 0) {
62 unlink(depfile_path.c_str());
63 Fatal(
"writing %s", depfile_path.c_str());
65 const set<string>& headers = parse.
includes_;
66 for (set<string>::const_iterator i = headers.begin();
67 i != headers.end(); ++i) {
71 unlink(depfile_path.c_str());
72 Fatal(
"writing %s", depfile_path.c_str());
81 const char* output_filename = NULL;
82 const char* envfile = NULL;
84 const option kLongOptions[] = {
90 while ((opt =
getopt_long(argc, argv,
"e:o:p:h", kLongOptions, NULL)) != -1) {
111 if (
ReadFile(envfile, &env, &err) != 0)
112 Fatal(
"couldn't open %s: %s", envfile, err.c_str());
113 PushPathIntoEnvironment(env);
116 char* command = GetCommandLineA();
117 command = strstr(command,
" -- ");
119 Fatal(
"expected command line to end with \" -- command args\"");
127 int exit_code = cl.
Run(command, &output);
129 if (output_filename) {
132 if (!parser.
Parse(output, deps_prefix, &output, &err))
133 Fatal(
"%s\n", err.c_str());
134 WriteDepFileOrDie(output_filename, parser);
142 _setmode(_fileno(stdout), _O_BINARY);
145 fwrite(&output[0], 1, output.size(), stdout);
int MSVCHelperMain(int argc, char **argv)
int getopt_long(int argc, char **argv, const char *shortopts, const GETOPT_LONG_OPTION_T *longopts, int *longind)
int ReadFile(const string &path, string *contents, string *err)
Read a file to a string (in text mode: with CRLF conversion on Windows).
int Run(const string &command, string *output)
Start a process and gather its raw output.
void Fatal(const char *msg,...)
Log a fatal message and exit.
Visual Studio's cl.exe requires some massaging to work with Ninja; for example, it emits include info...
Wraps a synchronous execution of a CL subprocess.
string EscapeForDepfile(const string &path)
void SetEnvBlock(void *env_block)
Set the environment block (as suitable for CreateProcess) to be used by Run().
bool Parse(const string &output, const string &deps_prefix, string *filtered_output, string *err)
Parse the full output of cl, filling filtered_output with the text that should be printed (if any)...