@@ -8,6 +8,7 @@ mod checksum;
88mod download;
99mod extract;
1010
11+ use std:: collections:: HashMap ;
1112use std:: fs:: DirEntry ;
1213use std:: path:: { Path , PathBuf } ;
1314
@@ -24,6 +25,8 @@ impl TryFrom<PathBuf> for QtInstallationQtMinimal {
2425 type Error = anyhow:: Error ;
2526
2627 fn try_from ( path_qt : PathBuf ) -> Result < Self , Self :: Error > {
28+ println ! ( "cargo::rerun-if-changed={}" , path_qt. display( ) ) ;
29+
2730 // Verify that the expected folders exist
2831 for folder in [ "bin" , "include" , "lib" , "libexec" ] {
2932 if !path_qt. join ( folder) . exists ( ) {
@@ -70,29 +73,8 @@ impl TryFrom<semver::Version> for QtInstallationQtMinimal {
7073 let manifest: artifact:: ParsedQtManifest =
7174 serde_json:: from_str ( qt_artifacts:: QT_MANIFEST_JSON ) ?;
7275
73- // Find artifacts matching Qt version
74- //
75- // Arch could be x86_64
76- // OS could be linux
77- // https://doc.rust-lang.org/cargo/appendix/glossary.html#target
78- //
79- // TODO: is there a better way to find the arch and os ?
80- // and should this be configurable via env var overrides?
81- let target = std:: env:: var ( "TARGET" ) . expect ( "TARGET to be set" ) ;
82- let target_parts: Vec < _ > = target. split ( "-" ) . collect ( ) ;
83- let arch = target_parts
84- . first ( )
85- . expect ( "TARGET to have a <arch><sub> component" ) ;
86- let os = target_parts
87- . get ( 2 )
88- . expect ( "TARGET to have a <sys> component" ) ;
89- let artifacts: Vec < ParsedQtArtifact > = manifest
90- . artifacts
91- . into_iter ( )
92- . filter ( |artifact| {
93- artifact. arch == * arch && artifact. os == * os && artifact. version == version
94- } )
95- . collect ( ) ;
76+ // Find artifacts for the Qt version
77+ let artifacts = Self :: match_artifact_requirements ( manifest. artifacts , & [ version. clone ( ) ] ) ;
9678
9779 // Find the first bin / include
9880 let artifact_bin = artifacts
@@ -110,8 +92,8 @@ impl TryFrom<semver::Version> for QtInstallationQtMinimal {
11092 "{}.{}.{}" ,
11193 version. major, version. minor, version. patch
11294 ) )
113- . join ( os)
114- . join ( arch) ;
95+ . join ( & artifact_bin . os )
96+ . join ( & artifact_bin . arch ) ;
11597 artifact_bin. download_and_extract ( & extract_target_dir) ;
11698 if artifact_bin != artifact_include {
11799 artifact_include. download_and_extract ( & extract_target_dir) ;
@@ -174,6 +156,7 @@ impl QtInstallation for QtInstallationQtMinimal {
174156impl QtInstallationQtMinimal {
175157 fn qt_minimal_root ( ) -> PathBuf {
176158 // Check if a custom root has been set
159+ println ! ( "cargo::rerun-if-env-changed=QT_MINIMAL_DOWNLOAD_ROOT" ) ;
177160 let path = if let Ok ( root) = std:: env:: var ( "QT_MINIMAL_DOWNLOAD_ROOT" ) {
178161 PathBuf :: from ( root)
179162 } else {
@@ -183,14 +166,18 @@ impl QtInstallationQtMinimal {
183166 . join ( "qt_minimal_download" )
184167 } ;
185168
186- std:: fs:: create_dir_all ( & path) . expect ( "Could not create Qt minimal root path" ) ;
169+ // Only create when it doesn't exist to avoid file modifications
170+ if !path. exists ( ) {
171+ std:: fs:: create_dir_all ( & path) . expect ( "Could not create Qt minimal root path" ) ;
172+ }
187173
188174 path
189175 }
190176
191177 /// Get a collection of the locally installed Qt artifacts
192178 pub ( crate ) fn local_artifacts ( ) -> anyhow:: Result < Vec < ParsedQtArtifact > > {
193179 let base_dir = Self :: qt_minimal_root ( ) ;
180+ println ! ( "cargo::rerun-if-changed={}" , base_dir. display( ) ) ;
194181
195182 // Expects folder structure like:
196183 // version/os/arch/qt/{bin, include}
@@ -199,17 +186,23 @@ impl QtInstallationQtMinimal {
199186
200187 // Iterate versions
201188 for version in list_dirs ( & base_dir) {
189+ println ! ( "cargo::rerun-if-changed={}" , version. path( ) . display( ) ) ;
190+
202191 let path = version;
203192 // TODO: Later skip unknown folders,
204193 // this will error if a directory exists which isn't a version number
205194 let semver = semver:: Version :: parse ( path. file_name ( ) . to_str ( ) . unwrap ( ) )
206195 . expect ( "Could not parse semver from directory name" ) ;
207196
208197 for os in list_dirs ( & path. path ( ) ) {
198+ println ! ( "cargo::rerun-if-changed={}" , os. path( ) . display( ) ) ;
199+
209200 let path = os;
210201 let os = path. file_name ( ) . to_str ( ) . unwrap ( ) . to_string ( ) ;
211202
212203 for arch in list_dirs ( & path. path ( ) ) {
204+ println ! ( "cargo::rerun-if-changed={}" , arch. path( ) . display( ) ) ;
205+
213206 let path = arch;
214207 let dir_entries = list_dirs ( & path. path ( ) ) ;
215208
@@ -219,6 +212,7 @@ impl QtInstallationQtMinimal {
219212 . filter ( |dir| dir. file_name ( ) == "qt" )
220213 . last ( )
221214 . expect ( "Expected to find a Qt dir in this folder" ) ;
215+ println ! ( "cargo::rerun-if-changed={}" , qt_dir_path. path( ) . display( ) ) ;
222216
223217 let qt_folders = list_dirs ( & qt_dir_path. path ( ) ) ;
224218 for dir in qt_folders {
@@ -248,6 +242,64 @@ impl QtInstallationQtMinimal {
248242
249243 Ok ( artifacts)
250244 }
245+
246+ /// Find artifacts matching Qt version
247+ pub ( crate ) fn match_artifact_requirements (
248+ artifacts : Vec < ParsedQtArtifact > ,
249+ versions : & [ semver:: Version ] ,
250+ ) -> Vec < ParsedQtArtifact > {
251+ // Arch could be x86_64
252+ // OS could be linux
253+ // https://doc.rust-lang.org/cargo/appendix/glossary.html#target
254+ //
255+ // TODO: is there a better way to find the arch and os ?
256+ // and should this be configurable via env var overrides?
257+ println ! ( "cargo::rerun-if-env-changed=TARGET" ) ;
258+ let target = std:: env:: var ( "TARGET" ) . expect ( "TARGET to be set" ) ;
259+ let target_parts: Vec < _ > = target. split ( "-" ) . collect ( ) ;
260+ let arch = target_parts
261+ . first ( )
262+ . expect ( "TARGET to have a <arch><sub> component" ) ;
263+ let os = target_parts
264+ . get ( 2 )
265+ . expect ( "TARGET to have a <sys> component" ) ;
266+
267+ artifacts
268+ . into_iter ( )
269+ . filter ( |artifact| {
270+ artifact. arch == * arch && artifact. os == * os && versions. contains ( & artifact. version )
271+ } )
272+ . collect ( )
273+ }
274+
275+ /// Merge together artifacts with the same version
276+ /// so that we do not have bin/ and include/ split
277+ //
278+ // NOTE: later we may support bin and include folders being in different places
279+ pub ( crate ) fn group_artifacts ( artifacts : Vec < ParsedQtArtifact > ) -> Vec < ParsedQtArtifact > {
280+ artifacts. into_iter ( ) . fold (
281+ HashMap :: < semver:: Version , ParsedQtArtifact > :: default ( ) ,
282+ |mut acc, mut artifact| {
283+ acc. entry ( artifact. version . clone ( ) )
284+ . and_modify ( |value| {
285+ if value. url == artifact. url {
286+ value. content . append ( & mut artifact. content )
287+ } else {
288+ println ! ( "cargo::warning=Found multiple minimal installations of the same version but different urls: {} and {}" , value. url, artifact. url) ;
289+ }
290+ } )
291+ . or_insert ( artifact) ;
292+ acc
293+ } ,
294+ )
295+ . into_values ( )
296+ // Ensure that artifacts contain bin/ and include/
297+ . filter ( |artifact| {
298+ artifact. content . contains ( & "bin" . to_string ( ) )
299+ && artifact. content . contains ( & "include" . to_string ( ) )
300+ } )
301+ . collect ( )
302+ }
251303}
252304
253305/// Get all valid directories in path bufs, ignoring errors
0 commit comments