1695b41eeSopenharmony_ci// Copyright 2011 Google Inc. All Rights Reserved. 2695b41eeSopenharmony_ci// 3695b41eeSopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4695b41eeSopenharmony_ci// you may not use this file except in compliance with the License. 5695b41eeSopenharmony_ci// You may obtain a copy of the License at 6695b41eeSopenharmony_ci// 7695b41eeSopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8695b41eeSopenharmony_ci// 9695b41eeSopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10695b41eeSopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11695b41eeSopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12695b41eeSopenharmony_ci// See the License for the specific language governing permissions and 13695b41eeSopenharmony_ci// limitations under the License. 14695b41eeSopenharmony_ci 15695b41eeSopenharmony_ci#include "msvc_helper.h" 16695b41eeSopenharmony_ci 17695b41eeSopenharmony_ci#include <fcntl.h> 18695b41eeSopenharmony_ci#include <io.h> 19695b41eeSopenharmony_ci#include <stdio.h> 20695b41eeSopenharmony_ci#include <windows.h> 21695b41eeSopenharmony_ci 22695b41eeSopenharmony_ci#include "clparser.h" 23695b41eeSopenharmony_ci#include "util.h" 24695b41eeSopenharmony_ci 25695b41eeSopenharmony_ci#include "getopt.h" 26695b41eeSopenharmony_ci 27695b41eeSopenharmony_ciusing namespace std; 28695b41eeSopenharmony_ci 29695b41eeSopenharmony_cinamespace { 30695b41eeSopenharmony_ci 31695b41eeSopenharmony_civoid Usage() { 32695b41eeSopenharmony_ci printf( 33695b41eeSopenharmony_ci"usage: ninja -t msvc [options] -- cl.exe /showIncludes /otherArgs\n" 34695b41eeSopenharmony_ci"options:\n" 35695b41eeSopenharmony_ci" -e ENVFILE load environment block from ENVFILE as environment\n" 36695b41eeSopenharmony_ci" -o FILE write output dependency information to FILE.d\n" 37695b41eeSopenharmony_ci" -p STRING localized prefix of msvc's /showIncludes output\n" 38695b41eeSopenharmony_ci ); 39695b41eeSopenharmony_ci} 40695b41eeSopenharmony_ci 41695b41eeSopenharmony_civoid PushPathIntoEnvironment(const string& env_block) { 42695b41eeSopenharmony_ci const char* as_str = env_block.c_str(); 43695b41eeSopenharmony_ci while (as_str[0]) { 44695b41eeSopenharmony_ci if (_strnicmp(as_str, "path=", 5) == 0) { 45695b41eeSopenharmony_ci _putenv(as_str); 46695b41eeSopenharmony_ci return; 47695b41eeSopenharmony_ci } else { 48695b41eeSopenharmony_ci as_str = &as_str[strlen(as_str) + 1]; 49695b41eeSopenharmony_ci } 50695b41eeSopenharmony_ci } 51695b41eeSopenharmony_ci} 52695b41eeSopenharmony_ci 53695b41eeSopenharmony_civoid WriteDepFileOrDie(const char* object_path, const CLParser& parse) { 54695b41eeSopenharmony_ci string depfile_path = string(object_path) + ".d"; 55695b41eeSopenharmony_ci FILE* depfile = fopen(depfile_path.c_str(), "w"); 56695b41eeSopenharmony_ci if (!depfile) { 57695b41eeSopenharmony_ci unlink(object_path); 58695b41eeSopenharmony_ci Fatal("opening %s: %s", depfile_path.c_str(), 59695b41eeSopenharmony_ci GetLastErrorString().c_str()); 60695b41eeSopenharmony_ci } 61695b41eeSopenharmony_ci if (fprintf(depfile, "%s: ", object_path) < 0) { 62695b41eeSopenharmony_ci unlink(object_path); 63695b41eeSopenharmony_ci fclose(depfile); 64695b41eeSopenharmony_ci unlink(depfile_path.c_str()); 65695b41eeSopenharmony_ci Fatal("writing %s", depfile_path.c_str()); 66695b41eeSopenharmony_ci } 67695b41eeSopenharmony_ci const set<string>& headers = parse.includes_; 68695b41eeSopenharmony_ci for (set<string>::const_iterator i = headers.begin(); 69695b41eeSopenharmony_ci i != headers.end(); ++i) { 70695b41eeSopenharmony_ci if (fprintf(depfile, "%s\n", EscapeForDepfile(*i).c_str()) < 0) { 71695b41eeSopenharmony_ci unlink(object_path); 72695b41eeSopenharmony_ci fclose(depfile); 73695b41eeSopenharmony_ci unlink(depfile_path.c_str()); 74695b41eeSopenharmony_ci Fatal("writing %s", depfile_path.c_str()); 75695b41eeSopenharmony_ci } 76695b41eeSopenharmony_ci } 77695b41eeSopenharmony_ci fclose(depfile); 78695b41eeSopenharmony_ci} 79695b41eeSopenharmony_ci 80695b41eeSopenharmony_ci} // anonymous namespace 81695b41eeSopenharmony_ci 82695b41eeSopenharmony_ciint MSVCHelperMain(int argc, char** argv) { 83695b41eeSopenharmony_ci const char* output_filename = NULL; 84695b41eeSopenharmony_ci const char* envfile = NULL; 85695b41eeSopenharmony_ci 86695b41eeSopenharmony_ci const option kLongOptions[] = { 87695b41eeSopenharmony_ci { "help", no_argument, NULL, 'h' }, 88695b41eeSopenharmony_ci { NULL, 0, NULL, 0 } 89695b41eeSopenharmony_ci }; 90695b41eeSopenharmony_ci int opt; 91695b41eeSopenharmony_ci string deps_prefix; 92695b41eeSopenharmony_ci while ((opt = getopt_long(argc, argv, "e:o:p:h", kLongOptions, NULL)) != -1) { 93695b41eeSopenharmony_ci switch (opt) { 94695b41eeSopenharmony_ci case 'e': 95695b41eeSopenharmony_ci envfile = optarg; 96695b41eeSopenharmony_ci break; 97695b41eeSopenharmony_ci case 'o': 98695b41eeSopenharmony_ci output_filename = optarg; 99695b41eeSopenharmony_ci break; 100695b41eeSopenharmony_ci case 'p': 101695b41eeSopenharmony_ci deps_prefix = optarg; 102695b41eeSopenharmony_ci break; 103695b41eeSopenharmony_ci case 'h': 104695b41eeSopenharmony_ci default: 105695b41eeSopenharmony_ci Usage(); 106695b41eeSopenharmony_ci return 0; 107695b41eeSopenharmony_ci } 108695b41eeSopenharmony_ci } 109695b41eeSopenharmony_ci 110695b41eeSopenharmony_ci string env; 111695b41eeSopenharmony_ci if (envfile) { 112695b41eeSopenharmony_ci string err; 113695b41eeSopenharmony_ci if (ReadFile(envfile, &env, &err) != 0) 114695b41eeSopenharmony_ci Fatal("couldn't open %s: %s", envfile, err.c_str()); 115695b41eeSopenharmony_ci PushPathIntoEnvironment(env); 116695b41eeSopenharmony_ci } 117695b41eeSopenharmony_ci 118695b41eeSopenharmony_ci char* command = GetCommandLineA(); 119695b41eeSopenharmony_ci command = strstr(command, " -- "); 120695b41eeSopenharmony_ci if (!command) { 121695b41eeSopenharmony_ci Fatal("expected command line to end with \" -- command args\""); 122695b41eeSopenharmony_ci } 123695b41eeSopenharmony_ci command += 4; 124695b41eeSopenharmony_ci 125695b41eeSopenharmony_ci CLWrapper cl; 126695b41eeSopenharmony_ci if (!env.empty()) 127695b41eeSopenharmony_ci cl.SetEnvBlock((void*)env.data()); 128695b41eeSopenharmony_ci string output; 129695b41eeSopenharmony_ci int exit_code = cl.Run(command, &output); 130695b41eeSopenharmony_ci 131695b41eeSopenharmony_ci if (output_filename) { 132695b41eeSopenharmony_ci CLParser parser; 133695b41eeSopenharmony_ci string err; 134695b41eeSopenharmony_ci if (!parser.Parse(output, deps_prefix, &output, &err)) 135695b41eeSopenharmony_ci Fatal("%s\n", err.c_str()); 136695b41eeSopenharmony_ci WriteDepFileOrDie(output_filename, parser); 137695b41eeSopenharmony_ci } 138695b41eeSopenharmony_ci 139695b41eeSopenharmony_ci if (output.empty()) 140695b41eeSopenharmony_ci return exit_code; 141695b41eeSopenharmony_ci 142695b41eeSopenharmony_ci // CLWrapper's output already as \r\n line endings, make sure the C runtime 143695b41eeSopenharmony_ci // doesn't expand this to \r\r\n. 144695b41eeSopenharmony_ci _setmode(_fileno(stdout), _O_BINARY); 145695b41eeSopenharmony_ci // Avoid printf and C strings, since the actual output might contain null 146695b41eeSopenharmony_ci // bytes like UTF-16 does (yuck). 147695b41eeSopenharmony_ci fwrite(&output[0], 1, output.size(), stdout); 148695b41eeSopenharmony_ci 149695b41eeSopenharmony_ci return exit_code; 150695b41eeSopenharmony_ci} 151