liblingo/backends/
cmake_cpp.rs1use std::fs;
2use std::io::Write;
3
4use std::process::Command;
5
6use crate::package::App;
7use crate::util::execute_command_to_build_result;
8
9use crate::backends::{
10 BatchBackend, BatchBuildResults, BuildCommandOptions, BuildProfile, BuildResult, CommandSpec,
11};
12
13pub struct CmakeCpp;
14
15fn gen_cmake_files(app: &App, options: &BuildCommandOptions) -> BuildResult {
16 let build_dir = app.output_root.join("build");
17 fs::create_dir_all(&build_dir)?;
18
19 let app_build_folder = app.src_gen_dir().join(&app.main_reactor_name);
21 let cmake_file = app_build_folder.clone().join("CMakeLists.txt");
22
23 app.properties.write_artifacts(&app_build_folder)?;
25
26 let src_gen_dir = app.src_gen_dir();
28
29 let mut content = fs::read_to_string(&cmake_file)?;
31 let include_statement = format!(
32 "\ninclude({}/aggregated_cmake_include.cmake)",
33 app_build_folder.display()
34 );
35 content += &*include_statement;
36
37 let mut f = fs::OpenOptions::new().write(true).open(&cmake_file)?;
39 f.write_all(content.as_ref())?;
40 f.flush()?;
41
42 let mut cmake = Command::new("cmake");
44 cmake.arg(format!(
45 "-DCMAKE_BUILD_TYPE={}",
46 if options.profile == BuildProfile::Release {
47 "RELEASE"
48 } else {
49 "DEBUG"
50 }
51 ));
52 cmake.arg(format!(
53 "-DCMAKE_INSTALL_PREFIX={}",
54 app.output_root.display()
55 ));
56 cmake.arg("-DCMAKE_INSTALL_BINDIR=bin");
57 cmake.arg("-DREACTOR_CPP_VALIDATE=ON");
58 cmake.arg("-DREACTOR_CPP_TRACE=OFF");
59 cmake.arg("-DREACTOR_CPP_LOG_LEVEL=3");
60 cmake.arg(format!(
61 "-DLF_SRC_PKG_PATH={}",
62 app.src_dir_path()
63 .expect("not a valid main reactor path")
64 .display()
65 ));
66 cmake.arg(src_gen_dir);
67 cmake.arg(format!("-B {}", build_dir.display()));
68 cmake.current_dir(&build_dir);
69
70 execute_command_to_build_result(cmake)
71}
72
73fn do_cmake_build(results: &mut BatchBuildResults, options: &BuildCommandOptions) {
74 results.keep_going(options.keep_going);
76
77 super::lfc::LFC::do_parallel_lfc_codegen(options, results, false);
79
80 if !options.compile_target_code {
82 return;
83 }
84
85 results
86 .map(|app| gen_cmake_files(app, options))
88 .gather(|apps| {
90 let build_dir = apps[0].output_root.join("build");
91
92 let mut cmake = Command::new("cmake");
94 cmake.current_dir(&build_dir);
95 cmake.args(["--build", "."]);
96 for app in apps {
97 let name = app.main_reactor.file_stem().unwrap();
99 cmake.arg("--target");
100 cmake.arg(name);
101 }
102 execute_command_to_build_result(cmake)
104 })
105 .map(|app| {
106 let build_dir = app.output_root.join("build");
107 let mut cmake = Command::new("cmake");
109 cmake.current_dir(&build_dir);
110 cmake.args(["--install", "."]);
111 execute_command_to_build_result(cmake)
112 })
113 .map(|app| {
114 let cmake_binary_name = app.main_reactor.file_stem().unwrap();
115 let bin_dir = app.output_root.join("bin");
117 fs::rename(bin_dir.join(cmake_binary_name), app.executable_path())?;
118 Ok(())
119 });
120}
121
122impl BatchBackend for CmakeCpp {
123 fn execute_command(&mut self, command: &CommandSpec, results: &mut BatchBuildResults) {
124 match command {
125 CommandSpec::Build(options) => do_cmake_build(results, options),
126 CommandSpec::Clean => {
127 results.par_map(|app| {
128 crate::util::default_build_clean(&app.output_root)?;
129 Ok(())
130 });
131 }
132 _ => todo!(),
133 }
134 }
135}