github.com/sercand/please@v13.4.0+incompatible/src/parse/rules/sh_rules.build_defs (about) 1 """ Rules to 'build' shell scripts. 2 3 Note that these do pretty much nothing beyond collecting the files. In future we might 4 implement something more advanced (ala .sar files or whatever). 5 """ 6 7 _SH_BINARY_TMPL_PREFIX = """ 8 unzip -qo $0 -d $(dirname $0) 9 """.replace('$', '\\\$').replace('"', '\\"') 10 11 _SH_BINARY_TMPL_SUFFIX = """ 12 exit 0\n\ 13 """ 14 15 16 def sh_library(name:str, src:str, deps:list=None, visibility:list=None, labels:list&features&tags=None): 17 """Generates a shell script binary, essentially just the given source. 18 19 Note that these are individually executable so can only have one source file each. 20 This is a bit tedious and would be nice to improve sometime. 21 22 Args: 23 name (str): Name of the rule. 24 src (str): Source file for the rule. 25 deps (list): Dependencies of this rule. 26 visibility (list): Visibility declaration of the rule. 27 labels (list): List of labels. 28 """ 29 return filegroup( 30 name=name, 31 srcs=[src], 32 deps=deps, 33 visibility=visibility, 34 binary=True, 35 labels=labels, 36 ) 37 38 39 def sh_binary(name:str, main:str, deps:list=None, visibility:list=None, labels:list&features&tags=None): 40 """Generates a shell script binary. 41 42 It assumes that unzip is in your path. 43 44 The resulting script will contain three things: 45 1) Code necessary to unzip dependent files. 46 2) The user defined shell script. 47 3) The zipfile containing all dependent files. 48 49 Args: 50 name (str): Name of the rule 51 main (str): The script to execute after all files have been uncompressed 52 deps (list): Dependencies of this rule 53 visibility (list): Visibility declaration of the rule. 54 labels (list): List of labels. 55 """ 56 # No need to go through zip/unzip and injecting code if there are no dependencies 57 if deps: 58 cmds = ' && '.join([ 59 # Use the same shebang as the original script 60 'head -1 $SRCS > _tmp.txt', 61 # Inject bash code to untar the compressed files. 62 f'echo "{_SH_BINARY_TMPL_PREFIX}" >> _tmp.txt', 63 # Inject the user defined script. 64 'cat $SRCS >> _tmp.txt', 65 # Inject a final exit so it doesn't try to execute the zipfile contents. 66 f'echo "{_SH_BINARY_TMPL_SUFFIX}" >> _tmp.txt', 67 # Compress the dependent files and dump out into the bash script. 68 'find . -type f | grep -v $SRCS | sort | grep -v "_tmp.txt" | $TOOL z -d -i - -o $OUT --preamble_file _tmp.txt --strip_prefix ./', 69 ]) 70 else: 71 cmds = 'cp $SRCS $OUT' 72 73 return build_rule( 74 name = name, 75 srcs = [main], 76 outs = ['%s.sh' % name], 77 tools = [CONFIG.JARCAT_TOOL], 78 cmd = cmds, 79 deps = deps, 80 binary = True, 81 needs_transitive_deps = True, 82 labels = labels, 83 visibility = visibility, 84 ) 85 86 87 def sh_test(name:str, src:str=None, labels:list&features&tags=None, data:list=None, deps:list=None, worker:str='', 88 size:str=None, visibility:list=None, flags:str='', flaky:bool|int=0, test_outputs:list=None, timeout:int=0, 89 container:bool|dict=False, sandbox:bool=None): 90 """Generates a shell test. Note that these aren't packaged in a useful way. 91 92 Args: 93 name (str): Name of the rule 94 src (str): Test script file. 95 labels (list): Labels to apply to this test. 96 data (list): Runtime data for the test. 97 deps (list): Dependencies of this rule 98 worker (str): Reference to worker script, A persistent worker process that is used to set up the test. 99 size (str): Test size (enormous, large, medium or small). 100 visibility (list): Visibility declaration of the rule. 101 flags (str): Flags to apply to the test invocation. 102 timeout (int): Maximum length of time, in seconds, to allow this test to run for. 103 flaky (int | bool): True to mark this as flaky and automatically rerun. 104 test_outputs (list): Extra test output files to generate from this test. 105 container (bool | dict): True to run this test within a container (eg. Docker). 106 sandbox (bool): Sandbox the test on Linux to restrict access to namespaces such as network. 107 """ 108 timeout, labels = _test_size_and_timeout(size, timeout, labels) 109 110 test_cmd = '$TEST %s' % flags 111 if worker: 112 test_cmd = f'$(worker {worker}) && {test_cmd} ' 113 deps += [worker] 114 115 return build_rule( 116 name=name, 117 srcs=[src or test], 118 data=data, 119 deps=deps, 120 outs=[name + '.sh'], 121 cmd='mv ${SRC} ${OUT}', 122 test_cmd=test_cmd, 123 visibility=visibility, 124 labels=labels, 125 binary=True, 126 test=True, 127 no_test_output=True, 128 flaky=flaky, 129 test_outputs=test_outputs, 130 test_timeout=timeout, 131 container=container, 132 test_sandbox=sandbox, 133 ) 134 135 136 def sh_cmd(name:str, cmd:str|dict, srcs:list|dict=None, out:list=None, shell:str='/bin/sh', 137 labels:list&features&tags=None, deps:list=None, visibility:list=None, 138 test_only:bool=False): 139 """Generates a runnable shell script from a command. 140 141 This is doable with a genrule with a little effort but it's awkward enough to be nice 142 to have a builtin. 143 The command is subject to Please's usual variable expansion at build time. Note that if 144 you want `plz run` to transparently work and refer to other files, you may need to use 145 $(out_location ...) instead of $(location ...). 146 147 Args: 148 name (str): Name of the rule. 149 cmd (str | dict): Command to write into the output script file. 150 srcs (list | dict): Source files. Can be consumed by the generated command (but are not 151 written into the output in any other way). 152 out (str): Name of the output file to create. Defaults to name + .sh. 153 shell (str): Shell to invoke in, by default /bin/sh. 154 labels (list): Labels to apply to this rule. 155 deps (list): Any dependencies for this rule. 156 visibility (list): Visibility declaration of the rule. 157 test_only (bool): If True, this rule can only be depended on by tests. 158 """ 159 if isinstance(cmd, str): 160 cmds = f'cat > $OUT << EOF\n#!{shell}\n{cmd}\nEOF' 161 else: 162 cmds = {k: f'cat > $OUT << EOF\n#!{shell}\n{v}\nEOF' for k, v in cmd.items()} 163 return build_rule( 164 name = name, 165 outs = [out or name + '.sh'], 166 srcs = srcs, 167 cmd = cmds, 168 labels = labels, 169 deps = deps, 170 visibility = visibility, 171 binary = True, 172 test_only = test_only, 173 )