Skip to content

Commit de0e139

Browse files
scheibelppearce8slabasanrfhaque
authored
Features/build instructions (#697)
* init command * add spack-python script to find 'the one main root' of an experiment * add in part that dumps the build log * add env vars; also take initial build log and try to extract just the build commands (not 100% accurate yet) * style fix * style fix * unnecessary import * Create showBuild.rst * Adding showBuild to index/scripts --------- Co-authored-by: pearce8 <pearce8@llnl.gov> Co-authored-by: Stephanie Brink <brink2@llnl.gov> Co-authored-by: Riyaz Haque <5333387+rfhaque@users.noreply.github.com>
1 parent ea58c13 commit de0e139

File tree

6 files changed

+158
-17
lines changed

6 files changed

+158
-17
lines changed

docs/index.rst

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,6 @@
4343
set-of-experiments
4444
run-binary
4545

46-
.. toctree::
47-
:maxdepth: 1
48-
:caption: Benchpark Utils
49-
50-
diffBuildSpecs
51-
diffExperimentBuilds
52-
diffExperimentSpecs
53-
diffPackageCommits
54-
diffSystemSpecs
55-
scripts
56-
developer-scripts
57-
5846
.. toctree::
5947
:maxdepth: 1
6048
:caption: Contributing
@@ -65,6 +53,17 @@
6553
add-a-dryrun
6654
update-a-system-config
6755

56+
.. toctree::
57+
:maxdepth: 1
58+
:caption: Benchpark Utils
59+
60+
diffBuildSpecs
61+
diffExperimentBuilds
62+
diffExperimentSpecs
63+
diffPackageCommits
64+
diffSystemSpecs
65+
showBuild
66+
6867
.. toctree::
6968
:maxdepth: 2
7069
:caption: API Docs

docs/showBuild.rst

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
.. Copyright 2023 Lawrence Livermore National Security, LLC and other
2+
Benchpark Project Developers. See the top-level COPYRIGHT file for details.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
6+
7+
=============================================
8+
Show how Benchpark/Spack Built the Experiment
9+
=============================================
10+
11+
If you create a Ramble workspace with Benchpark:
12+
13+
```
14+
bin/benchpark experiment init --dest=def-raja-perf raja-perf
15+
bin/benchpark system init --dest=def-ruby llnl-cluster cluster=ruby compiler=gcc
16+
bin/benchpark setup def-raja-perf/ def-ruby/ workspace/
17+
. `pwd`/workspace/setup.sh
18+
ramble --disable-progress-bar --workspace-dir `pwd`/workspace/def-raja-perf/def-ruby/workspace workspace setup
19+
```
20+
21+
You will now be able to `benchpark show-build dump`, a command that will dump a log of how Spack built the experiment:
22+
23+
```
24+
bin/benchpark show-build dump /usr/workspace/scheibel/oslic/benchpark2/workspace/def-raja-perf/def-ruby/workspace/ build-test/
25+
```
26+
27+
for this example, it will add the following artifacts to `build-test/`
28+
29+
1. `build-raja-perf.log`: a full log of all build commands and their output
30+
2. `extracted-commands.txt`: [1] but with most output filtered out (generally much easier to understand what commands to run to do the build)
31+
3. `spack-build-env.txt`: the environment variables set at build time

lib/benchpark/cmd/show_build.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Copyright 2023 Lawrence Livermore National Security, LLC and other
2+
# Benchpark Project Developers. See the top-level COPYRIGHT file for details.
3+
#
4+
# Copyright 2013-2023 Spack Project Developers.
5+
#
6+
# SPDX-License-Identifier: Apache-2.0
7+
8+
import os
9+
import os.path
10+
import re
11+
import shutil
12+
13+
import benchpark.paths
14+
from benchpark.runtime import run_command
15+
16+
17+
def _find_env_root(basedir):
18+
for root, _, fnames in os.walk(basedir):
19+
if "spack.yaml" in fnames:
20+
return root
21+
raise Exception(f"Could not find spack.yaml in {basedir}")
22+
23+
24+
def extract_build_commands(log_file):
25+
extracted = []
26+
with open(log_file, "r", encoding="utf-8") as f:
27+
for line in f.readlines():
28+
match = re.match(r"^==>\s*\[.*\]\s*(\S.*)", line)
29+
if not match:
30+
continue
31+
extract = match.group(1)
32+
if any(x in extract for x in ["cmake", "configure", "make"]):
33+
extracted.append(extract)
34+
return extracted
35+
36+
37+
def show_build_dump(args):
38+
env_root = _find_env_root(args.workspace)
39+
40+
determine_exp = os.path.join(
41+
benchpark.paths.benchpark_root, "lib", "scripts", "determine-exp.py"
42+
)
43+
out, err = run_command(f"spack -e {env_root} python {determine_exp}")
44+
experiment_name = out.strip()
45+
46+
logs_out = os.path.join(args.destdir, f"build-{experiment_name}.log")
47+
if not os.path.exists(logs_out):
48+
with open(logs_out, "w") as f:
49+
run_command(f"spack -e {env_root} logs {experiment_name}", stdout=f)
50+
51+
build_cmds = extract_build_commands(logs_out)
52+
cmds_out = os.path.join(args.destdir, "extracted-commands.txt")
53+
if not os.path.exists(cmds_out):
54+
with open(cmds_out, "w", encoding="utf-8") as f:
55+
for cmd in build_cmds:
56+
f.write(f"{cmd}\n")
57+
58+
# Spack also stores env vars for the build in the install dir, copy them
59+
out, err = run_command(f"spack -e {env_root} location -i {experiment_name}")
60+
install_location = out.strip()
61+
env_vars_path = os.path.join(install_location, ".spack", "spack-build-env.txt")
62+
env_vars_out = os.path.join(args.destdir, os.path.basename(env_vars_path))
63+
if not os.path.exists(env_vars_out):
64+
shutil.copy(env_vars_path, env_vars_out)
65+
66+
67+
def setup_parser(root_parser):
68+
show_build_subparser = root_parser.add_subparsers(dest="show_build_subcommand")
69+
70+
dump_parser = show_build_subparser.add_parser("dump")
71+
dump_parser.add_argument(
72+
"workspace",
73+
help="A Ramble workspace you want to want to generate build instructions for",
74+
)
75+
dump_parser.add_argument("destdir", help="Put all needed resources here")
76+
77+
78+
def command(args):
79+
actions = {
80+
"dump": show_build_dump,
81+
}
82+
if args.show_build_subcommand in actions:
83+
actions[args.show_build_subcommand](args)
84+
else:
85+
raise ValueError(
86+
f"Unknown subcommand for 'show-build': {args.show_build_subcommand}"
87+
)

lib/benchpark/runtime.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,23 @@ def git_clone_commit(url, commit, destination):
3939
run_command(f"git checkout {commit}")
4040

4141

42-
def run_command(command_str, env=None):
42+
def run_command(command_str, env=None, stdout=None, stderr=None):
43+
stdout = stdout or subprocess.PIPE
44+
stderr = stderr or subprocess.PIPE
4345
proc = subprocess.Popen(
4446
shlex.split(command_str),
4547
env=env,
46-
stdout=subprocess.PIPE,
47-
stderr=subprocess.PIPE,
48+
stdout=stdout,
49+
stderr=stderr,
4850
text=True,
4951
)
50-
stdout, stderr = proc.communicate()
52+
out, err = proc.communicate()
5153
if proc.returncode != 0:
5254
raise RuntimeError(
5355
f"Failed command: {command_str}\nOutput: {stdout}\nError: {stderr}"
5456
)
5557

56-
return (stdout, stderr)
58+
return (out, err)
5759

5860

5961
class Command:

lib/main.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import benchpark.cmd.system # noqa: E402
4444
import benchpark.cmd.experiment # noqa: E402
4545
import benchpark.cmd.setup # noqa: E402
46+
import benchpark.cmd.show_build # noqa: E402
4647
import benchpark.cmd.unit_test # noqa: E402
4748
import benchpark.cmd.info # noqa: E402
4849
import benchpark.cmd.list # noqa: E402
@@ -190,6 +191,11 @@ def init_commands(subparsers, actions_dict):
190191
)
191192
benchpark.cmd.info.setup_parser(info_parser)
192193

194+
show_build_parser = subparsers.add_parser(
195+
"show-build", help="Show how spack built a benchmark"
196+
)
197+
benchpark.cmd.show_build.setup_parser(show_build_parser)
198+
193199
list_parser = subparsers.add_parser(
194200
"list", help="List experiments, systems, benchmarks, and modifiers"
195201
)
@@ -206,6 +212,7 @@ def init_commands(subparsers, actions_dict):
206212
actions_dict["unit-test"] = benchpark.cmd.unit_test.command
207213
actions_dict["audit"] = benchpark.cmd.audit.command
208214
actions_dict["info"] = benchpark.cmd.info.command
215+
actions_dict["show-build"] = benchpark.cmd.show_build.command
209216
actions_dict["list"] = benchpark.cmd.list.command
210217
if analyze_installed:
211218
benchpark.cmd.analyze.setup_parser(analyze_parser)

lib/scripts/determine-exp.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import spack.environment as ev
2+
3+
4+
def main():
5+
x = ev.active_environment()
6+
y = list(x.concrete_roots())
7+
# There may be multiple roots in the env. Assume that the experiment of
8+
# interest is the largest dag (every other root should just be an attempt
9+
# to constrain dependencies of this experiment).
10+
z = max(y, key=lambda i: sum(1 for _ in i.traverse()))
11+
print(z.name)
12+
13+
14+
if __name__ == "__main__":
15+
main()

0 commit comments

Comments
 (0)