simics_package/artifacts/
mod.rs1use crate::{Error, Result, HOST_DIRNAME};
8use artifact_dependency::ARTIFACT_NAMEPARTS;
9use cargo_subcommand::Subcommand;
10use std::{fs::read_dir, path::PathBuf};
11use typed_builder::TypedBuilder;
12
13#[derive(TypedBuilder, Debug, Clone, Default)]
14pub struct PackageArtifacts {
16 pub libs: Vec<PathBuf>,
19 pub files: Vec<(String, String)>,
22}
23
24impl PackageArtifacts {
25 pub fn from_subcommand(subcommand: &Subcommand) -> Result<Self> {
28 let module_cdylib = subcommand
29 .artifacts()
30 .map(|a| {
31 subcommand.build_dir(subcommand.target()).join(format!(
32 "{}{}{}",
33 ARTIFACT_NAMEPARTS.0,
34 a.name.replace('_', "-"),
35 ARTIFACT_NAMEPARTS.1
36 ))
37 })
38 .find(|p| p.exists())
39 .ok_or_else(|| Error::CdylibArtifactNotFound {
40 package: subcommand.package().to_string(),
41 })?;
42
43 let module_artifact = PathBuf::from({
44 let file_name = module_cdylib
45 .file_name()
46 .ok_or_else(|| Error::FilenameNotFound {
47 path: module_cdylib.to_path_buf(),
48 })?
49 .to_str()
50 .ok_or_else(|| Error::FilenameNotFound {
51 path: module_cdylib.to_path_buf(),
52 })?;
53 let module_cdylib_dir =
54 module_cdylib
55 .parent()
56 .ok_or_else(|| Error::ParentNotFound {
57 path: module_cdylib.to_path_buf(),
58 })?;
59
60 module_cdylib_dir
61 .join(file_name.replace('_', "-"))
62 .to_str()
63 .ok_or_else(|| Error::FilenameNotFound {
64 path: module_cdylib.to_path_buf(),
65 })?
66 });
67
68 let target_profile_build_dir = subcommand.build_dir(subcommand.target()).join("build");
69
70 let target_profile_build_subdirs = read_dir(target_profile_build_dir)?
72 .filter_map(|rd| rd.ok())
73 .map(|de| de.path())
74 .filter(|p| {
75 p.is_dir()
76 && p.file_name().is_some_and(|n| {
77 n.to_str()
78 .is_some_and(|ns| ns.starts_with(subcommand.package()))
79 })
80 && !p
81 .join(format!("build-script-build{}", ARTIFACT_NAMEPARTS.4))
82 .exists()
83 && p.join("out").is_dir()
84 })
85 .collect::<Vec<_>>();
86
87 let cdylib_out_artifacts = target_profile_build_subdirs
89 .iter()
90 .map(|bd| bd.join("out"))
91 .map(|od| {
92 read_dir(od).map(|rd| {
93 Ok(rd
94 .filter_map(|rd| rd.ok())
95 .map(|de| de.path())
96 .filter(|p| {
97 p.file_name().is_some_and(|n| {
98 n.to_str().is_some_and(|ns| {
99 ns.starts_with(ARTIFACT_NAMEPARTS.0)
100 && ns.ends_with(ARTIFACT_NAMEPARTS.1)
101 })
102 })
103 })
104 .collect::<Vec<_>>())
105 })?
106 })
107 .collect::<Result<Vec<_>>>()?
108 .into_iter()
109 .flatten()
110 .map(|a| {
111 a.file_name()
112 .and_then(|n| n.to_str())
113 .ok_or_else(|| Error::FilenameNotFound { path: a.clone() })
114 .map(|t| (a.clone(), subcommand.build_dir(subcommand.target()).join(t)))
115 })
116 .collect::<Result<Vec<_>>>()?;
117
118 let cdylib_out_artifacts = cdylib_out_artifacts
119 .iter()
120 .map(|a| a.1.clone())
121 .collect::<Vec<_>>();
122
123 let libs = vec![module_artifact]
124 .into_iter()
125 .chain(cdylib_out_artifacts)
126 .collect::<Vec<_>>();
127
128 let host_dir = PathBuf::from(HOST_DIRNAME);
129 let lib_dir = host_dir.join("lib");
130
131 let files = libs
136 .iter()
137 .map(|file_path| {
138 file_path
139 .canonicalize()
140 .map_err(Error::from)
141 .and_then(|file_path| {
142 file_path
143 .file_name()
144 .ok_or_else(|| Error::FilenameNotFound {
145 path: file_path.clone(),
146 })
147 .and_then(|file_name| {
148 lib_dir
149 .join(file_name)
150 .to_str()
151 .ok_or_else(|| Error::PathConversionError {
152 path: lib_dir.join(file_name),
153 })
154 .and_then(|packaged_file_path| {
155 Ok((
156 packaged_file_path.to_string(),
157 file_path
158 .to_str()
159 .ok_or_else(|| Error::PathConversionError {
160 path: file_path.clone(),
161 })?
162 .to_string(),
163 ))
164 })
165 })
166 })
167 })
168 .collect::<Result<Vec<_>>>()?;
169
170 Ok(Self { libs, files })
171 }
172}