aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/launcher/launcher.h
blob: a5f6920b57bcfb23ce451a4517be93a3f73dcf00 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright 2017 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef BAZEL_SRC_TOOLS_LAUNCHER_LAUNCHER_H_
#define BAZEL_SRC_TOOLS_LAUNCHER_LAUNCHER_H_

#include <string>
#include <unordered_map>
#include <vector>

#include "src/tools/launcher/util/data_parser.h"

namespace bazel {
namespace launcher {

typedef int32_t ExitCode;
static constexpr const char* WORKSPACE_NAME = "workspace_name";

// The maximum length of lpCommandLine is 32768 characters.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
static const int MAX_CMDLINE_LENGTH = 32768;

struct CmdLine {
  wchar_t cmdline[MAX_CMDLINE_LENGTH];
};

class BinaryLauncherBase {
  typedef std::unordered_map<std::wstring, std::wstring> ManifestFileMap;

 public:
  BinaryLauncherBase(const LaunchDataParser::LaunchInfo& launch_info, int argc,
                     wchar_t* argv[]);

  virtual ~BinaryLauncherBase() = default;

  // Get launch information based on a launch info key.
  std::wstring GetLaunchInfoByKey(const std::string& key);

  // Get the original command line arguments passed to this binary.
  const std::vector<std::wstring>& GetCommandlineArguments() const;

  // Map a runfile path to its absolute path.
  //
  // If need_workspace_name is true, then this method prepend workspace name to
  // path before doing rlocation.
  // If need_workspace_name is false, then this method uses path directly.
  // The default value of need_workspace_name is true.
  std::wstring Rlocation(const std::wstring& path,
                         bool need_workspace_name = true) const;
  std::wstring Rlocation(const std::string& path,
                         bool need_workspace_name = true) const;

  // Lauch a process with given executable and command line arguments.
  // If --print_launcher_command exists in arguments, then we print the full
  // command line instead of launching the real process.
  //
  // exectuable: the binary to be executed.
  // arguments:  the command line arguments to be passed to the exectuable,
  //             it doesn't include the exectuable itself.
  //             The arguments are expected to be quoted if having spaces.
  ExitCode LaunchProcess(const std::wstring& executable,
                         const std::vector<std::wstring>& arguments,
                         bool suppressOutput = false) const;

  // A launch function to be implemented for a specific language.
  virtual ExitCode Launch() = 0;

  // Return the runfiles directory of this binary.
  //
  // The method appends ".exe.runfiles" to the first command line argument,
  // converts forward slashes to back slashes, then returns that.
  std::wstring GetRunfilesPath() const;

 private:
  // A map to store all the launch information.
  const LaunchDataParser::LaunchInfo& launch_info;

  // Absolute path to the runfiles manifest file, if one exists.
  const std::wstring manifest_file;

  // Path to the runfiles directory, if one exists.
  const std::wstring runfiles_dir;

  // The commandline arguments recieved.
  // The first argument is the path of this launcher itself.
  std::vector<std::wstring> commandline_arguments;

  // The workspace name of the repository this target belongs to.
  const std::wstring workspace_name;

  // A map to store all entries of the manifest file.
  ManifestFileMap manifest_file_map;

  // If --print_launcher_command is presented in arguments,
  // then print the command line.
  //
  // Return true if command line is printed.
  bool PrintLauncherCommandLine(
      const std::wstring& executable,
      const std::vector<std::wstring>& arguments) const;

  // Create a command line to be passed to Windows CreateProcessA API.
  //
  // exectuable: the binary to be executed.
  // arguments:  the command line arguments to be passed to the exectuable,
  //             it doesn't include the exectuable itself.
  void CreateCommandLine(CmdLine* result, const std::wstring& executable,
                         const std::vector<std::wstring>& arguments) const;

  // Find manifest file of the binary.
  //
  // Expect the manifest file to be at
  //    1. <path>/<to>/<binary>/<target_name>.runfiles/MANIFEST
  // or 2. <path>/<to>/<binary>/<target_name>.runfiles_manifest
  static std::wstring FindManifestFile(const wchar_t* argv0);

  // Parse manifest file into a map
  static void ParseManifestFile(ManifestFileMap* manifest_file_map,
                                const std::wstring& manifest_path);
};

}  // namespace launcher
}  // namespace bazel

#endif  // BAZEL_SRC_TOOLS_LAUNCHER_LAUNCHER_H_