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      )