Skip to main content

qt_build_utils/tool/
qtpaths.rs

1// SPDX-FileCopyrightText: 2026 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
2// SPDX-FileContributor: Andrew Hayzen <andrew.hayzen@kdab.com>
3//
4// SPDX-License-Identifier: MIT OR Apache-2.0
5
6use std::{path::PathBuf, process::Command};
7
8use crate::{utils, QtInstallation, QtTool};
9
10/// Arguments for [QtToolQtPaths::query]
11#[derive(Default)]
12pub struct QtPathsQueryArguments {
13    query: Option<String>,
14    qtconf: Option<String>,
15    // NOTE: could add query-format here later
16}
17
18impl QtPathsQueryArguments {
19    /// Which Qt property to query for
20    pub fn query(mut self, query: &str) -> Self {
21        self.query = Some(query.to_string());
22        self
23    }
24
25    /// Path to a qt.conf file
26    pub fn qtconf(mut self, qtconf: &str) -> Self {
27        self.qtconf = Some(qtconf.to_string());
28        self
29    }
30}
31
32impl From<&str> for QtPathsQueryArguments {
33    fn from(value: &str) -> Self {
34        Self::default().query(value)
35    }
36}
37
38/// A wrapper around the qtpaths tool
39pub struct QtToolQtPaths {
40    executable: PathBuf,
41}
42
43impl QtToolQtPaths {
44    /// Construct a [QtToolQtPaths] from a given [QtInstallation]
45    pub fn new(qt_installation: &dyn QtInstallation) -> Self {
46        let executable = qt_installation
47            .try_find_tool(QtTool::QtPaths)
48            .expect("Could not find qtpaths");
49
50        // Ensure that the executable works
51        utils::check_executable_help(&executable).unwrap();
52
53        Self { executable }
54    }
55
56    // NOTE: if we later have query format json, could have a method that returns a HashMap of all values
57
58    /// Find the path for a given Qt property
59    ///
60    /// Note: this will fail on Qt 5
61    pub fn query(&self, query_args: impl Into<QtPathsQueryArguments>) -> Option<String> {
62        let query_args = query_args.into();
63        let mut args = vec![];
64
65        // Determine if there is a specific query
66        if let Some(query) = &query_args.query {
67            args.extend(["--query", query]);
68        } else {
69            args.push("--query")
70        }
71
72        // Determine if there is a custom qtconf
73        if let Some(qtconf) = &query_args.qtconf {
74            args.extend(["--qtconf", qtconf]);
75        }
76
77        // Run the qtpaths command and trim the output
78        let output = Command::new(&self.executable)
79            .args(args)
80            // Binaries should work without environment and this prevents
81            // LD_LIBRARY_PATH from causing different Qt version clashes
82            .env_clear()
83            // NOTE: Qt 5 will fail as there is no -query parameter
84            .output()
85            .ok()?
86            .stdout;
87        Some(String::from_utf8_lossy(&output).trim().to_owned())
88    }
89}
90
91#[cfg(feature = "qt_minimal")]
92impl QtToolQtPaths {
93    /// Construct from an executable path this is used interally to allow for querying for the Qt version
94    pub(crate) fn from_path_buf(executable: PathBuf) -> Self {
95        // Ensure that the executable works
96        utils::check_executable_help(&executable).unwrap();
97
98        Self { executable }
99    }
100}