| # Copyright lowRISC contributors. |
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| # SPDX-License-Identifier: Apache-2.0 |
| |
| load("@rules_python//python:pip.bzl", "pip_install") |
| load("@python3//:defs.bzl", "interpreter") |
| |
| _WHEEL_BUILD_FILE_CONTENTS = """\ |
| package(default_visibility = ["//visibility:public"]) |
| |
| exports_files([ |
| "sanitized_requirements.txt", |
| ]) |
| |
| filegroup( |
| name = "all_wheels", |
| srcs = glob(["**/*.whl"]) |
| ) |
| """ |
| |
| def _pip_wheel_impl(rctx): |
| # First, check if an existing pre-built Python wheels repo exists, and if |
| # so, use it instead of building one. |
| python_wheel_repo_path = rctx.os.environ.get( |
| "BAZEL_PYTHON_WHEELS_REPO", |
| None, |
| ) |
| if python_wheel_repo_path: |
| rctx.report_progress("Mounting existing Python wheels repo") |
| rctx.symlink(python_wheel_repo_path, ".") |
| return |
| |
| # If a pre-built Python wheels repo does not exist, we need to build it. |
| rctx.report_progress("No Python wheels repo detected, building it instead") |
| |
| # First, we install the Python wheel package so we can build other wheels. |
| args = [ |
| rctx.path(rctx.attr.python_interpreter), |
| "-m", |
| "pip", |
| "install", |
| "-U", |
| "--ignore-installed", |
| "wheel", |
| ] |
| rctx.report_progress("Installing the Python wheel package") |
| result = rctx.execute( |
| args, |
| timeout = rctx.attr.timeout, |
| quiet = rctx.attr.quiet, |
| ) |
| if result.return_code: |
| fail("pip_wheel failed: {} ({})".format(result.stdout, result.stderr)) |
| |
| # Next, we download/build all the Python wheels for each requirement. |
| args = [ |
| rctx.path(rctx.attr.python_interpreter), |
| "-m", |
| "pip", |
| "wheel", |
| "-r", |
| rctx.path(rctx.attr.requirements), |
| "-w", |
| "./", |
| ] |
| rctx.report_progress("Pre-building Python wheels") |
| result = rctx.execute( |
| args, |
| timeout = rctx.attr.timeout, |
| quiet = rctx.attr.quiet, |
| ) |
| if result.return_code: |
| fail("pip_wheel failed: {} ({})".format(result.stdout, result.stderr)) |
| |
| # Last, we generate a new Python requirements file that does not contain any |
| # VCS links. We avoid just patching the existing python_requirements.txt |
| # file, and instead generate a requirements file based on the wheels that |
| # were built above. This enables us to make changes to the main |
| # python_requirements.txt file without impacting this step. |
| args = [rctx.path(rctx.attr._gen_requirements_script)] |
| rctx.report_progress("Generating sanitzed requirements file") |
| result = rctx.execute( |
| args, |
| timeout = rctx.attr.timeout, |
| quiet = rctx.attr.quiet, |
| working_directory = "./", |
| ) |
| if result.return_code: |
| fail("pip_wheel failed: {} ({})".format(result.stdout, result.stderr)) |
| |
| # We need a BUILD file to load the downloaded Python packages. |
| rctx.file( |
| "BUILD.bazel", |
| _WHEEL_BUILD_FILE_CONTENTS, |
| ) |
| |
| pip_wheel = repository_rule( |
| implementation = _pip_wheel_impl, |
| attrs = { |
| "python_interpreter": attr.label( |
| default = interpreter, |
| allow_single_file = True, |
| doc = "Python interpreter to use.", |
| ), |
| "requirements": attr.label( |
| default = "//:python-requirements.txt", |
| allow_single_file = True, |
| doc = "Python requirements file describing package dependencies.", |
| ), |
| "quiet": attr.bool( |
| default = True, |
| doc = "If True, suppress printing stdout/stderr to the terminal.", |
| ), |
| "timeout": attr.int( |
| default = 300, |
| doc = "Timeout (in seconds) on the rule's execution duration.", |
| ), |
| "_gen_requirements_script": attr.label( |
| default = "//third_party/python:gen_requirements.sh", |
| allow_single_file = True, |
| doc = "Shell script that generates a requirements file without VCS links.", |
| executable = True, |
| cfg = "exec", |
| ), |
| }, |
| environ = ["BAZEL_PYTHON_WHEELS_REPO"], |
| ) |
| |
| def pip_deps(): |
| pip_wheel( |
| name = "ot_python_wheels", |
| ) |
| pip_install( |
| name = "ot_python_deps", |
| python_interpreter_target = interpreter, |
| requirements = "@ot_python_wheels//:sanitized_requirements.txt", |
| find_links = "@ot_python_wheels//:all_wheels", |
| extra_pip_args = ["--no-index"], |
| ) |