liblingo/package/
target_properties.rs

1use serde::{Deserialize, Serialize, Serializer};
2use std::fmt;
3use std::fmt::{Display, Formatter};
4use std::io::Write;
5use std::path::{Path, PathBuf};
6
7pub trait CMakeLoader {
8    fn read_file(&mut self, path: &str) -> anyhow::Result<AutoCmakeLoad>;
9}
10
11impl Serialize for AutoCmakeLoad {
12    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
13    where
14        S: Serializer,
15    {
16        serializer.serialize_none()
17    }
18}
19
20impl Display for AutoCmakeLoad {
21    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
22        f.write_str(&self.0)
23    }
24}
25
26#[derive(Serialize, Deserialize, Clone)]
27pub enum GenericTargetPropertiesFile {
28    Library(LibraryTargetPropertiesFile),
29    App(AppTargetPropertiesFile),
30}
31
32#[derive(Clone)]
33pub enum GenericTargetProperties {
34    Library(LibraryTargetProperties),
35    App(AppTargetProperties),
36}
37
38#[derive(Clone, Default, Debug)]
39pub struct AutoCmakeLoad(String);
40
41impl MergeTargetProperty for AutoCmakeLoad {
42    fn merge(&mut self, parent: &AutoCmakeLoad) -> anyhow::Result<()> {
43        self.0 += &*("\n# ------------------------- \n".to_owned() + &*parent.0);
44        Ok(())
45    }
46}
47
48#[derive(Serialize, Deserialize, Clone)]
49pub struct LibraryTargetPropertiesFile {
50    /// cmake include only available for C and CPP
51    #[serde(rename = "cmake-include", default)]
52    cmake_include: Option<PathBuf>,
53
54    /// files that should be compiled and linked
55    #[serde(rename = "sources", default)]
56    sources: Vec<PathBuf>,
57
58    /// list of files that should be made available to the user
59    #[serde(rename = "sources", default)]
60    artifacts: Vec<PathBuf>,
61}
62
63#[derive(Clone, Default, Debug)]
64pub struct LibraryTargetProperties {
65    /// cmake include only available for C and CPP
66    pub cmake_include: AutoCmakeLoad,
67
68    /// files that should be compiled and linked
69    pub sources: Vec<PathBuf>,
70
71    /// list of files that should be made available to the user
72    pub artifacts: Vec<PathBuf>,
73}
74
75impl LibraryTargetPropertiesFile {
76    pub fn from(self, base_path: &Path) -> LibraryTargetProperties {
77        LibraryTargetProperties {
78            cmake_include: AutoCmakeLoad(
79                self.cmake_include
80                    .map(|cmake_file| {
81                        let absolute_path = base_path.join(cmake_file);
82                        std::fs::read_to_string(absolute_path)
83                            .expect("invalid file {absolute_path}")
84                    })
85                    .unwrap_or_default(),
86            ),
87            sources: self.sources,
88            artifacts: self.artifacts,
89        }
90    }
91}
92
93#[derive(Serialize, Deserialize, Clone, Default)]
94pub struct AppTargetPropertiesFile {
95    /// cmake include only available for C and CPP
96    #[serde(rename = "cmake-include", default)]
97    cmake_include: Option<PathBuf>,
98
99    /// if the runtime should wait for physical time to catch up
100    #[serde(default)]
101    pub fast: bool,
102}
103
104#[derive(Clone, Default)]
105pub struct AppTargetProperties {
106    /// cmake include only available for C and CPP
107    cmake_include: AutoCmakeLoad,
108
109    /// if the runtime should wait for physical time to catch up
110    pub fast: bool,
111}
112
113impl AppTargetPropertiesFile {
114    pub fn from(self, base_path: &Path) -> AppTargetProperties {
115        AppTargetProperties {
116            cmake_include: AutoCmakeLoad(
117                self.cmake_include
118                    .map(|cmake_file| {
119                        let absolute_path = base_path.join(cmake_file);
120                        std::fs::read_to_string(&absolute_path)
121                            .expect("invalid file {absolute_path}")
122                    })
123                    .unwrap_or_default(),
124            ),
125            fast: self.fast,
126        }
127    }
128}
129
130pub trait MergeTargetProperty {
131    fn merge(&mut self, other: &Self) -> anyhow::Result<()>;
132}
133
134pub trait MergeTargetProperties {
135    fn merge(&mut self, other: &LibraryTargetProperties) -> anyhow::Result<()>;
136}
137
138impl MergeTargetProperties for LibraryTargetProperties {
139    fn merge(&mut self, partent: &LibraryTargetProperties) -> anyhow::Result<()> {
140        self.cmake_include.merge(&partent.cmake_include)?;
141        Ok(())
142    }
143}
144
145impl MergeTargetProperties for AppTargetProperties {
146    fn merge(&mut self, parent: &LibraryTargetProperties) -> anyhow::Result<()> {
147        self.cmake_include.merge(&parent.cmake_include)?;
148        Ok(())
149    }
150}
151
152impl MergeTargetProperties for GenericTargetProperties {
153    fn merge(&mut self, other: &LibraryTargetProperties) -> anyhow::Result<()> {
154        match self {
155            GenericTargetProperties::Library(own_lib) => own_lib.merge(other),
156            GenericTargetProperties::App(own_app) => own_app.merge(other),
157        }
158    }
159}
160
161impl AppTargetProperties {
162    pub fn write_artifacts(&self, library_folder: &Path) -> anyhow::Result<()> {
163        let file = library_folder.join("aggregated_cmake_include.cmake");
164
165        let mut fd = std::fs::File::create(file)?;
166        fd.write_all(self.cmake_include.0.as_ref())?;
167        fd.flush()?;
168
169        Ok(())
170    }
171}