diff --git a/src/tools/launcher/bash_launcher.cc b/src/tools/launcher/bash_launcher.cc index 56b77275c1f152..3a9b6849b429f0 100644 --- a/src/tools/launcher/bash_launcher.cc +++ b/src/tools/launcher/bash_launcher.cc @@ -52,11 +52,7 @@ ExitCode BashBinaryLauncher::Launch() { vector origin_args = this->GetCommandlineArguments(); wostringstream bash_command; - // In case the given binary path is a shortened Windows 8dot3 path, we need to - // convert it back to its long path form before using it to find the bash main - // file. - wstring full_binary_path = GetWindowsLongPath(origin_args[0]); - wstring bash_main_file = GetBinaryPathWithoutExtension(full_binary_path); + wstring bash_main_file = GetBinaryPathWithoutExtension(GetExecutableFile()); bash_command << BashEscapeArg(bash_main_file); for (int i = 1; i < origin_args.size(); i++) { bash_command << L' '; diff --git a/src/tools/launcher/bash_launcher.h b/src/tools/launcher/bash_launcher.h index b00828109f81b9..bb4d97d7fc9640 100644 --- a/src/tools/launcher/bash_launcher.h +++ b/src/tools/launcher/bash_launcher.h @@ -22,9 +22,11 @@ namespace launcher { class BashBinaryLauncher : public BinaryLauncherBase { public: - BashBinaryLauncher(const LaunchDataParser::LaunchInfo& launch_info, int argc, + BashBinaryLauncher(const LaunchDataParser::LaunchInfo& launch_info, + const std::wstring& executable_file, + int argc, wchar_t* argv[]) - : BinaryLauncherBase(launch_info, argc, argv) {} + : BinaryLauncherBase(launch_info, executable_file, argc, argv) {} ~BashBinaryLauncher() override = default; ExitCode Launch() override; }; diff --git a/src/tools/launcher/java_launcher.cc b/src/tools/launcher/java_launcher.cc index 12cb6a82b97c14..1d90e2514d0f4c 100644 --- a/src/tools/launcher/java_launcher.cc +++ b/src/tools/launcher/java_launcher.cc @@ -162,8 +162,7 @@ static void WriteJarClasspath(const wstring& jar_path, } wstring JavaBinaryLauncher::GetJunctionBaseDir() { - wstring binary_base_path = - GetBinaryPathWithExtension(this->GetCommandlineArguments()[0]); + wstring binary_base_path = GetBinaryPathWithExtension(GetExecutableFile()); wstring result; if (!NormalizePath(binary_base_path + L".j", &result)) { die(L"Failed to get normalized junction base directory."); @@ -191,8 +190,7 @@ void JavaBinaryLauncher::DeleteJunctionBaseDir() { } wstring JavaBinaryLauncher::CreateClasspathJar(const wstring& classpath) { - wstring binary_base_path = - GetBinaryPathWithoutExtension(this->GetCommandlineArguments()[0]); + wstring binary_base_path = GetBinaryPathWithoutExtension(GetExecutableFile()); wstring abs_manifest_jar_dir_norm = GetManifestJarDir(binary_base_path); wostringstream manifest_classpath; @@ -312,7 +310,7 @@ ExitCode JavaBinaryLauncher::Launch() { // Run deploy jar if needed, otherwise generate the CLASSPATH by rlocation. if (this->singlejar) { wstring deploy_jar = - GetBinaryPathWithoutExtension(this->GetCommandlineArguments()[0]) + + GetBinaryPathWithoutExtension(GetExecutableFile()) + L"_deploy.jar"; if (!DoesFilePathExist(deploy_jar.c_str())) { die(L"Option --singlejar was passed, but %s does not exist.\n (You may " diff --git a/src/tools/launcher/java_launcher.h b/src/tools/launcher/java_launcher.h index 1881d587d998d8..e0e4ff62b16b8b 100644 --- a/src/tools/launcher/java_launcher.h +++ b/src/tools/launcher/java_launcher.h @@ -29,9 +29,11 @@ static const int MAX_ARG_STRLEN = 7000; class JavaBinaryLauncher : public BinaryLauncherBase { public: - JavaBinaryLauncher(const LaunchDataParser::LaunchInfo& launch_info, int argc, + JavaBinaryLauncher(const LaunchDataParser::LaunchInfo& launch_info, + const std::wstring& executable_file, + int argc, wchar_t* argv[]) - : BinaryLauncherBase(launch_info, argc, argv), + : BinaryLauncherBase(launch_info, executable_file, argc, argv), singlejar(false), print_javabin(false), classpath_limit(MAX_ARG_STRLEN) {} diff --git a/src/tools/launcher/launcher.cc b/src/tools/launcher/launcher.cc index 2d30bb4ed047ec..6406162c31f292 100644 --- a/src/tools/launcher/launcher.cc +++ b/src/tools/launcher/launcher.cc @@ -42,14 +42,14 @@ using std::vector; using std::wostringstream; using std::wstring; -static wstring GetRunfilesDir(const wchar_t* argv0) { +static wstring GetRunfilesDir(const wchar_t* executable_file) { 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(L"RUNFILES_DIR", &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. - runfiles_dir = GetBinaryPathWithExtension(argv0) + L".runfiles"; + runfiles_dir = GetBinaryPathWithExtension(executable_file) + L".runfiles"; } // Make sure we return a normalized absolute path. if (!blaze_util::IsAbsolute(runfiles_dir)) { @@ -63,10 +63,14 @@ static wstring GetRunfilesDir(const wchar_t* argv0) { } BinaryLauncherBase::BinaryLauncherBase( - const LaunchDataParser::LaunchInfo& _launch_info, int argc, wchar_t* argv[]) - : launch_info(_launch_info), - manifest_file(FindManifestFile(argv[0])), - runfiles_dir(GetRunfilesDir(argv[0])), + const LaunchDataParser::LaunchInfo& _launch_info, + const std::wstring& executable_file, + int argc, + wchar_t* argv[]) + : executable_file(executable_file), + launch_info(_launch_info), + manifest_file(FindManifestFile(executable_file.c_str())), + runfiles_dir(GetRunfilesDir(executable_file.c_str())), workspace_name(GetLaunchInfoByKey(WORKSPACE_NAME)), symlink_runfiles_enabled(GetLaunchInfoByKey(SYMLINK_RUNFILES_ENABLED) == L"1") { @@ -81,7 +85,8 @@ BinaryLauncherBase::BinaryLauncherBase( } } -static bool FindManifestFileImpl(const wchar_t* argv0, wstring* result) { +static bool FindManifestFileImpl(const wchar_t* executable_file, + 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(L"RUNFILES_MANIFEST_FILE", result) && @@ -100,7 +105,7 @@ static bool FindManifestFileImpl(const wchar_t* argv0, wstring* 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) + L".runfiles"; + directory = GetBinaryPathWithExtension(executable_file) + L".runfiles"; *result = directory + L"/MANIFEST"; if (DoesFilePathExist(result->c_str())) { return true; @@ -114,9 +119,9 @@ static bool FindManifestFileImpl(const wchar_t* argv0, wstring* result) { return false; } -wstring BinaryLauncherBase::FindManifestFile(const wchar_t* argv0) { +wstring BinaryLauncherBase::FindManifestFile(const wchar_t* executable_file) { wstring manifest_file; - if (!FindManifestFileImpl(argv0, &manifest_file)) { + if (!FindManifestFileImpl(executable_file, &manifest_file)) { return L""; } // The path will be set as the RUNFILES_MANIFEST_FILE envvar and used by the @@ -125,9 +130,13 @@ wstring BinaryLauncherBase::FindManifestFile(const wchar_t* argv0) { return manifest_file; } +wstring BinaryLauncherBase::GetExecutableFile() const { + return executable_file; +} + wstring BinaryLauncherBase::GetRunfilesPath() const { wstring runfiles_path = - GetBinaryPathWithExtension(this->commandline_arguments[0]) + L".runfiles"; + GetBinaryPathWithExtension(executable_file) + L".runfiles"; std::replace(runfiles_path.begin(), runfiles_path.end(), L'/', L'\\'); return runfiles_path; } diff --git a/src/tools/launcher/launcher.h b/src/tools/launcher/launcher.h index c2e8cf16417986..510582407bd612 100644 --- a/src/tools/launcher/launcher.h +++ b/src/tools/launcher/launcher.h @@ -41,7 +41,9 @@ class BinaryLauncherBase { typedef std::unordered_map ManifestFileMap; public: - BinaryLauncherBase(const LaunchDataParser::LaunchInfo& launch_info, int argc, + BinaryLauncherBase(const LaunchDataParser::LaunchInfo& launch_info, + const std::wstring& executable_file, + int argc, wchar_t* argv[]); virtual ~BinaryLauncherBase() = default; @@ -77,13 +79,22 @@ class BinaryLauncherBase { // A launch function to be implemented for a specific language. virtual ExitCode Launch() = 0; + // Returns the path of the launcher's executable file. + // + // The returned path is always a long path, that is, it never contains 8.3 + // style filenames. + std::wstring GetExecutableFile() const; + // 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. + // The method appends ".exe.runfiles" to the path of the launcher executable, + // converts forward slashes to backslashes, then returns that. std::wstring GetRunfilesPath() const; private: + // The path of the launcher binary. + const std::wstring executable_file; + // A map to store all the launch information. const LaunchDataParser::LaunchInfo& launch_info; @@ -127,7 +138,7 @@ class BinaryLauncherBase { // Expect the manifest file to be at // 1. ///.runfiles/MANIFEST // or 2. ///.runfiles_manifest - static std::wstring FindManifestFile(const wchar_t* argv0); + static std::wstring FindManifestFile(const wchar_t* executable_file); // Parse manifest file into a map static void ParseManifestFile(ManifestFileMap* manifest_file_map, diff --git a/src/tools/launcher/launcher_main.cc b/src/tools/launcher/launcher_main.cc index e2fc4735e47276..6a1af63bad8743 100644 --- a/src/tools/launcher/launcher_main.cc +++ b/src/tools/launcher/launcher_main.cc @@ -45,6 +45,7 @@ static constexpr const char* BINARY_TYPE = "binary_type"; using bazel::launcher::BashBinaryLauncher; using bazel::launcher::BinaryLauncherBase; using bazel::launcher::GetBinaryPathWithExtension; +using bazel::launcher::GetWindowsLongPath; using bazel::launcher::JavaBinaryLauncher; using bazel::launcher::LaunchDataParser; using bazel::launcher::PythonBinaryLauncher; @@ -64,7 +65,12 @@ static std::wstring GetExecutableFileName() { } int wmain(int argc, wchar_t* argv[]) { - const std::wstring executable_file = GetExecutableFileName(); + // In case the given binary path is a shortened Windows 8dot3 path, we convert + // it back to its long path form so that path manipulations (e.g. appending + // ".runfiles") work as expected. Note that GetExecutableFileName may return a + // path different from argv[0]. + const std::wstring executable_file = + GetWindowsLongPath(GetExecutableFileName()); LaunchDataParser::LaunchInfo launch_info; if (!LaunchDataParser::GetLaunchInfo(executable_file, &launch_info)) { die(L"Failed to parse launch info."); @@ -81,9 +87,11 @@ int wmain(int argc, wchar_t* argv[]) { binary_launcher = make_unique( launch_info, executable_file, argc, argv); } else if (result->second == L"Bash") { - binary_launcher = make_unique(launch_info, argc, argv); + binary_launcher = make_unique( + launch_info, executable_file, argc, argv); } else if (result->second == L"Java") { - binary_launcher = make_unique(launch_info, argc, argv); + binary_launcher = make_unique( + launch_info, executable_file, argc, argv); } else { die(L"Unknown binary type, cannot launch anything."); } diff --git a/src/tools/launcher/python_launcher.cc b/src/tools/launcher/python_launcher.cc index 6a0b487f1a3623..e37cbaba98c3bf 100644 --- a/src/tools/launcher/python_launcher.cc +++ b/src/tools/launcher/python_launcher.cc @@ -56,14 +56,10 @@ ExitCode PythonBinaryLauncher::Launch() { vector args = this->GetCommandlineArguments(); wstring use_zip_file = this->GetLaunchInfoByKey(USE_ZIP_FILE); wstring python_file; - // In case the given binary path is a shortened Windows 8dot3 path, we need to - // convert it back to its long path form before using it to find the python - // file. - wstring full_binary_path = GetWindowsLongPath(executable_file_); if (use_zip_file == L"1") { - python_file = GetBinaryPathWithoutExtension(full_binary_path) + L".zip"; + python_file = GetBinaryPathWithoutExtension(GetExecutableFile()) + L".zip"; } else { - python_file = GetBinaryPathWithoutExtension(full_binary_path); + python_file = GetBinaryPathWithoutExtension(GetExecutableFile()); } // Replace the first argument with python file path diff --git a/src/tools/launcher/python_launcher.h b/src/tools/launcher/python_launcher.h index eb1ca6d2a17ce8..266e4b4a8ceaee 100644 --- a/src/tools/launcher/python_launcher.h +++ b/src/tools/launcher/python_launcher.h @@ -26,14 +26,12 @@ namespace launcher { class PythonBinaryLauncher : public BinaryLauncherBase { public: PythonBinaryLauncher(const LaunchDataParser::LaunchInfo& launch_info, - std::wstring executable_file, int argc, wchar_t* argv[]) - : BinaryLauncherBase(launch_info, argc, argv), - executable_file_(std::move(executable_file)) {} + const std::wstring& executable_file, + int argc, + wchar_t* argv[]) + : BinaryLauncherBase(launch_info, executable_file, argc, argv) {} ~PythonBinaryLauncher() override = default; ExitCode Launch() override; - - private: - std::wstring executable_file_; }; } // namespace launcher