kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/cxx/extractor/objc_bazel_support.cc (about) 1 /* 2 * Copyright 2016 The Kythe Authors. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "objc_bazel_support.h" 18 19 #include <stdio.h> 20 21 #include <algorithm> 22 #include <cstddef> 23 #include <cstdio> 24 #include <sstream> 25 #include <string> 26 #include <vector> 27 28 #include "google/protobuf/repeated_ptr_field.h" 29 #include "llvm/ADT/StringRef.h" 30 #include "re2/re2.h" 31 #include "third_party/bazel/src/main/protobuf/extra_actions_base.pb.h" 32 33 namespace kythe { 34 35 // This is inspiried by Python's commands.mkarg 36 // https://hg.python.org/cpython/file/tip/Lib/commands.py#l81 37 std::string SanitizeArgument(const std::string& s) { 38 if (s.find('\'') == std::string::npos) { 39 // There are no single quotes, so we can make the string safe by putting it 40 // in single quotes. 41 return "'" + s + "'"; 42 } 43 // There are single quotes in the string, so we will wrap it in double quotes 44 // and escape backslash, double-quote, dollar, and back-tick. 45 std::string ret = s; 46 RE2::GlobalReplace(&ret, R"(([\\"$`]))", R"(\\\1)"); 47 return "\"" + ret + "\""; 48 } 49 50 std::string BuildEnvVarCommandPrefix( 51 const google::protobuf::RepeatedPtrField<blaze::EnvironmentVariable>& 52 vars) { 53 std::stringstream ret; 54 for (const auto& env : vars) { 55 // Neither name nor value are validated or sanitized. 56 // This really should be unnecessary, but we don't have any guarantees. 57 if (RE2::FullMatch(env.name(), "[a-zA-Z_][a-zA-Z_0-9]*")) { 58 ret << env.name() << "=" << SanitizeArgument(env.value()) << " "; 59 } 60 } 61 return ret.str(); 62 } 63 64 std::string RunScript(const std::string& cmd) { 65 char buffer[256]; 66 std::string output = ""; 67 FILE* f = popen(cmd.c_str(), "r"); 68 if (!f) { 69 return output; 70 } 71 while (!feof(f)) { 72 if (fgets(buffer, 256, f) != nullptr) { 73 output += buffer; 74 } 75 } 76 pclose(f); 77 return std::string(llvm::StringRef(output).trim()); 78 } 79 80 void FillWithFixedArgs(std::vector<std::string>& args, 81 const blaze::CppCompileInfo& ci, 82 const std::string& devdir, const std::string& sdkroot) { 83 args.push_back(ci.tool()); 84 for (const auto& i : ci.compiler_option()) { 85 std::string arg = i; 86 RE2::GlobalReplace(&arg, "__BAZEL_XCODE_DEVELOPER_DIR__", devdir); 87 RE2::GlobalReplace(&arg, "__BAZEL_XCODE_SDKROOT__", sdkroot); 88 args.push_back(arg); 89 } 90 // If the command-line did not specify "-c x.m" specifically, include the 91 // primary source at the end of the argument list. 92 if (std::find(args.begin(), args.end(), "-c") == args.end()) { 93 args.push_back(ci.source_file()); 94 } 95 } 96 97 void FillWithFixedArgs(std::vector<std::string>& args, 98 const blaze::SpawnInfo& si, const std::string& devdir, 99 const std::string& sdkroot) { 100 for (const auto& i : si.argument()) { 101 std::string arg = i; 102 RE2::GlobalReplace(&arg, "__BAZEL_XCODE_DEVELOPER_DIR__", devdir); 103 RE2::GlobalReplace(&arg, "__BAZEL_XCODE_SDKROOT__", sdkroot); 104 args.push_back(arg); 105 } 106 } 107 108 } // namespace kythe