Ninja
|
00001 // Copyright 2011 Google Inc. All Rights Reserved. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // http://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 00015 #include "msvc_helper.h" 00016 00017 #include <fcntl.h> 00018 #include <io.h> 00019 #include <stdio.h> 00020 #include <windows.h> 00021 00022 #include "util.h" 00023 00024 #include "getopt.h" 00025 00026 namespace { 00027 00028 void Usage() { 00029 printf( 00030 "usage: ninja -t msvc [options] -- cl.exe /showIncludes /otherArgs\n" 00031 "options:\n" 00032 " -e ENVFILE load environment block from ENVFILE as environment\n" 00033 " -o FILE write output dependency information to FILE.d\n" 00034 ); 00035 } 00036 00037 void PushPathIntoEnvironment(const string& env_block) { 00038 const char* as_str = env_block.c_str(); 00039 while (as_str[0]) { 00040 if (_strnicmp(as_str, "path=", 5) == 0) { 00041 _putenv(as_str); 00042 return; 00043 } else { 00044 as_str = &as_str[strlen(as_str) + 1]; 00045 } 00046 } 00047 } 00048 00049 void WriteDepFileOrDie(const char* object_path, const CLParser& parse) { 00050 string depfile_path = string(object_path) + ".d"; 00051 FILE* depfile = fopen(depfile_path.c_str(), "w"); 00052 if (!depfile) { 00053 unlink(object_path); 00054 Fatal("opening %s: %s", depfile_path.c_str(), 00055 GetLastErrorString().c_str()); 00056 } 00057 if (fprintf(depfile, "%s: ", object_path) < 0) { 00058 unlink(object_path); 00059 fclose(depfile); 00060 unlink(depfile_path.c_str()); 00061 Fatal("writing %s", depfile_path.c_str()); 00062 } 00063 const set<string>& headers = parse.includes_; 00064 for (set<string>::const_iterator i = headers.begin(); 00065 i != headers.end(); ++i) { 00066 if (fprintf(depfile, "%s\n", EscapeForDepfile(*i).c_str()) < 0) { 00067 unlink(object_path); 00068 fclose(depfile); 00069 unlink(depfile_path.c_str()); 00070 Fatal("writing %s", depfile_path.c_str()); 00071 } 00072 } 00073 fclose(depfile); 00074 } 00075 00076 } // anonymous namespace 00077 00078 int MSVCHelperMain(int argc, char** argv) { 00079 const char* output_filename = NULL; 00080 const char* envfile = NULL; 00081 00082 const option kLongOptions[] = { 00083 { "help", no_argument, NULL, 'h' }, 00084 { NULL, 0, NULL, 0 } 00085 }; 00086 int opt; 00087 while ((opt = getopt_long(argc, argv, "e:o:h", kLongOptions, NULL)) != -1) { 00088 switch (opt) { 00089 case 'e': 00090 envfile = optarg; 00091 break; 00092 case 'o': 00093 output_filename = optarg; 00094 break; 00095 case 'h': 00096 default: 00097 Usage(); 00098 return 0; 00099 } 00100 } 00101 00102 string env; 00103 if (envfile) { 00104 string err; 00105 if (ReadFile(envfile, &env, &err) != 0) 00106 Fatal("couldn't open %s: %s", envfile, err.c_str()); 00107 PushPathIntoEnvironment(env); 00108 } 00109 00110 char* command = GetCommandLine(); 00111 command = strstr(command, " -- "); 00112 if (!command) { 00113 Fatal("expected command line to end with \" -- command args\""); 00114 } 00115 command += 4; 00116 00117 CLWrapper cl; 00118 if (!env.empty()) 00119 cl.SetEnvBlock((void*)env.data()); 00120 string output; 00121 int exit_code = cl.Run(command, &output); 00122 00123 if (output_filename) { 00124 CLParser parser; 00125 output = parser.Parse(output); 00126 WriteDepFileOrDie(output_filename, parser); 00127 } 00128 00129 // CLWrapper's output already as \r\n line endings, make sure the C runtime 00130 // doesn't expand this to \r\r\n. 00131 _setmode(_fileno(stdout), _O_BINARY); 00132 printf("%s", output.c_str()); 00133 00134 return exit_code; 00135 }