Ninja
browse.cc
Go to the documentation of this file.
1 // Copyright 2011 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "browse.h"
16 
17 #include <errno.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <vector>
22 
23 #include "build/browse_py.h"
24 
25 using namespace std;
26 
27 void RunBrowsePython(State* state, const char* ninja_command,
28  const char* input_file, int argc, char* argv[]) {
29  // Fork off a Python process and have it run our code via its stdin.
30  // (Actually the Python process becomes the parent.)
31  int pipefd[2];
32  if (pipe(pipefd) < 0) {
33  perror("ninja: pipe");
34  return;
35  }
36 
37  pid_t pid = fork();
38  if (pid < 0) {
39  perror("ninja: fork");
40  return;
41  }
42 
43  if (pid > 0) { // Parent.
44  close(pipefd[1]);
45  do {
46  if (dup2(pipefd[0], 0) < 0) {
47  perror("ninja: dup2");
48  break;
49  }
50 
51  std::vector<const char *> command;
52  command.push_back(NINJA_PYTHON);
53  command.push_back("-");
54  command.push_back("--ninja-command");
55  command.push_back(ninja_command);
56  command.push_back("-f");
57  command.push_back(input_file);
58  for (int i = 0; i < argc; i++) {
59  command.push_back(argv[i]);
60  }
61  command.push_back(NULL);
62  execvp(command[0], const_cast<char**>(&command[0]));
63  if (errno == ENOENT) {
64  printf("ninja: %s is required for the browse tool\n", NINJA_PYTHON);
65  } else {
66  perror("ninja: execvp");
67  }
68  } while (false);
69  _exit(1);
70  } else { // Child.
71  close(pipefd[0]);
72 
73  // Write the script file into the stdin of the Python process.
74  // Only write n - 1 bytes, because Python 3.11 does not allow null
75  // bytes in source code anymore, so avoid writing the null string
76  // terminator.
77  // See https://github.com/python/cpython/issues/96670
78  auto kBrowsePyLength = sizeof(kBrowsePy) - 1;
79  ssize_t len = write(pipefd[1], kBrowsePy, kBrowsePyLength);
80  if (len < (ssize_t)kBrowsePyLength)
81  perror("ninja: write");
82  close(pipefd[1]);
83  exit(0);
84  }
85 }
void RunBrowsePython(State *state, const char *ninja_command, const char *input_file, int argc, char *argv[])
Run in "browse" mode, which execs a Python webserver.
Definition: browse.cc:27
Definition: hash_map.h:26
Global state (file status) for a single run.
Definition: state.h:95