github.phpd.cn/thought-machine/please@v12.2.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 'echo "%s" >> _tmp.txt' % _SH_BINARY_TMPL_PREFIX, 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 'echo "%s" >> _tmp.txt' % _SH_BINARY_TMPL_SUFFIX, 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, size:str=None, 88 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 size (str): Test size (enormous, large, medium or small). 99 visibility (list): Visibility declaration of the rule. 100 flags (str): Flags to apply to the test invocation. 101 timeout (int): Maximum length of time, in seconds, to allow this test to run for. 102 flaky (int | bool): True to mark this as flaky and automatically rerun. 103 test_outputs (list): Extra test output files to generate from this test. 104 container (bool | dict): True to run this test within a container (eg. Docker). 105 sandbox (bool): Sandbox the test on Linux to restrict access to namespaces such as network. 106 """ 107 timeout, labels = _test_size_and_timeout(size, timeout, labels) 108 return build_rule( 109 name=name, 110 srcs=[src or test], 111 data=data, 112 deps=deps, 113 outs=[name + '.sh'], 114 cmd='mv ${SRC} ${OUT}', 115 test_cmd='$TEST %s' % flags, 116 visibility=visibility, 117 labels=labels, 118 binary=True, 119 test=True, 120 no_test_output=True, 121 flaky=flaky, 122 test_outputs=test_outputs, 123 test_timeout=timeout, 124 container=container, 125 test_sandbox=sandbox, 126 ) 127 128 129 def sh_cmd(name:str, cmd:str|dict, srcs:list|dict=None, out:list=None, shell:str='/bin/sh', 130 labels:list&features&tags=None, deps:list=None, visibility:list=None): 131 """Generates a runnable shell script from a command. 132 133 This is doable with a genrule with a little effort but it's awkward enough to be nice 134 to have a builtin. 135 The command is subject to Please's usual variable expansion at build time. Note that if 136 you want `plz run` to transparently work and refer to other files, you may need to use 137 $(out_location ...) instead of $(location ...). 138 139 Args: 140 name (str): Name of the rule. 141 cmd (str | dict): Command to write into the output script file. 142 srcs (list | dict): Source files. Can be consumed by the generated command (but are not 143 written into the output in any other way). 144 out (str): Name of the output file to create. Defaults to name + .sh. 145 shell (str): Shell to invoke in, by default /bin/sh. 146 labels (list): Labels to apply to this rule. 147 deps (list): Any dependencies for this rule. 148 visibility (list): Visibility declaration of the rule. 149 """ 150 if isinstance(cmd, str): 151 cmds = 'cat > $OUT << EOF\n#!%s\n%s\nEOF' % (shell, cmd) 152 else: 153 cmds = {k: 'cat > $OUT << EOF\n#!%s\n%s\nEOF' % (shell, v) for k, v in cmd.items()} 154 return build_rule( 155 name = name, 156 outs = [out or name + '.sh'], 157 srcs = srcs, 158 cmd = cmds, 159 labels = labels, 160 deps = deps, 161 visibility = visibility, 162 binary = True, 163 )