33load ("@bazel_skylib//lib:paths.bzl" , "paths" )
44load ("@bazel_skylib//rules:common_settings.bzl" , "BuildSettingInfo" )
55load ("@bazel_tools//tools/cpp:toolchain_utils.bzl" , "find_cpp_toolchain" , "use_cpp_toolchain" )
6+ load ("@rules_python//python:py_info.bzl" , "PyInfo" )
67load ("//mojo:providers.bzl" , "MojoInfo" )
78load (":utils.bzl" , "MOJO_EXTENSIONS" , "collect_mojoinfo" )
89
@@ -16,7 +17,7 @@ _ATTRS = {
1617 ),
1718 "copts" : attr .string_list (),
1819 "deps" : attr .label_list (
19- providers = [[CcInfo ], [MojoInfo ]],
20+ providers = [[CcInfo ], [MojoInfo ], [ PyInfo ] ],
2021 ),
2122 "data" : attr .label_list (allow_files = True ),
2223 "enable_assertions" : attr .bool (default = True ),
@@ -28,6 +29,7 @@ _ATTRS = {
2829
2930_TOOLCHAINS = use_cpp_toolchain () + [
3031 "//:toolchain_type" ,
32+ "@bazel_tools//tools/python:toolchain_type" ,
3133]
3234
3335def _find_main (name , srcs , main ):
@@ -56,8 +58,9 @@ def _find_main(name, srcs, main):
5658 fail ("Multiple Mojo files provided, but no main file specified. Please set 'main = \" foo.mojo\" ' to disambiguate." )
5759
5860def _mojo_binary_test_implementation (ctx ):
59- mojo_toolchain = ctx .toolchains ["//:toolchain_type" ].mojo_toolchain_info
6061 cc_toolchain = find_cpp_toolchain (ctx )
62+ mojo_toolchain = ctx .toolchains ["//:toolchain_type" ].mojo_toolchain_info
63+ py_toolchain = ctx .toolchains ["@bazel_tools//tools/python:toolchain_type" ]
6164
6265 object_file = ctx .actions .declare_file (ctx .label .name + ".lo" )
6366 args = ctx .actions .args ()
@@ -138,20 +141,53 @@ def _mojo_binary_test_implementation(ctx):
138141
139142 data = ctx .attr .data
140143 runfiles = ctx .runfiles (ctx .files .data )
141- transitive_runfiles = []
144+ transitive_runfiles = [
145+ ctx .runfiles (transitive_files = py_toolchain .py3_runtime .files ),
146+ ]
142147 for target in data :
143148 transitive_runfiles .append (target [DefaultInfo ].default_runfiles )
144149
145150 # Collect transitive shared libraries that must exist at runtime
151+ python_imports = []
146152 for target in ctx .attr .deps + mojo_toolchain .implicit_deps :
153+ transitive_runfiles .append (target [DefaultInfo ].default_runfiles )
154+
155+ if PyInfo in target :
156+ python_imports .append (target [PyInfo ].imports )
157+ transitive_runfiles .append (
158+ ctx .runfiles (transitive_files = target [PyInfo ].transitive_sources ),
159+ )
160+
147161 if CcInfo not in target :
148162 continue
149163 for linker_input in target [CcInfo ].linking_context .linker_inputs .to_list ():
150164 for library in linker_input .libraries :
151165 if library .dynamic_library and not library .pic_static_library and not library .static_library :
152166 transitive_runfiles .append (ctx .runfiles (transitive_files = depset ([library .dynamic_library ])))
153167
154- runtime_env = dict (ctx .attr .env )
168+ python_path = ""
169+ for path in depset (transitive = python_imports ).to_list ():
170+ python_path += "../" + path + ":"
171+
172+ # https://github.com/bazelbuild/rules_python/issues/2262
173+ libpython = None
174+ for file in py_toolchain .py3_runtime .files .to_list ():
175+ if file .basename .startswith ("libpython" ):
176+ libpython = file .short_path
177+ break # if there are multiple any of them should work and they are likely symlinks to each other
178+
179+ if not libpython :
180+ fail ("failed to find libpython, please report this at https://github.com/modular/rules_mojo/issues" )
181+
182+ runtime_env = dict (ctx .attr .env ) | {
183+ "MODULAR_PYTHON_EXECUTABLE" : py_toolchain .py3_runtime .interpreter .short_path ,
184+ "MOJO_PYTHON" : py_toolchain .py3_runtime .interpreter .short_path ,
185+ "MOJO_PYTHON_LIBRARY" : libpython ,
186+ "PYTHONEXECUTABLE" : py_toolchain .py3_runtime .interpreter .short_path ,
187+ "PYTHONNOUSERSITE" : "affirmative" ,
188+ "PYTHONPATH" : python_path ,
189+ "PYTHONSAFEPATH" : "affirmative" ,
190+ }
155191 for key , value in runtime_env .items ():
156192 runtime_env [key ] = ctx .expand_make_variables (
157193 "env" ,
0 commit comments