Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows, launcher: support python/bash toolchain #8440

Closed
wants to merge 7 commits into from

Conversation

meteorcloudy
Copy link
Member

Previously, we assume the python/bash binary path passed to the launcher is an absolute path specified by --python_path or --shell_executable, but this is not true when using python/shell toolchain. When using the python toolchain, the given python binary path will be a runfile path, we can use Rlocation to find the absolute path.

Fixes #7947

@@ -30,6 +30,10 @@ static constexpr const char* BASH_BIN_PATH = "bash_bin_path";

ExitCode BashBinaryLauncher::Launch() {
wstring bash_binary = this->GetLaunchInfoByKey(BASH_BIN_PATH);

// Rlocation returns the original path if bash_binary is an absolute path.
bash_binary = this->Rlocation(bash_binary, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the input bash_binary ever be just bash.exe for example, which would mean "whatever is on the PATH"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are two ways to tell which shell binary to use, BAZEL_SH or --shell_executable. Both way requires user to set an absolute path. The only case bash_binary is a relative path (runfile path) is that when using shell toolchain (similar to python toolchain), but I'm not sure it's implemented.

@@ -30,6 +30,10 @@ static constexpr const char* WINDOWS_STYLE_ESCAPE_JVM_FLAGS = "escape_args";

ExitCode PythonBinaryLauncher::Launch() {
wstring python_binary = this->GetLaunchInfoByKey(PYTHON_BIN_PATH);

// Rlocation returns the original path if python_binary is an absolute path.
python_binary = this->Rlocation(python_binary, true);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But here, python_binary will just be python if nothing is specified.. I need to fix this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, let me know when the PR is ready for another review.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching the problem! Please take a look again. ;)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, just realized I had a typo. It should be GetBinaryPathWithoutExtension(bash_binary) != L"bash"), GetBinaryPathWithoutExtension just strips out the ending .exe if there is any. I wanted to check if bash_binary is already bash or bash.exe. Similar for the python case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add comment for this!

src/tools/launcher/bash_launcher.cc Outdated Show resolved Hide resolved
@@ -30,6 +30,12 @@ static constexpr const char* WINDOWS_STYLE_ESCAPE_JVM_FLAGS = "escape_args";

ExitCode PythonBinaryLauncher::Launch() {
wstring python_binary = this->GetLaunchInfoByKey(PYTHON_BIN_PATH);

if (GetBinaryPathWithoutExtension(python_binary) == L"python") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What other values could python_binary have, and in what situations?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to shell, we have

  1. --python_path, gives an absolute path
  2. --python_top, gives an runfile path
  3. python toolchain (py_runtime), gives a runfile path
  4. Default if nothing specified: python

@brandjon Can confirm this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Waiting for @brandjon to confirm before LGTM. Please add a comment in the code summarizing Jon's answer.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do that!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both --python_top and Python toolchains select a py_runtime to use. py_runtime provides a runfiles path if its interpreter attribute is set, and an absolute path if its interpreter_path attribute is set (these attributes are exclusive).

--python_path is validated to be an absolute path. If nothing is specified, the python default is passed along the same code path that --python_path uses but skips this validation check as a special case. It is intended that both of these approaches are deprecated and replaced by toolchains, with the python PATH lookup behavior provided by an autodetecting toolchain.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the confirmation, I'll add those to comment

@brandjon
Copy link
Member

I don't understand how this change is supposed to work. How do you rlocation a binary in runfiles if the runfiles are packed in a zip that has yet to be extracted (by the zip file's __main__.py entry point)? We'd need to move the extraction logic into the launcher, no?

I'm not sure how much test coverage for Python we have on windows. Some of the tests I wrote I've disabled because we haven't had both Python 2 and 3 on the test machines until recently. See #8411.

@meteorcloudy
Copy link
Member Author

How do you rlocation a binary in runfiles if the runfiles are packed in a zip that has yet to be extracted (by the zip file's main.py entry point)?

We don't rlocation in runfiles, the rlocation function reads the MANIFEST file and maps a runfile path (relative path) to its absolute path. This way doesn't care if there is a runfiles tree or not, so it will also work when people using --build_python_zip=0 and --enable_runfiles.

Some of the tests I wrote I've disabled because we haven't had both Python 2 and 3 on the test machines until recently.

Yes, we definitely need to enable those test.

@laszlocsomor
Copy link
Contributor

And I presume the code works with --build_python_zip=True too?

@meteorcloudy
Copy link
Member Author

Yes, --build_python_zip=True is by default

Copy link
Contributor

@laszlocsomor laszlocsomor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, please wait for Jon's LGTM too

Copy link
Member

@brandjon brandjon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but please wait for my fix to #8411 so we have some test coverage.

@@ -30,6 +30,17 @@ static constexpr const char* WINDOWS_STYLE_ESCAPE_JVM_FLAGS = "escape_args";

ExitCode PythonBinaryLauncher::Launch() {
wstring python_binary = this->GetLaunchInfoByKey(PYTHON_BIN_PATH);

// The value of python_binary could be the following cases:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rewrite comment as follows:

There are three kinds of values for python_binary:

  1. An absolute path to a system interpreter. This is the case if --python_path is set by the user, or if a py_runtime is used that has interpreter_path set.
  2. A runfile path to an in-workspace interpreter. This is the case if a py_runtime is used that has interpreter set.
  3. The special constant, "python". This is the default case if neither of the above apply.
    Rlocation resolves runfiles paths to absolute paths, and if given an absolute path it leaves it alone, so it's suitable for cases 1 and 2.

There's a slight detail that the default toolchain's py_runtime on windows contains a sentinel value hack that tells bazel to use legacy --python_path, but I don't think we need to mention that in this comment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for help with the comment!

@bazel-io bazel-io closed this in b68d3c1 May 29, 2019
irengrig pushed a commit to irengrig/bazel that referenced this pull request Jun 18, 2019
Previously, we assume the python/bash binary path passed to the launcher is an absolute path specified by `--python_path` or `--shell_executable`, but this is not true when using python/shell toolchain. When using the python toolchain, the given python binary path will be a runfile path, we can use `Rlocation` to find the absolute path.

Fixes bazelbuild#7947

Closes bazelbuild#8440.

PiperOrigin-RevId: 250569171
irengrig pushed a commit to irengrig/bazel that referenced this pull request Jul 15, 2019
Previously, we assume the python/bash binary path passed to the launcher is an absolute path specified by `--python_path` or `--shell_executable`, but this is not true when using python/shell toolchain. When using the python toolchain, the given python binary path will be a runfile path, we can use `Rlocation` to find the absolute path.

Fixes bazelbuild#7947

Closes bazelbuild#8440.

PiperOrigin-RevId: 250569171
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Neither python_top nor python toolchain works with starlark actions on windows
4 participants