Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crux-mir: Automate generation of translate_libs.sh script #1152

Open
RyanGlScott opened this issue Dec 7, 2023 · 0 comments
Open

crux-mir: Automate generation of translate_libs.sh script #1152

RyanGlScott opened this issue Dec 7, 2023 · 0 comments
Labels
crux MIR Issues relating to Rust/MIR support technical debt

Comments

@RyanGlScott
Copy link
Contributor

RyanGlScott commented Dec 7, 2023

Currently, crux-mir's translate_libs.sh script is written by hand. This makes it tedious to maintain, especially when new rustc toolchains alter the dependencies used in the Rust standard libraries. We should include a program that generates the translate_libs.sh script in a more declarative way. @m10f started work on this with this program:

# gen_build_sh.py
import sys
import shlex
import os
import shutil
from typing import Iterator

def crate_loc(path: str):
  (parent, _) = os.path.split(path)
  (parent2, parent_name) = os.path.split(parent)
  if parent_name == "src":
    return parent2

  return parent


def has_arg(args: list[str], n: str) -> bool:
  return n in args

def get_args(args: list[str], n: str) -> Iterator[str]:
  for arg_idx in range(0, len(args)):
    arg = args[arg_idx]
    if arg == n and arg_idx + 1 < len(args):
      yield args[arg_idx + 1]

def get_arg(args: list[str], n: str) -> str:
  for x in get_args(args, n):
    return x

  raise RuntimeError(f"Missing required arg: {n} args: {args}")

def parse(inp):
  for line in inp:
    line = str(line)
    if "--target" not in line:
      continue

    line = line.removeprefix("Running ").strip(" ").strip("`")
    args = shlex.split(line)

    crate_name = get_arg(args, "--crate-name")
    edition = None
    if has_arg(args, "--edition=2021"):
      edition = 2021
    if has_arg(args, "--edition=2018"):
      edition = 2018
    if has_arg(args, "--edition=2015"):
      edition = 2015

    cfgs = get_args(args, "--cfg")
    externs = [ x.split("=")[0] for x in get_args(args, "--extern") ]

    # this is kinda brittle but it's not really tagged
    lib_path = next(a for a in args if a.endswith(".rs"))
    crate_path = crate_loc(lib_path)

    yield {
      "edition": edition,
      "crate_name": crate_name,
      "cfgs": cfgs,
      "externs": externs,
      "crate_path": crate_path,
      "lib_path": lib_path,
    }

def copy(crate, srcpath):
  crate_path = crate["crate_path"]
  shutil.copytree(crate_path, os.path.join(srcpath, crate["crate_name"]))

def build_cmd(crate, libdir, srcpath):
  cfg_args = [f"--cfg {shlex.quote(c)}" for c in crate["cfgs"]]
  edition = crate["edition"]
  externs = crate["externs"]
  crate_name = crate["crate_name"]
  crate_path = crate["crate_path"]
  lib_path = crate["lib_path"]
  lib_rel_path = os.path.relpath(lib_path, crate_path)
  target_path = os.path.join(srcpath, crate_name, lib_rel_path)


  extern_args = [f"--extern {e}={os.path.join(libdir, 'lib' + e + '.rlib') }" for e in externs]
  cmd = [
    "mir-json",
    target_path,
    f"--edition={edition}" if edition is not None else "",
    f"--crate-name {crate_name}",
    f"-L {libdir}",
    f"--out-dir {libdir}",
    f"--crate-type rlib",
  ] + cfg_args + extern_args
  return " ".join(cmd)

crates = parse(sys.stdin)
if sys.argv[1] == "copy":
  for crate in crates:
    copy(crate, "lib")

elif sys.argv[1] == "buildscript":
  print("set -e")
  for crate in crates:
    print(f"echo 'Building {crate['crate_name']}...'")
    print(build_cmd(crate, "rlibs", "lib"))
    print()

Where it is intended to be used with gen_build_sh.py buildscript < log_from_building_an_empty_project, where "log_from_building_an_empty_project" is the result of running something like cargo build -Z build-std --verbose.

The script also includes a copy mode that can be used to copy the source code for the Rust standard libraries into a central location. This could be used to automate the process of updating crux-mir/lib to a new rustc toolchain.

@RyanGlScott RyanGlScott added crux technical debt MIR Issues relating to Rust/MIR support labels Dec 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crux MIR Issues relating to Rust/MIR support technical debt
Projects
None yet
Development

No branches or pull requests

1 participant