diff options
author | 2018-06-25 05:35:50 -0700 | |
---|---|---|
committer | 2018-06-25 05:36:55 -0700 | |
commit | 40f5a773e97d0e389838becd3fe0a8ab43853999 (patch) | |
tree | 2c2aec321caa559b43787281fd097a7545eacc28 /src/tools/launcher/launcher.cc | |
parent | d753745d58fc45fcb50623073829644812083da0 (diff) |
Windows: Native launcher now works with unicode.
The native launcher can now launch Java and Bash binary in
directory with non-English characters.
Unfortunately, python doesn't support running python zip file under
directory with non-English characters. eg. python ./??/bin.zip will
still fail.
See https://github.com/bazelbuild/bazel/issues/4473
Change-Id: I77fe9cdaabffc2e0d25c7097da5c0c9333a9c4a3
PiperOrigin-RevId: 201939391
Diffstat (limited to 'src/tools/launcher/launcher.cc')
-rw-r--r-- | src/tools/launcher/launcher.cc | 132 |
1 files changed, 70 insertions, 62 deletions
diff --git a/src/tools/launcher/launcher.cc b/src/tools/launcher/launcher.cc index 9bcc3642c2..b663c2cc77 100644 --- a/src/tools/launcher/launcher.cc +++ b/src/tools/launcher/launcher.cc @@ -21,6 +21,7 @@ #include <vector> #include "src/main/cpp/util/path_platform.h" +#include "src/main/cpp/util/strings.h" #include "src/tools/launcher/launcher.h" #include "src/tools/launcher/util/data_parser.h" #include "src/tools/launcher/util/launcher_util.h" @@ -29,25 +30,26 @@ namespace bazel { namespace launcher { using std::ifstream; -using std::ostringstream; using std::string; using std::unordered_map; using std::vector; +using std::wostringstream; +using std::wstring; -static std::string GetRunfilesDir(const char* argv0) { - string runfiles_dir; +static wstring GetRunfilesDir(const wchar_t* argv0) { + wstring runfiles_dir; // If RUNFILES_DIR is already set (probably we are either in a test or in a // data dependency) then use it. - if (GetEnv("RUNFILES_DIR", &runfiles_dir)) { + if (GetEnv(L"RUNFILES_DIR", &runfiles_dir)) { return runfiles_dir; } // Otherwise this is probably a top-level non-test binary (e.g. a genrule // tool) and should look for its runfiles beside the executable. - return GetBinaryPathWithExtension(argv0) + ".runfiles"; + return GetBinaryPathWithExtension(argv0) + L".runfiles"; } BinaryLauncherBase::BinaryLauncherBase( - const LaunchDataParser::LaunchInfo& _launch_info, int argc, char* argv[]) + const LaunchDataParser::LaunchInfo& _launch_info, int argc, wchar_t* argv[]) : launch_info(_launch_info), manifest_file(FindManifestFile(argv[0])), runfiles_dir(GetRunfilesDir(argv[0])), @@ -58,22 +60,22 @@ BinaryLauncherBase::BinaryLauncherBase( // Prefer to use the runfiles manifest, if it exists, but otherwise the // runfiles directory will be used by default. On Windows, the manifest is // used locally, and the runfiles directory is used remotely. - if (manifest_file != "") { + if (!manifest_file.empty()) { ParseManifestFile(&manifest_file_map, manifest_file); } } -static bool FindManifestFileImpl(const char* argv0, string* result) { +static bool FindManifestFileImpl(const wchar_t* argv0, wstring* result) { // If this binary X runs as the data-dependency of some other binary Y, then // X has no runfiles manifest/directory and should use Y's. - if (GetEnv("RUNFILES_MANIFEST_FILE", result) && + if (GetEnv(L"RUNFILES_MANIFEST_FILE", result) && DoesFilePathExist(result->c_str())) { return true; } - string directory; - if (GetEnv("RUNFILES_DIR", &directory)) { - *result = directory + "/MANIFEST"; + wstring directory; + if (GetEnv(L"RUNFILES_DIR", &directory)) { + *result = directory + L"/MANIFEST"; if (DoesFilePathExist(result->c_str())) { return true; } @@ -82,13 +84,13 @@ static bool FindManifestFileImpl(const char* argv0, string* result) { // If this binary X runs by itself (not as a data-dependency of another // binary), then look for the manifest in a runfiles directory next to the // main binary, then look for it (the manifest) next to the main binary. - directory = GetBinaryPathWithExtension(argv0) + ".runfiles"; - *result = directory + "/MANIFEST"; + directory = GetBinaryPathWithExtension(argv0) + L".runfiles"; + *result = directory + L"/MANIFEST"; if (DoesFilePathExist(result->c_str())) { return true; } - *result = directory + "_manifest"; + *result = directory + L"_manifest"; if (DoesFilePathExist(result->c_str())) { return true; } @@ -96,10 +98,10 @@ static bool FindManifestFileImpl(const char* argv0, string* result) { return false; } -string BinaryLauncherBase::FindManifestFile(const char* argv0) { - string manifest_file; +wstring BinaryLauncherBase::FindManifestFile(const wchar_t* argv0) { + wstring manifest_file; if (!FindManifestFileImpl(argv0, &manifest_file)) { - return ""; + return L""; } // The path will be set as the RUNFILES_MANIFEST_FILE envvar and used by the // shell script, so let's convert backslashes to forward slashes. @@ -107,35 +109,36 @@ string BinaryLauncherBase::FindManifestFile(const char* argv0) { return manifest_file; } -string BinaryLauncherBase::GetRunfilesPath() const { - string runfiles_path = - GetBinaryPathWithExtension(this->commandline_arguments[0]) + ".runfiles"; - std::replace(runfiles_path.begin(), runfiles_path.end(), '/', '\\'); +wstring BinaryLauncherBase::GetRunfilesPath() const { + wstring runfiles_path = + GetBinaryPathWithExtension(this->commandline_arguments[0]) + L".runfiles"; + std::replace(runfiles_path.begin(), runfiles_path.end(), L'/', L'\\'); return runfiles_path; } void BinaryLauncherBase::ParseManifestFile(ManifestFileMap* manifest_file_map, - const string& manifest_path) { + const wstring& manifest_path) { ifstream manifest_file(AsAbsoluteWindowsPath(manifest_path.c_str()).c_str()); if (!manifest_file) { - die("Couldn't open MANIFEST file: %s", manifest_path.c_str()); + die(L"Couldn't open MANIFEST file: %s", manifest_path.c_str()); } string line; while (getline(manifest_file, line)) { size_t space_pos = line.find_first_of(' '); if (space_pos == string::npos) { - die("Wrong MANIFEST format at line: %s", line.c_str()); + die(L"Wrong MANIFEST format at line: %s", line.c_str()); } - string key = line.substr(0, space_pos); - string value = line.substr(space_pos + 1); + wstring wline = blaze_util::CstringToWstring(line); + wstring key = wline.substr(0, space_pos); + wstring value = wline.substr(space_pos + 1); manifest_file_map->insert(make_pair(key, value)); } } -string BinaryLauncherBase::Rlocation(const string& path, - bool need_workspace_name) const { +wstring BinaryLauncherBase::Rlocation(const wstring& path, + bool need_workspace_name) const { // If the manifest file map is empty, then we're using the runfiles directory // instead. if (manifest_file_map.empty()) { @@ -143,106 +146,111 @@ string BinaryLauncherBase::Rlocation(const string& path, return path; } - string query_path = runfiles_dir; + wstring query_path = runfiles_dir; if (need_workspace_name) { - query_path += "/" + this->workspace_name; + query_path += L"/" + this->workspace_name; } - query_path += "/" + path; + query_path += L"/" + path; return query_path; } - string query_path = path; + wstring query_path = path; if (need_workspace_name) { - query_path = this->workspace_name + "/" + path; + query_path = this->workspace_name + L"/" + path; } auto entry = manifest_file_map.find(query_path); if (entry == manifest_file_map.end()) { - die("Rlocation failed on %s, path doesn't exist in MANIFEST file", + die(L"Rlocation failed on %s, path doesn't exist in MANIFEST file", query_path.c_str()); } return entry->second; } -string BinaryLauncherBase::GetLaunchInfoByKey(const string& key) { +wstring BinaryLauncherBase::Rlocation(const string& path, + bool need_workspace_name) const { + return this->Rlocation(blaze_util::CstringToWstring(path), + need_workspace_name); +} + +wstring BinaryLauncherBase::GetLaunchInfoByKey(const string& key) { auto item = launch_info.find(key); if (item == launch_info.end()) { - die("Cannot find key \"%s\" from launch data.\n", key.c_str()); + die(L"Cannot find key \"%hs\" from launch data.\n", key.c_str()); } return item->second; } -const vector<string>& BinaryLauncherBase::GetCommandlineArguments() const { +const vector<wstring>& BinaryLauncherBase::GetCommandlineArguments() const { return this->commandline_arguments; } void BinaryLauncherBase::CreateCommandLine( - CmdLine* result, const string& executable, - const vector<string>& arguments) const { - ostringstream cmdline; - cmdline << '\"' << executable << '\"'; + CmdLine* result, const wstring& executable, + const vector<wstring>& arguments) const { + wostringstream cmdline; + cmdline << L'\"' << executable << L'\"'; for (const auto& s : arguments) { - cmdline << ' ' << s; + cmdline << L' ' << s; } - string cmdline_str = cmdline.str(); + wstring cmdline_str = cmdline.str(); if (cmdline_str.size() >= MAX_CMDLINE_LENGTH) { - die("Command line too long: %s", cmdline_str.c_str()); + die(L"Command line too long: %s", cmdline_str.c_str()); } // Copy command line into a mutable buffer. // CreateProcess is allowed to mutate its command line argument. - strncpy(result->cmdline, cmdline_str.c_str(), MAX_CMDLINE_LENGTH - 1); + wcsncpy(result->cmdline, cmdline_str.c_str(), MAX_CMDLINE_LENGTH - 1); result->cmdline[MAX_CMDLINE_LENGTH - 1] = 0; } bool BinaryLauncherBase::PrintLauncherCommandLine( - const string& executable, const vector<string>& arguments) const { + const wstring& executable, const vector<wstring>& arguments) const { bool has_print_cmd_flag = false; for (const auto& arg : arguments) { - has_print_cmd_flag |= (arg == "--print_launcher_command"); + has_print_cmd_flag |= (arg == L"--print_launcher_command"); } if (has_print_cmd_flag) { - printf("%s\n", executable.c_str()); + wprintf(L"%s\n", executable.c_str()); for (const auto& arg : arguments) { - printf("%s\n", arg.c_str()); + wprintf(L"%s\n", arg.c_str()); } } return has_print_cmd_flag; } -ExitCode BinaryLauncherBase::LaunchProcess(const string& executable, - const vector<string>& arguments, +ExitCode BinaryLauncherBase::LaunchProcess(const wstring& executable, + const vector<wstring>& arguments, bool suppressOutput) const { if (PrintLauncherCommandLine(executable, arguments)) { return 0; } - if (manifest_file != "") { - SetEnv("RUNFILES_MANIFEST_ONLY", "1"); - SetEnv("RUNFILES_MANIFEST_FILE", manifest_file); + if (!manifest_file.empty()) { + SetEnv(L"RUNFILES_MANIFEST_ONLY", L"1"); + SetEnv(L"RUNFILES_MANIFEST_FILE", manifest_file); } else { - SetEnv("RUNFILES_DIR", runfiles_dir); + SetEnv(L"RUNFILES_DIR", runfiles_dir); } CmdLine cmdline; CreateCommandLine(&cmdline, executable, arguments); PROCESS_INFORMATION processInfo = {0}; - STARTUPINFOA startupInfo = {0}; + STARTUPINFOW startupInfo = {0}; startupInfo.cb = sizeof(startupInfo); - BOOL ok = CreateProcessA( + BOOL ok = CreateProcessW( /* lpApplicationName */ NULL, /* lpCommandLine */ cmdline.cmdline, /* lpProcessAttributes */ NULL, /* lpThreadAttributes */ NULL, /* bInheritHandles */ FALSE, /* dwCreationFlags */ - suppressOutput ? CREATE_NO_WINDOW // no console window => no output - : 0, + suppressOutput ? CREATE_NO_WINDOW // no console window => no output + : 0, /* lpEnvironment */ NULL, /* lpCurrentDirectory */ NULL, /* lpStartupInfo */ &startupInfo, /* lpProcessInformation */ &processInfo); if (!ok) { - PrintError("Cannot launch process: %s\nReason: %s", - cmdline.cmdline, + PrintError(L"Cannot launch process: %s\nReason: %hs", cmdline.cmdline, GetLastErrorString().c_str()); return GetLastError(); } |