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:
```py
# 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.
Currently,
crux-mir
'stranslate_libs.sh
script is written by hand. This makes it tedious to maintain, especially when newrustc
toolchains alter the dependencies used in the Rust standard libraries. We should include a program that generates thetranslate_libs.sh
script in a more declarative way. @m10f started work on this with this program: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 likecargo 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 updatingcrux-mir/lib
to a newrustc
toolchain.