diff --git a/sbysrc/sby_core.py b/sbysrc/sby_core.py index 2d0d1c2..17b1ae9 100644 --- a/sbysrc/sby_core.py +++ b/sbysrc/sby_core.py @@ -45,12 +45,8 @@ signal.signal(signal.SIGINT, force_shutdown) signal.signal(signal.SIGTERM, force_shutdown) def process_filename(filename): - if filename.startswith("~/"): - filename = os.environ['HOME'] + filename[1:] - filename = os.path.expandvars(filename) - - return filename + return Path(filename).expanduser() def dress_message(workdir, logmessage): tm = localtime() @@ -579,7 +575,7 @@ class SbyConfig: self.error(f"sby file syntax error: '[files]' section entry expects up to 2 arguments, {len(entries)} specified") if len(entries) == 1: - self.files[os.path.basename(entries[0])] = entries[0] + self.files[Path(entries[0]).name] = entries[0] elif len(entries) == 2: self.files[entries[0]] = entries[1] @@ -1033,42 +1029,44 @@ class SbyTask(SbyConfig): raise SbyAbort(logmessage) def makedirs(self, path): - if self.reusedir and os.path.isdir(path): + path = Path(path) + if self.reusedir and path.is_dir(): rmtree(path, ignore_errors=True) - if not os.path.isdir(path): - os.makedirs(path) + path.mkdir(parents=True, exist_ok=True) def copy_src(self, linkmode=False): - self.makedirs(self.workdir + "/src") + outdir = Path(self.workdir) / "src" + self.makedirs(outdir) for dstfile, lines in self.verbatim_files.items(): - dstfile = self.workdir + "/src/" + dstfile - self.log(f"Writing '{dstfile}'.") + dstfile = outdir / dstfile + self.log(f"Writing '{dstfile.absolute()}'.") + dstfile.parent.mkdir(parents=True, exist_ok=True) with open(dstfile, "w") as f: for line in lines: f.write(line) for dstfile, srcfile in self.files.items(): - if dstfile.startswith("/") or dstfile.startswith("../") or ("/../" in dstfile): + dstfile = Path(dstfile) + if dstfile.is_absolute() or ".." in dstfile.parts: self.error(f"destination filename must be a relative path without /../: {dstfile}") - dstfile = self.workdir + "/src/" + dstfile + dstfile = outdir / dstfile srcfile = process_filename(srcfile) - basedir = os.path.dirname(dstfile) - if basedir != "" and not os.path.exists(basedir): - os.makedirs(basedir) + basedir = dstfile.parent + basedir.mkdir(parents=True, exist_ok=True) if linkmode: verb = "Link" else: verb = "Copy" - self.log(f"{verb} '{os.path.abspath(srcfile)}' to '{os.path.abspath(dstfile)}'.") + self.log(f"{verb} '{srcfile.absolute()}' to '{dstfile.absolute()}'.") if linkmode: - os.symlink(os.path.relpath(srcfile, basedir), dstfile) - elif os.path.isdir(srcfile): + os.symlink(srcfile.resolve(), dstfile) + elif srcfile.is_dir(): copytree(srcfile, dstfile, dirs_exist_ok=True) else: copyfile(srcfile, dstfile) @@ -1097,12 +1095,12 @@ class SbyTask(SbyConfig): self.__dict__["opt_" + option_name] = default_value def make_model(self, model_name): - if not os.path.isdir(f"{self.workdir}/model"): - os.makedirs(f"{self.workdir}/model") + modeldir = Path(self.workdir) / "model" + modeldir.mkdir(exist_ok=True) if model_name == "prep": - with open(f"""{self.workdir}/model/design_prep.ys""", "w") as f: - print(f"# running in {self.workdir}/model/", file=f) + with open(modeldir / "design_prep.ys", "w") as f: + print(f"# running in {modeldir}/", file=f) print(f"""read_rtlil design.il""", file=f) if not self.opt_skip_prep: print("scc -select; simplemap; select -clear", file=f) @@ -1146,7 +1144,7 @@ class SbyTask(SbyConfig): return [proc] if model_name == "base": - with open(f"""{self.workdir}/model/design.ys""", "w") as f: + with open(modeldir / "design.ys", "w") as f: print(f"# running in {self.workdir}/src/", file=f) for cmd in self.script: print(cmd, file=f) @@ -1168,7 +1166,7 @@ class SbyTask(SbyConfig): def instance_hierarchy_callback(retcode): if self.design == None: - with open(f"{self.workdir}/model/design.json") as f: + with open(modeldir / "design.json") as f: self.design = design_hierarchy(f) self.status_db.create_task_properties([ prop for prop in self.design.properties_by_path.values() @@ -1184,8 +1182,8 @@ class SbyTask(SbyConfig): return [proc] if re.match(r"^smt2(_syn)?(_nomem)?(_stbv|_stdt)?$", model_name): - with open(f"{self.workdir}/model/design_{model_name}.ys", "w") as f: - print(f"# running in {self.workdir}/model/", file=f) + with open(modeldir / f"design_{model_name}.ys", "w") as f: + print(f"# running in {modeldir}/", file=f) print(f"""read_rtlil design_prep.il""", file=f) print("hierarchy -smtcheck", file=f) print("delete */t:$print", file=f) @@ -1218,8 +1216,8 @@ class SbyTask(SbyConfig): return [proc] if re.match(r"^btor(_syn)?(_nomem)?$", model_name): - with open(f"{self.workdir}/model/design_{model_name}.ys", "w") as f: - print(f"# running in {self.workdir}/model/", file=f) + with open(modeldir / f"design_{model_name}.ys", "w") as f: + print(f"# running in {modeldir}/", file=f) print(f"""read_rtlil design_prep.il""", file=f) print("hierarchy -simcheck", file=f) print("delete */t:$print", file=f) @@ -1254,8 +1252,8 @@ class SbyTask(SbyConfig): return [proc] if model_name == "aig": - with open(f"{self.workdir}/model/design_aiger.ys", "w") as f: - print(f"# running in {self.workdir}/model/", file=f) + with open(modeldir / "design_aiger.ys", "w") as f: + print(f"# running in {modeldir}/", file=f) print("read_rtlil design_prep.il", file=f) print("delete */t:$print", file=f) print("hierarchy -simcheck", file=f) @@ -1281,7 +1279,7 @@ class SbyTask(SbyConfig): self, "aig", self.model("prep"), - f"""cd {self.workdir}/model; {self.exe_paths["yosys"]} -ql design_aiger.log design_aiger.ys""" + f"""cd {modeldir}; {self.exe_paths["yosys"]} -ql design_aiger.log design_aiger.ys""" ) proc.checkretcode = True @@ -1292,8 +1290,8 @@ class SbyTask(SbyConfig): self, model_name, self.model("aig"), - f"""cd {self.workdir}/model; {self.exe_paths["abc"]} -c 'read_aiger design_aiger.aig; fold{" -s" if self.opt_aigfolds else ""}; strash; write_aiger design_aiger_fold.aig'""", - logfile=open(f"{self.workdir}/model/design_aiger_fold.log", "w") + f"""cd {modeldir}; {self.exe_paths["abc"]} -c 'read_aiger design_aiger.aig; fold{" -s" if self.opt_aigfolds else ""}; strash; write_aiger design_aiger_fold.aig'""", + logfile=open(f"{modeldir}/design_aiger_fold.log", "w") ) proc.checkretcode = True diff --git a/tests/links/more_dirs.sby b/tests/links/more_dirs.sby new file mode 100644 index 0000000..9a926dd --- /dev/null +++ b/tests/links/more_dirs.sby @@ -0,0 +1,20 @@ +[tasks] +link +copy + +[options] +mode prep + +[engines] +btor btormc + +[script] +read -noverific +script dir/script.ys + +[files] +here/dir ${WORKDIR}/../dir +a/b/c.v prv32fmcmp.v + +[file here/doc] +log foo diff --git a/tests/links/more_dirs.sh b/tests/links/more_dirs.sh new file mode 100644 index 0000000..aa9ce11 --- /dev/null +++ b/tests/links/more_dirs.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -e +if [[ $TASK == link ]]; then + flags="--setup --link" +else + flags="--setup" +fi +python3 $SBY_MAIN -f $SBY_FILE $TASK $flags + +test -e ${WORKDIR}/src/here/dir -a -e ${WORKDIR}/src/a/b/c.v -a -e ${WORKDIR}/src/here/doc diff --git a/tests/links/symlink.py b/tests/links/symlink.py index a6a06d5..f274d61 100644 --- a/tests/links/symlink.py +++ b/tests/links/symlink.py @@ -1,10 +1,10 @@ -import os from pathlib import Path import sys def main(): workdir, task = sys.argv[1:] src = Path(workdir) / "src" + count = 0 for srcfile in src.iterdir(): if srcfile.name == "heredoc": assert(not srcfile.is_symlink()) @@ -13,6 +13,11 @@ def main(): assert(local_contents.strip() == 'log foo') else: assert(srcfile.is_symlink() == (task == "link")) + assert(srcfile.name != "script.ys") + count += 1 + assert(count == 4) + script_ys = src / "dir" / "script.ys" + assert(script_ys.exists()) if __name__ == "__main__": main() diff --git a/tests/links/symlink.sby b/tests/links/symlink.sby index 52fa881..c3841ce 100644 --- a/tests/links/symlink.sby +++ b/tests/links/symlink.sby @@ -1,6 +1,8 @@ [tasks] link copy +dir_implicit: dir +dir_explicit: dir [options] mode prep @@ -15,7 +17,9 @@ script dir/script.ys [files] ../../docs/examples/demos/picorv32.v prv32fmcmp.v -dir +~dir: dir +dir_implicit: dir/ +dir_explicit: dir/ dir/ [file heredoc] log foo