ahc_evaluation/
build.rs

1use std::process::Command;
2
3use anyhow::{ensure, Context};
4
5use crate::config::Config;
6
7/// Builds the submission code.
8pub fn build_submission(config: &Config) -> anyhow::Result<()> {
9    let cmd_args = &config.command.build.submission;
10
11    // Skips build if build command for submission code is empty.
12    let Some(program) = cmd_args.first() else {
13        return Ok(());
14    };
15
16    let process_handle = Command::new(program)
17        .args(&cmd_args[1..])
18        .spawn()
19        .with_context(|| {
20            format!(
21                "
22Failed to start the child process that builds the submission code.
23List of arguments: {:?}
24",
25                cmd_args
26            )
27        })?;
28
29    let output = process_handle
30        .wait_with_output()
31        .with_context(|| "Failed to building the submission code.")?;
32
33    ensure!(
34        output.status.success(),
35        BuildCommandError {
36            cmd_args: config.command.build.submission.clone(),
37            output
38        }
39    );
40
41    Ok(())
42}
43
44/// Builds the local tester.
45pub fn build_tester(config: &Config) -> anyhow::Result<()> {
46    let cmd_args = &config.command.build.tester;
47
48    // Skips build if build command for local tester is empty.
49    let Some(program) = cmd_args.first() else {
50        return Ok(());
51    };
52
53    let process_handle = Command::new(program)
54        .args(&cmd_args[1..])
55        .spawn()
56        .with_context(|| {
57            format!(
58                "
59Failed to start the child process that builds the local tester.
60List of arguments: {:?}
61",
62                cmd_args
63            )
64        })?;
65
66    let output = process_handle
67        .wait_with_output()
68        .with_context(|| "Failed to build the local tester.")?;
69
70    ensure!(
71        output.status.success(),
72        BuildCommandError {
73            cmd_args: config.command.build.tester.clone(),
74            output
75        }
76    );
77
78    Ok(())
79}
80
81#[derive(Debug)]
82pub struct BuildCommandError {
83    pub cmd_args: Vec<String>,
84    pub output: std::process::Output,
85}
86
87impl std::fmt::Display for BuildCommandError {
88    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89        let stdout = String::from_utf8(self.output.stdout.clone()).unwrap();
90        let stderr = String::from_utf8(self.output.stderr.clone()).unwrap();
91
92        write!(
93            f,
94            "
95Failed to execute command.
96
97Exit code: {}
98
99Command line arguments: {:?},
100
101------------------------------- Standard Output --------------------------------
102{}
103--------------------------------------------------------------------------------
104
105---------------------------- Standard Error Output -----------------------------
106{}
107--------------------------------------------------------------------------------
108",
109            self.output.status, self.cmd_args, stdout, stderr,
110        )
111    }
112}
113
114impl std::error::Error for BuildCommandError {}