@@ -30,12 +30,14 @@ load(
3030 "PrecompileAttr" ,
3131 "PycCollectionAttr" ,
3232 "REQUIRED_EXEC_GROUP_BUILDERS" ,
33+ "WINDOWS_CONSTRAINTS_ATTRS" ,
3334 "apply_config_settings_attr" ,
3435)
3536load (":builders.bzl" , "builders" )
3637load (":cc_helper.bzl" , "cc_helper" )
3738load (
3839 ":common.bzl" ,
40+ "ExplicitSymlink" ,
3941 "collect_cc_info" ,
4042 "collect_deps" ,
4143 "collect_imports" ,
@@ -49,10 +51,10 @@ load(
4951 "csv" ,
5052 "filter_to_py_srcs" ,
5153 "is_bool" ,
54+ "is_windows_platform" ,
5255 "maybe_create_repo_mapping" ,
5356 "relative_path" ,
5457 "runfiles_root_path" ,
55- "target_platform_has_any_constraint" ,
5658)
5759load (":common_labels.bzl" , "labels" )
5860load (":flags.bzl" , "BootstrapImplFlag" , "VenvsUseDeclareSymlinkFlag" , "read_possibly_native_flag" )
@@ -73,37 +75,14 @@ _EXTERNAL_PATH_PREFIX = "external"
7375_ZIP_RUNFILES_DIRECTORY_NAME = "runfiles"
7476_INIT_PY = "__init__.py"
7577
76- # buildifier: disable=name-conventions
77- ExplicitSymlink = provider (
78- doc = """
79- A runfile that should be created as a symlink pointing to a specific location.
80-
81- This is only needed on Windows, where Bazel doesn't preserve declare_symlink
82- with relative paths. This is basically manually captures what using
83- declare_symlink(), symlink() and runfiles like so would capture:
84-
85- ```
86- link = declare_symlink(...)
87- link_to_path = relative_path(from=link, to=target)
88- symlink(output=link, target_path=link_to_path)
89- runfiles.add([link, target])
90- ```
91- """ ,
92- fields = {
93- "files" : "depset[File] of files that should be included if this symlink is used" ,
94- "link_to_path" : "Path the symlink should point to" ,
95- "runfiles_path" : "runfiles-root-relative path for the symlink" ,
96- "venv_path" : "venv-root-relative path for the symlink" ,
97- },
98- )
99-
10078# Non-Google-specific attributes for executables
10179# These attributes are for rules that accept Python sources.
10280EXECUTABLE_ATTRS = dicts .add (
10381 COMMON_ATTRS ,
10482 AGNOSTIC_EXECUTABLE_ATTRS ,
10583 PY_SRCS_ATTRS ,
10684 IMPORTS_ATTRS ,
85+ WINDOWS_CONSTRAINTS_ATTRS ,
10786 # starlark flags attributes
10887 {
10988 "_build_python_zip_flag" : attr .label (default = "//python/config_settings:build_python_zip" ),
@@ -257,11 +236,6 @@ accepting arbitrary Python versions.
257236 default = labels .VENVS_USE_DECLARE_SYMLINK ,
258237 providers = [BuildSettingInfo ],
259238 ),
260- "_windows_constraints" : lambda : attrb .LabelList (
261- default = [
262- "@platforms//os:windows" ,
263- ],
264- ),
265239 "_zipper" : lambda : attrb .Label (
266240 cfg = "exec" ,
267241 executable = True ,
@@ -323,7 +297,7 @@ def _create_executable(
323297 extra_deps ):
324298 _ = is_test , cc_details , native_deps_details # @unused
325299
326- is_windows = target_platform_has_any_constraint (ctx , ctx . attr . _windows_constraints )
300+ is_windows = is_windows_platform (ctx )
327301
328302 if is_windows :
329303 if not executable .extension == "exe" :
@@ -447,14 +421,14 @@ WARNING: Target: {}
447421 use_zip_file = build_zip_enabled ,
448422 python_binary_path = runtime_details .executable_interpreter_path ,
449423 )
450- if not build_zip_enabled :
451- # On Windows, the main executable has an "exe" extension, so
452- # here we re-use the un-extensioned name for the bootstrap output.
453- bootstrap_output = ctx .actions .declare_file (base_executable_name )
454424
455- # The launcher looks for the non-zip executable next to
456- # itself, so add it to the default outputs.
457- extra_default_outputs .append (bootstrap_output )
425+ # On Windows, the main executable has an "exe" extension, so
426+ # here we re-use the un-extensioned name for the bootstrap output.
427+ bootstrap_output = ctx .actions .declare_file (base_executable_name )
428+
429+ # The launcher looks for the non-zip executable next to
430+ # itself, so add it to the default outputs.
431+ extra_default_outputs .append (bootstrap_output )
458432
459433 if should_create_executable_zip :
460434 if bootstrap_output != None :
@@ -516,6 +490,9 @@ WARNING: Target: {}
516490 # runfiles; runfiles for the app itself (e.g its deps, but no Python
517491 # runtime files)
518492 app_runfiles = app_runfiles .build (ctx ),
493+ # depset[ExplicitSymlink]None; symlinks that should be created in
494+ # the venv to augment app_runfiles
495+ venv_app_symlinks = venv .lib_symlinks if venv else None ,
519496 # File|None; the venv `bin/python3` file, if any.
520497 venv_python_exe = venv .interpreter if venv else None ,
521498 # runfiles|None; runfiles in the venv for the interpreter
@@ -561,7 +538,7 @@ def _create_venv(ctx, output_prefix, imports, runtime_details, add_runfiles_root
561538 else :
562539 interpreter_actual_path = runtime .interpreter_path
563540
564- is_windows = target_platform_has_any_constraint (ctx , ctx . attr . _windows_constraints )
541+ is_windows = is_windows_platform (ctx )
565542 if is_windows :
566543 venv_details = _create_venv_windows (
567544 ctx ,
@@ -644,6 +621,7 @@ def _create_venv(ctx, output_prefix, imports, runtime_details, add_runfiles_root
644621 lib_runfiles = ctx .runfiles (
645622 root_symlinks = venv_app_files .runfiles_symlinks ,
646623 ),
624+ lib_symlinks = venv_app_files .explicit_symlinks ,
647625 )
648626
649627def _create_venv_unixy (ctx , * , venv_ctx_rel_root , runtime , interpreter_actual_path ):
@@ -937,9 +915,12 @@ def _create_stage1_bootstrap(
937915 }
938916 computed_subs = ctx .actions .template_dict ()
939917 if venv :
918+ runtime_venv_symlinks = depset (
919+ transitive = [venv .interpreter_symlinks , venv .lib_symlinks ],
920+ )
940921 computed_subs .add_joined (
941922 "%runtime_venv_symlinks%" ,
942- venv . interpreter_symlinks ,
923+ runtime_venv_symlinks ,
943924 join_with = "\n " ,
944925 map_each = _map_runtime_venv_symlink ,
945926 )
@@ -1250,8 +1231,6 @@ def py_executable_base_impl(ctx, *, semantics, is_test, inherited_environment =
12501231 )
12511232 ))
12521233
1253- app_runfiles = exec_result .app_runfiles
1254-
12551234 providers = []
12561235
12571236 _add_provider_default_info (
@@ -1265,13 +1244,14 @@ def py_executable_base_impl(ctx, *, semantics, is_test, inherited_environment =
12651244 _add_provider_run_environment_info (providers , ctx , inherited_environment )
12661245 _add_provider_py_executable_info (
12671246 providers ,
1268- app_runfiles = app_runfiles ,
1247+ app_runfiles = exec_result . app_runfiles ,
12691248 build_data_file = runfiles_details .build_data_file ,
12701249 interpreter_args = ctx .attr .interpreter_args ,
12711250 interpreter_path = runtime_details .executable_interpreter_path ,
12721251 main_py = main_py ,
12731252 runfiles_without_exe = runfiles_details .runfiles_without_exe ,
12741253 stage2_bootstrap = exec_result .stage2_bootstrap ,
1254+ venv_app_symlinks = exec_result .venv_app_symlinks ,
12751255 venv_interpreter_runfiles = exec_result .venv_interpreter_runfiles ,
12761256 venv_interpreter_symlinks = exec_result .venv_interpreter_symlinks ,
12771257 venv_python_exe = exec_result .venv_python_exe ,
@@ -1313,7 +1293,7 @@ def _validate_executable(ctx):
13131293 ).format (ctx .attr .main , ctx .attr .main_module ))
13141294
13151295def _declare_executable_file (ctx ):
1316- if target_platform_has_any_constraint (ctx , ctx . attr . _windows_constraints ):
1296+ if is_windows_platform (ctx ):
13171297 executable = ctx .actions .declare_file (ctx .label .name + ".exe" )
13181298 else :
13191299 executable = ctx .actions .declare_file (ctx .label .name )
@@ -1882,6 +1862,7 @@ def _add_provider_py_executable_info(
18821862 main_py ,
18831863 runfiles_without_exe ,
18841864 stage2_bootstrap ,
1865+ venv_app_symlinks ,
18851866 venv_interpreter_runfiles ,
18861867 venv_interpreter_symlinks ,
18871868 venv_python_exe ):
@@ -1896,6 +1877,8 @@ def _add_provider_py_executable_info(
18961877 main_py: File; the main .py entry point.
18971878 runfiles_without_exe: runfiles; the default runfiles, but without the executable.
18981879 stage2_bootstrap: File; the stage 2 bootstrap script.
1880+ venv_app_symlinks: depset[ExplicitSymlink]; symlinks to create for the
1881+ venv that are the application (deps, etc).
18991882 venv_interpreter_runfiles: runfiles; runfiles specific to the interpreter for the venv.
19001883 venv_interpreter_symlinks: depset[ExplicitSymlink]; interpreter-specific symlinks to create for the venv.
19011884 venv_python_exe: File; the python executable in the venv.
@@ -1908,6 +1891,7 @@ def _add_provider_py_executable_info(
19081891 main = main_py ,
19091892 runfiles_without_exe = runfiles_without_exe ,
19101893 stage2_bootstrap = stage2_bootstrap ,
1894+ venv_app_symlinks = venv_app_symlinks ,
19111895 venv_interpreter_runfiles = venv_interpreter_runfiles ,
19121896 venv_interpreter_symlinks = venv_interpreter_symlinks ,
19131897 venv_python_exe = venv_python_exe ,
0 commit comments