Skip to content

Commit e40b609

Browse files
authored
fix: use runfiles symlinks for venv symlink creation to reduce action count (#3402)
When the venv files are materialized, it can result in many symlink actions being created. Rather than register them as regular symlink actions, batch them into the runfiles object, which can probably handle large numbers of them more efficiently. Work towards #3401
1 parent 4dca7e5 commit e40b609

File tree

2 files changed

+23
-10
lines changed

2 files changed

+23
-10
lines changed

python/private/py_executable.bzl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ def _create_executable(
356356
[stage2_bootstrap] + (
357357
venv.files_without_interpreter if venv else []
358358
),
359-
)
359+
).merge(venv.lib_runfiles)
360360
zip_main = _create_zip_main(
361361
ctx,
362362
stage2_bootstrap = stage2_bootstrap,
@@ -606,7 +606,7 @@ def _create_venv(ctx, output_prefix, imports, runtime_details):
606606
}
607607
venv_app_files = create_venv_app_files(ctx, ctx.attr.deps, venv_dir_map)
608608

609-
files_without_interpreter = [pth, site_init] + venv_app_files
609+
files_without_interpreter = [pth, site_init] + venv_app_files.venv_files
610610
if pyvenv_cfg:
611611
files_without_interpreter.append(pyvenv_cfg)
612612

@@ -629,6 +629,11 @@ def _create_venv(ctx, output_prefix, imports, runtime_details):
629629
venv,
630630
),
631631
),
632+
# venv files for user library dependencies (files that are specific
633+
# to the executable bootstrap and python runtime aren't here).
634+
lib_runfiles = ctx.runfiles(
635+
symlinks = venv_app_files.runfiles_symlinks,
636+
),
632637
)
633638

634639
def _map_each_identity(v):

python/private/venv_runfiles.bzl

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@ def create_venv_app_files(ctx, deps, venv_dir_map):
3030
paths within the current ctx's venv (e.g. `_foo.venv/bin`).
3131
3232
Returns:
33-
{type}`list[File]` of the files that were created.
33+
{type}`struct` with the following attributes:
34+
* {type}`list[File]` `venv_files` additional files created for
35+
the venv.
36+
* {type}`dict[str, File]` `runfiles_symlinks` map intended for
37+
the `runfiles.symlinks` argument. A map of main-repo
38+
relative paths to File.
3439
"""
3540

3641
# maps venv-relative path to the runfiles path it should point to
@@ -44,16 +49,16 @@ def create_venv_app_files(ctx, deps, venv_dir_map):
4449

4550
link_map = build_link_map(ctx, entries)
4651
venv_files = []
52+
runfiles_symlinks = {}
53+
4754
for kind, kind_map in link_map.items():
4855
base = venv_dir_map[kind]
4956
for venv_path, link_to in kind_map.items():
5057
bin_venv_path = paths.join(base, venv_path)
5158
if is_file(link_to):
52-
if link_to.is_directory:
53-
venv_link = ctx.actions.declare_directory(bin_venv_path)
54-
else:
55-
venv_link = ctx.actions.declare_file(bin_venv_path)
56-
ctx.actions.symlink(output = venv_link, target_file = link_to)
59+
symlink_from = "{}/{}".format(ctx.label.package, bin_venv_path)
60+
runfiles_symlinks[symlink_from] = link_to
61+
5762
else:
5863
venv_link = ctx.actions.declare_symlink(bin_venv_path)
5964
venv_link_rf_path = runfiles_root_path(ctx, venv_link.short_path)
@@ -64,9 +69,12 @@ def create_venv_app_files(ctx, deps, venv_dir_map):
6469
to = link_to,
6570
)
6671
ctx.actions.symlink(output = venv_link, target_path = rel_path)
67-
venv_files.append(venv_link)
72+
venv_files.append(venv_link)
6873

69-
return venv_files
74+
return struct(
75+
venv_files = venv_files,
76+
runfiles_symlinks = runfiles_symlinks,
77+
)
7078

7179
# Visible for testing
7280
def build_link_map(ctx, entries):

0 commit comments

Comments
 (0)