/ prelude / utils / cmd_script.bzl
cmd_script.bzl
 1  # prelude/utils/cmd_script.bzl
 2  #
 3  # Wrap cmd_args as an executable script.
 4  #
 5  # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 6  # PRELUDE ARCHAEOLOGY
 7  # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 8  #
 9  # This wraps a cmd_args into a callable script, useful when you need to pass
10  # an executable + args as a single argument to another tool.
11  #
12  # Example (Rust linker wrapper):
13  #     linker_cmd = cmd_args(linker, linker_flags)
14  #     wrapper = cmd_script(ctx, "linker", linker_cmd)
15  #     rustc_args.add("-Clinker={}".format(wrapper))
16  #
17  # We only support Unix (sh) since we don't target Windows.
18  #
19  # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
20  
21  def cmd_script(
22          ctx: AnalysisContext,
23          name: str,
24          cmd: cmd_args,
25          quote: str | None = "shell") -> cmd_args:
26      """
27      Wrap cmd_args in a shell script.
28      
29      Args:
30          ctx: analysis context
31          name: script name (without .sh extension)
32          cmd: command to wrap
33          quote: quoting style ("shell" or None)
34      
35      Returns:
36          cmd_args pointing to script with original cmd as hidden dep
37      """
38      cmd_kwargs = {} if quote == None else {"quote": quote}
39      shell_quoted = cmd_args(cmd, **cmd_kwargs)
40  
41      wrapper, _ = ctx.actions.write(
42          ctx.actions.declare_output("{}.sh".format(name)),
43          [
44              "#!/usr/bin/env bash",
45              cmd_args(cmd_args(shell_quoted, delimiter = " \\\n"), format = "{} \"$@\"\n"),
46          ],
47          is_executable = True,
48          allow_args = True,
49      )
50  
51      return cmd_args(wrapper, hidden = cmd)