1# Copyright 2023 The Bazel Authors. All rights reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15""" 16A private rule to generate an entry_point python file to be used in a py_binary. 17 18Right now it only supports console_scripts via the entry_points.txt file in the dist-info. 19 20NOTE @aignas 2023-08-07: This cannot be in pure starlark, because we need to 21read a file and then create a `.py` file based on the contents of that file, 22which cannot be done in pure starlark according to 23https://github.com/bazelbuild/bazel/issues/14744 24""" 25 26_ENTRY_POINTS_TXT = "entry_points.txt" 27 28def _get_entry_points_txt(entry_points_txt): 29 """Get the entry_points.txt file 30 31 TODO: use map_each to avoid flattening of the directories outside the execution phase. 32 """ 33 for file in entry_points_txt.files.to_list(): 34 if file.basename == _ENTRY_POINTS_TXT: 35 return file 36 37 fail("{} does not contain {}".format(entry_points_txt, _ENTRY_POINTS_TXT)) 38 39def _py_console_script_gen_impl(ctx): 40 entry_points_txt = _get_entry_points_txt(ctx.attr.entry_points_txt) 41 42 args = ctx.actions.args() 43 args.add("--console-script", ctx.attr.console_script) 44 args.add("--console-script-guess", ctx.attr.console_script_guess) 45 args.add(entry_points_txt) 46 args.add(ctx.outputs.out) 47 48 ctx.actions.run( 49 inputs = [ 50 entry_points_txt, 51 ], 52 outputs = [ctx.outputs.out], 53 arguments = [args], 54 mnemonic = "PyConsoleScriptBinaryGen", 55 progress_message = "Generating py_console_script_binary main: %{label}", 56 executable = ctx.executable._tool, 57 ) 58 59 return [DefaultInfo( 60 files = depset([ctx.outputs.out]), 61 )] 62 63py_console_script_gen = rule( 64 _py_console_script_gen_impl, 65 attrs = { 66 "console_script": attr.string( 67 doc = "The name of the console_script to create the .py file for. Optional if there is only a single entry-point available.", 68 default = "", 69 mandatory = False, 70 ), 71 "console_script_guess": attr.string( 72 doc = "The string used for guessing the console_script if it is not provided.", 73 default = "", 74 mandatory = False, 75 ), 76 "entry_points_txt": attr.label( 77 doc = "The filegroup to search for entry_points.txt.", 78 mandatory = True, 79 ), 80 "out": attr.output( 81 doc = "Output file location.", 82 mandatory = True, 83 ), 84 "_tool": attr.label( 85 default = ":py_console_script_gen_py", 86 executable = True, 87 cfg = "exec", 88 ), 89 }, 90 doc = """\ 91Builds an entry_point script from an entry_points.txt file. 92""", 93) 94