cargo_fel4/
new_cmd.rs

1use std::fs;
2use std::fs::{File, OpenOptions};
3use std::io::prelude::*;
4use std::path::Path;
5use std::process::Command;
6
7use super::Error;
8use command_ext::CommandExt;
9use config::NewCmd;
10use fel4_config::get_exemplar_default_toml;
11
12/// Create a new feL4 project.
13///
14/// Generates all of the scaffolding files for a new
15/// feL4 project.
16pub fn handle_new_cmd(subcmd: &NewCmd) -> Result<(), Error> {
17    generate_baseline_cargo_package(subcmd)?;
18
19    generate_fel4_project_files(subcmd)?;
20
21    generate_tests_source_files(Some(&subcmd.path))?;
22
23    generate_target_specs(subcmd)?;
24
25    Ok(())
26}
27
28fn generate_baseline_cargo_package(subcmd: &NewCmd) -> Result<(), Error> {
29    let mut cmd = Command::new("cargo");
30    cmd.arg("new").add_loudness_args(&subcmd.loudness);
31
32    if let Some(ref n) = subcmd.name {
33        cmd.arg("--name").arg(&n);
34    }
35
36    // Set the edition to 2015
37    cmd.arg("--edition").arg("2015");
38
39    cmd.arg("--lib").arg(&subcmd.path).run_cmd()
40}
41
42fn generate_fel4_project_files(subcmd: &NewCmd) -> Result<(), Error> {
43    // Create example feL4 application thread run function
44    let mut lib_src_file = File::create(Path::new(&subcmd.path).join("src").join("lib.rs"))?;
45    lib_src_file.write_all(APP_LIB_CODE.as_bytes())?;
46
47    // Add feL4 dependencies to Cargo.toml
48    let mut cargo_toml_file = OpenOptions::new()
49        .append(true)
50        .open(Path::new(&subcmd.path).join("Cargo.toml"))?;
51
52    // Add feL4 dev-dependencies
53    cargo_toml_file.write_all(CARGO_TOML_TEXT.as_bytes())?;
54
55    let mut fel4_toml_file = File::create(Path::new(&subcmd.path).join("fel4.toml"))?;
56    fel4_toml_file.write_all(get_exemplar_default_toml().as_bytes())?;
57
58    // Create Xargo.toml with our target features
59    let mut xargo_toml_file = File::create(Path::new(&subcmd.path).join("Xargo.toml"))?;
60    xargo_toml_file.write_all(XARGO_TOML_TEXT.as_bytes())?;
61
62    // Create rust-toolchain file pinned to nightly
63    let mut toolchain_file = File::create(Path::new(&subcmd.path).join("rust-toolchain"))?;
64    toolchain_file.write_all(b"nightly\n")?;
65
66    Ok(())
67}
68
69fn generate_target_specs(subcmd: &NewCmd) -> Result<(), Error> {
70    // Create target specifications directory and specification files
71    let target_specs_path = Path::new(&subcmd.path).join("target_specs");
72    fs::create_dir(Path::new(&target_specs_path))?;
73
74    let mut target_spec_readme_file = File::create(&target_specs_path.join("README.md"))?;
75    target_spec_readme_file.write_all(FEL4_TARGET_SPEC_README.as_bytes())?;
76
77    let mut target_spec_x86_64_file =
78        File::create(&target_specs_path.join("x86_64-sel4-fel4.json"))?;
79    target_spec_x86_64_file.write_all(FEL4_TARGET_SPEC_X86_64_SEL4_FEL4.as_bytes())?;
80
81    let mut target_spec_armv7_file = File::create(&target_specs_path.join("armv7-sel4-fel4.json"))?;
82    target_spec_armv7_file.write_all(FEL4_TARGET_SPEC_ARMV7_SEL4_FEL4.as_bytes())?;
83
84    let mut target_spec_aarch64_file =
85        File::create(&target_specs_path.join("aarch64-sel4-fel4.json"))?;
86    target_spec_aarch64_file.write_all(FEL4_TARGET_SPEC_AARCH64_SEL4_FEL4.as_bytes())?;
87
88    Ok(())
89}
90
91pub fn generate_tests_source_files(base_dir: Option<&Path>) -> Result<(), Error> {
92    let src_path = if let Some(path) = base_dir {
93        path.join("src").join("fel4_test.rs")
94    } else {
95        Path::new("src").join("fel4_test.rs")
96    };
97
98    if !src_path.exists() {
99        let mut test_src_file = File::create(&src_path)
100            .map_err(|e| Error::IO(format!("Could not create fel4_test.rs {}", e)))?;
101        test_src_file
102            .write_all(TEST_LIB_CODE.as_bytes())
103            .map_err(|e| Error::IO(format!("Could not write to fel4_test.rs {}", e)))?;
104    }
105
106    Ok(())
107}
108
109const FEL4_TARGET_SPEC_README: &str = include_str!("../target_specs/README.md");
110
111const FEL4_TARGET_SPEC_X86_64_SEL4_FEL4: &str =
112    include_str!("../target_specs/x86_64-sel4-fel4.json");
113
114const FEL4_TARGET_SPEC_ARMV7_SEL4_FEL4: &str = include_str!("../target_specs/armv7-sel4-fel4.json");
115
116const FEL4_TARGET_SPEC_AARCH64_SEL4_FEL4: &str =
117    include_str!("../target_specs/aarch64-sel4-fel4.json");
118
119const APP_LIB_CODE: &str = include_str!("../templates/lib.rs");
120
121const XARGO_TOML_TEXT: &str = include_str!("../templates/Xargo.toml");
122
123const CARGO_TOML_TEXT: &str = include_str!("../templates/Cargo.toml.part");
124
125const TEST_LIB_CODE: &str = include_str!("../templates/fel4_test.rs");