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

feat(bzlmod): support cross-platform whl setups within the main hub repo #1837

Merged
merged 20 commits into from
Jun 6, 2024

Conversation

aignas
Copy link
Collaborator

@aignas aignas commented Apr 8, 2024

With this change we add support for platform-specific wheel registration and
doing the selection of which wheel is used at build time.

This supports:

  • Different package versions for different platforms.
  • Use string_flags to configure what to fetch/select:
    • only whls, only sdist or auto mode.
    • libc version and musl vs glibc selection.
    • universal2 vs arch wheels for mac.
    • target osx version selection.

Summary of changes:

  • The uv pip install would only warn the user of yanked packages but
    would not refuse to install them. Update our implementation to better
    match the same behaviour.
  • A previous PR has added the support for passing it in the
    requirements_by_platform and this just add the necessary code to make
    sure that we can also do the dependency management when parsing the
    whl METADATA files.
  • Only configure dev_pip deps for linux and osx platforms to not raise
    issues later.
  • Add a function for generating a whl_library name from a filename.
  • Add a macro for generating all config settings for a particular set of parameters.
  • Update render_pkg_aliases to also use those config settings.
  • Update the toolchain selection target_settings to use the py_linux_libc
    config setting. With this the user can register a musl linux toolchain if
    needed. We can also use similar flag_values to resolve Consider supporting armv7-unknown-linux-gnueabi/hf toolchain #1876.
  • Integrate everything in the pip extension and setup cross-platform
    select statements.

Work towards #1357, #260

Stacked on #1937

@aignas
Copy link
Collaborator Author

aignas commented Apr 14, 2024

I think I've identified at least multiple changes that can be separate PRs:

@aignas
Copy link
Collaborator Author

aignas commented May 18, 2024

This now needs to be reimplemented/rebased on #1875 and #1885.

@aignas aignas force-pushed the feat/multi-platform-whls branch 2 times, most recently from 6c19b7b to 6ad9f4a Compare May 30, 2024 05:36
@aignas aignas self-assigned this May 30, 2024
@aignas
Copy link
Collaborator Author

aignas commented May 31, 2024

@dougthor42, if you have time, I'd be curious if you could try this PR, It may have the same issue as #1917, but if does not, then it would be a really interesting data point.

@dougthor42
Copy link
Contributor

A different error than previously seen. This one is:

ERROR: Traceback (most recent call last):
        File "/usr/local/google/home/dthor/.cache/bazel/_bazel_dthor/dbe74c4144b5c9a438d84a119652bef9/external/rules_python~/python/private/bzlmod/pip.bzl", line 481, column 30, in _pip_impl
                _create_whl_repos(module_ctx, pip_attr, hub_whl_map, whl_overrides, hub_group_map, simpleapi_cache)
        File "/usr/local/google/home/dthor/.cache/bazel/_bazel_dthor/dbe74c4144b5c9a438d84a119652bef9/external/rules_python~/python/private/bzlmod/pip.bzl", line 276, column 32, in _create_whl_repos
                whl_library(name = repo_name, **dict(sorted(whl_library_args.items())))
Error in repository_rule: invalid user-provided repo name 'pypi_311__REDACTED_0_1_0+7_g9c9466d_py3_none_any': valid names may contain only A-Z, a-z, 0-9, '-', '_', '.', and must start with a letter
ERROR: Analysis of target '//src/pyle/dataking/system_optimization/snake_optimizer:snake_metrics_test' failed; build aborted: error evaluating module extension pip in @@rules_python~//python/extensions:pip.bzl

Some of our internal packages include the short git commit hash in their wheel name.

@aignas aignas marked this pull request as ready for review June 1, 2024 05:13
@aignas aignas requested a review from rickeylev as a code owner June 1, 2024 05:13
@aignas
Copy link
Collaborator Author

aignas commented Jun 1, 2024

This still needs an updated git commit message and more docs, but the functionality is there and is covered by tests, so it should be ready to test/review.

I'll add more docs later.

Sorry for the big PR, but I am not sure if it is possible to split it without loosing the context that is happening all over the pip.parse extension.

This should be portable to the WORKSPACE world, but I would like to leave this out of scope for now.

@aignas aignas changed the title feat(bzlmod): support multi-platform wheel hubs [WIP] feat(bzlmod): support cross-platform whl setups within the main hub repo Jun 1, 2024
@aignas aignas requested a review from f0rmiga as a code owner June 2, 2024 10:57
@aignas
Copy link
Collaborator Author

aignas commented Jun 2, 2024

Right now the only tests that fail are on Windows and they fail with a weird:

(15:03:02) WARNING: C:/b/bk-windows-nznf/bazel/rules-python-python/docs/BUILD.bazel:47:6: target '//docs:requirements_parser_bzl' is deprecated: Use //python/pip_install:pip_repository_bzl instead; Both the requirements parser and targets under //docs are internal
(15:03:14) ERROR: C:/b/bk-windows-nznf/bazel/rules-python-python/tests/config_settings/transition/BUILD.bazel:6:25: in _transition_py_binary rule //tests/config_settings/transition:test_py_binary_with_transition_subject:
Traceback (most recent call last):
	File "C:/b/bk-windows-nznf/bazel/rules-python-python/python/config_settings/transition.bzl", line 78, column 13, in _transition_py_impl
		fail("target {} does not have rules_python PyRuntimeInfo or builtin PyRuntimeInfo".format(target))
Error in fail: target <target //tests/config_settings/transition:_test_py_binary_with_transition_subject> does not have rules_python PyRuntimeInfo or builtin PyRuntimeInfo
(15:03:14) ERROR: C:/b/bk-windows-nznf/bazel/rules-python-python/tests/config_settings/transition/BUILD.bazel:6:25: in _transition_py_test rule //tests/config_settings/transition:test_py_test_with_transition_subject:
Traceback (most recent call last):
	File "C:/b/bk-windows-nznf/bazel/rules-python-python/python/config_settings/transition.bzl", line 78, column 13, in _transition_py_impl
		fail("target {} does not have rules_python PyRuntimeInfo or builtin PyRuntimeInfo".format(target))

I'll finish here for the day. I might split out the last commit out as a separate PR since that is a small distinct change that is related to the big multi-platform change, but we can land it separately.

…lled

With this PR we can finally have fewer lock file entries in setups which
do not use the `experimental_index_url` feature yet. This is fully
backwards compatible change as it relies on `bazel` doing the right
thing and regenerating the lock file.

Fixes bazelbuild#1643.
@aignas
Copy link
Collaborator Author

aignas commented Jun 2, 2024

Done, split out the lock-file related work into #1937, so once that one is merged, the diff here will shrink a tiny bit, but not by much.

The `uv pip install` would only warn the user of yanked packages but
would not refuse to install them. Update our implementation to better
match the same behaviour.
A previous PR has added the support for passing it in the
`requirements_by_platform` and this just add the necessary code to make
sure that we can also do the dependency management when parsing the
`whl` `METADATA` files.
…ndows

This fixes a small issue with our dependency configuration for the
documentation building. It is missing `colorama` and probably a few
other dependencies to work on windows, but I am not sure if the
other `sphinx` machinery supports non UNIX.
With this we can ensure that the name is unique (we use `sha256` and
prefix it with `pip_hub` repo), valid (we use `sha256` instead of the
version or the build tag of the whl filename) and easy to understand (we
add the python tag, abi tag and platform tags to the end of the name to
ensure that users have an easy way to navigate the files).
This also changes `is_python_config_setting` so that it can accept extra
`flag_values` so that we can reuse it for the cases where we want
something that is more specific than `is_python_config_setting` with a
`python_version` alone.
…ames

This code will use the config settings generated by
`pip_config_settings` in all cases and when the `whl_alias` instances
are generated by passing `filename` values, then we will also use the
platform-specific config settings from the `//_config` package in the
hub repo.
With this we start using the `py_linux_libc` flag value in toolchains as
well and ensure that no hermetic toolchain will be matched when we
specify to pull the `musl` wheels. In that case the user will need to
supply their own toolchain that is the expected behaviour.

However, I am not sure how we could fail due to no available toolchain
in that case because the autodetecting toolchain will just use the host
interpreter.
This feature leverages all of the foundational work from previous
commits and updates the tests and documentation.
@aignas
Copy link
Collaborator Author

aignas commented Jun 3, 2024

Merged the main since I saw some auto-detecting toolchain changelog present, so just to make sure that I am not missing out on anything.


def _test_simple(env):
got = pip_repo_name("prefix", "foo-1.2.3-py3-none-any.whl", "deadbeef")
env.expect.that_str(got).equals("prefix_foo_py3_none_any_deadbeef")
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Using sha is good enough for the first pass, but PR welcome for including the version (and optionally the build tag) in the repo name.

Copy link
Collaborator

Choose a reason for hiding this comment

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

We will need to keep this experimental until we settle on the names. Or at least remember to update if we change it and it breaks for users.

}
)

def pip_config_settings(
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This could be a good alternative to the current is_python_config_setting implementation as it would reduce the number of flags that we generate.

#
# If the toolchain is not resolved then you will have a weird message telling
# you that your transition target does not have a PyRuntime provider, which is
# caused by there not being a toolchain detected for the target.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The tests were working previously because even though the test is setting a specific python_version via a transition, the toolchain that we were getting was the default version. So in this case the actual version would be returned would be different from the one requested in the transition.

This could explain some of the issues we've seen recently about people saying that the toolchain is mismatching their configuration as it could happen if they do not configure the default toolchain version in their MODULE.bazel file.

I wonder if this should be mentioned in the CHANGELOG.md. I'll do it for the sake of posterity.

@dougthor42
Copy link
Contributor

Still failing on the foobar package that has a md5 for both py311 and py312 🫤

It's a different failure, though, so that's good!

$ bazel clean; bazel build //...
INFO: Invocation ID: cefb7077-a468-4283-b711-06897aff5e1d
INFO: Starting clean (this may take a while). Consider using --async if the clean takes more than several minutes.
INFO: Invocation ID: 84fe841f-1ab2-4990-9261-165044c971ac
ERROR: /usr/local/google/home/dthor/.cache/bazel/_bazel_dthor/dbe74c4144b5c9a438d84a119652bef9/external/rules_python~~pip~pypi/_config/BUILD.bazel: no such target '@@rules_python~~pip~pypi//_config:is_py311_none_manylinux_x86_64': target 'is_py311_none_manylinux_x86_64' not declared in package '_config' defined by /usr/local/google/home/dthor/.cache/bazel/_bazel_dthor/dbe74c4144b5c9a438d84a119652bef9/external/rules_python~~pip~pypi/_config/BUILD.bazel (did you mean is_py3_none_manylinux_x86_64, _is_py3_none_manylinux_x86_64, is_py_none_manylinux_x86_64, _is_py_none_manylinux_x86_64, is_cp3x_none_manylinux_x86_64, or is_py3_none_any_linux_x86_64?)
ERROR: /usr/local/google/home/dthor/.cache/bazel/_bazel_dthor/dbe74c4144b5c9a438d84a119652bef9/external/rules_python~~pip~pypi/foobar/BUILD.bazel:53:6: errors encountered resolving select() keys for @@rules_python~~pip~pypi//foobar:whl
Use --verbose_failures to see the command lines of failed build steps.
ERROR: Analysis of target '//:modules_map' failed; build aborted: Analysis failed
INFO: Elapsed time: 1.091s, Critical Path: 0.63s
INFO: 18 processes: 18 internal.
ERROR: Build did NOT complete successfully

@aignas
Copy link
Collaborator Author

aignas commented Jun 4, 2024

@dougthor42, sorry for that one, now should be fixed

@dougthor42
Copy link
Contributor

Yup! 445337e worked for me 👍

I noticed that the runfiles directory now has more info in the path name:

  • the wheel name
  • the head of the wheel sha
-test.runfiles/rules_python~~pip~pypi_311_foobar/
+test.runfiles/rules_python~~pip~pypi_311_foobar_py311_none_manylinux_2_17_x86_64_b7d2f441/

These are great changes! Super useful. Should such a change be included in the changelog?

Copy link
Collaborator

@groodt groodt left a comment

Choose a reason for hiding this comment

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

LGTM

As mentioned at the maintainers review, we might need to keep exploring alternatives for the explosion of config flags, but I don't think it needs to be blocking while we iterate.

@aignas
Copy link
Collaborator Author

aignas commented Jun 5, 2024

@groodt, thanks for the stamp, could you also stamp #1937 please?

Comment on lines -56 to +74
elif set_python_version_constraint == "False":
target_settings = []
target_settings = [name]
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The absence of this branch is the root cause of #1967.

aignas added a commit to aignas/rules_python that referenced this pull request Nov 1, 2024
…ames

Initially the repo name generate was very conservative and we had sha256
as the endings of the repo names. With this change we have more human
readable repository names. In order to still comply with the bazel label
rules, we are normalizing the versions to only have `_` and `.`
characters.

This is an alternative fix to the error message seen in
bazelbuild#1837 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consider supporting armv7-unknown-linux-gnueabi/hf toolchain
3 participants