1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
3 | |
4 | #include "property.h" |
5 | |
6 | #include <qdir.h> |
7 | #include <qsettings.h> |
8 | #include <qtversion.h> |
9 | #include <qmakelibraryinfo.h> |
10 | #include <qstringlist.h> |
11 | #include <stdio.h> |
12 | |
13 | namespace { |
14 | constexpr int PropSuccessRetCode = 0; |
15 | constexpr int PropFailRetCode = 101; |
16 | } |
17 | |
18 | QT_BEGIN_NAMESPACE |
19 | |
20 | static const struct { |
21 | const char *name; |
22 | int loc; |
23 | bool raw; |
24 | bool singular; |
25 | } propList[] = { |
26 | { .name: "QT_SYSROOT" , .loc: QMakeLibraryInfo::SysrootPath, .raw: true, .singular: true }, |
27 | { .name: "QT_INSTALL_PREFIX" , .loc: QLibraryInfo::PrefixPath, .raw: false, .singular: false }, |
28 | { .name: "QT_INSTALL_ARCHDATA" , .loc: QLibraryInfo::ArchDataPath, .raw: false, .singular: false }, |
29 | { .name: "QT_INSTALL_DATA" , .loc: QLibraryInfo::DataPath, .raw: false, .singular: false }, |
30 | { .name: "QT_INSTALL_DOCS" , .loc: QLibraryInfo::DocumentationPath, .raw: false, .singular: false }, |
31 | { .name: "QT_INSTALL_HEADERS" , .loc: QLibraryInfo::HeadersPath, .raw: false, .singular: false }, |
32 | { .name: "QT_INSTALL_LIBS" , .loc: QLibraryInfo::LibrariesPath, .raw: false, .singular: false }, |
33 | { .name: "QT_INSTALL_LIBEXECS" , .loc: QLibraryInfo::LibraryExecutablesPath, .raw: false, .singular: false }, |
34 | { .name: "QT_INSTALL_BINS" , .loc: QLibraryInfo::BinariesPath, .raw: false, .singular: false }, |
35 | { .name: "QT_INSTALL_TESTS" , .loc: QLibraryInfo::TestsPath, .raw: false, .singular: false }, |
36 | { .name: "QT_INSTALL_PLUGINS" , .loc: QLibraryInfo::PluginsPath, .raw: false, .singular: false }, |
37 | { .name: "QT_INSTALL_QML" , .loc: QLibraryInfo::QmlImportsPath, .raw: false, .singular: false }, |
38 | { .name: "QT_INSTALL_TRANSLATIONS" , .loc: QLibraryInfo::TranslationsPath, .raw: false, .singular: false }, |
39 | { .name: "QT_INSTALL_CONFIGURATION" , .loc: QLibraryInfo::SettingsPath, .raw: false, .singular: false }, |
40 | { .name: "QT_INSTALL_EXAMPLES" , .loc: QLibraryInfo::ExamplesPath, .raw: false, .singular: false }, |
41 | { .name: "QT_INSTALL_DEMOS" , .loc: QLibraryInfo::ExamplesPath, .raw: false, .singular: false }, // Just backwards compat |
42 | { .name: "QT_HOST_PREFIX" , .loc: QMakeLibraryInfo::HostPrefixPath, .raw: true, .singular: false }, |
43 | { .name: "QT_HOST_DATA" , .loc: QMakeLibraryInfo::HostDataPath, .raw: true, .singular: false }, |
44 | { .name: "QT_HOST_BINS" , .loc: QMakeLibraryInfo::HostBinariesPath, .raw: true, .singular: false }, |
45 | { .name: "QT_HOST_LIBEXECS" , .loc: QMakeLibraryInfo::HostLibraryExecutablesPath, .raw: true, .singular: false }, |
46 | { .name: "QT_HOST_LIBS" , .loc: QMakeLibraryInfo::HostLibrariesPath, .raw: true, .singular: false }, |
47 | { .name: "QMAKE_SPEC" , .loc: QMakeLibraryInfo::HostSpecPath, .raw: true, .singular: true }, |
48 | { .name: "QMAKE_XSPEC" , .loc: QMakeLibraryInfo::TargetSpecPath, .raw: true, .singular: true }, |
49 | }; |
50 | |
51 | QMakeProperty::QMakeProperty() : settings(nullptr) |
52 | { |
53 | reload(); |
54 | } |
55 | |
56 | void QMakeProperty::reload() |
57 | { |
58 | QMakeLibraryInfo::reload(); |
59 | for (unsigned i = 0; i < sizeof(propList)/sizeof(propList[0]); i++) { |
60 | QString name = QString::fromLatin1(ba: propList[i].name); |
61 | if (!propList[i].singular) { |
62 | m_values[ProKey(name + "/src" )] = QMakeLibraryInfo::rawLocation( |
63 | loc: propList[i].loc, group: QMakeLibraryInfo::EffectiveSourcePaths); |
64 | m_values[ProKey(name + "/get" )] = QMakeLibraryInfo::rawLocation( |
65 | loc: propList[i].loc, group: QMakeLibraryInfo::EffectivePaths); |
66 | } |
67 | QString val = QMakeLibraryInfo::rawLocation(loc: propList[i].loc, group: QMakeLibraryInfo::FinalPaths); |
68 | if (!propList[i].raw) { |
69 | m_values[ProKey(name + "/dev" )] = |
70 | QMakeLibraryInfo::rawLocation(loc: propList[i].loc, group: QMakeLibraryInfo::DevicePaths); |
71 | m_values[ProKey(name)] = QMakeLibraryInfo::path(loc: propList[i].loc); |
72 | name += "/raw" ; |
73 | } |
74 | m_values[ProKey(name)] = val; |
75 | } |
76 | #ifdef QMAKE_VERSION_STR |
77 | m_values["QMAKE_VERSION" ] = ProString(QMAKE_VERSION_STR); |
78 | #endif |
79 | #ifdef QT_VERSION_STR |
80 | m_values["QT_VERSION" ] = ProString(QT_VERSION_STR); |
81 | #endif |
82 | } |
83 | |
84 | QMakeProperty::~QMakeProperty() |
85 | { |
86 | delete settings; |
87 | settings = nullptr; |
88 | } |
89 | |
90 | void QMakeProperty::initSettings() |
91 | { |
92 | if (!settings) { |
93 | settings = new QSettings(QSettings::UserScope, "QtProject" , "QMake" ); |
94 | settings->setFallbacksEnabled(false); |
95 | } |
96 | } |
97 | |
98 | ProString |
99 | QMakeProperty::value(const ProKey &vk) |
100 | { |
101 | ProString val = m_values.value(key: vk); |
102 | if (!val.isNull()) |
103 | return val; |
104 | |
105 | initSettings(); |
106 | return settings->value(key: vk.toQString()).toString(); |
107 | } |
108 | |
109 | bool |
110 | QMakeProperty::hasValue(const ProKey &v) |
111 | { |
112 | return !value(vk: v).isNull(); |
113 | } |
114 | |
115 | void |
116 | QMakeProperty::setValue(QString var, const QString &val) |
117 | { |
118 | initSettings(); |
119 | settings->setValue(key: var, value: val); |
120 | } |
121 | |
122 | void |
123 | QMakeProperty::remove(const QString &var) |
124 | { |
125 | initSettings(); |
126 | settings->remove(key: var); |
127 | } |
128 | |
129 | int QMakeProperty::queryProperty(const QStringList &optionProperties, |
130 | const PropertyPrinter &printer) |
131 | { |
132 | QList<QPair<QString, QString>> output; |
133 | int ret = PropSuccessRetCode; |
134 | if (optionProperties.isEmpty()) { |
135 | initSettings(); |
136 | const auto keys = settings->childKeys(); |
137 | for (const QString &key : keys) { |
138 | QString val = settings->value(key).toString(); |
139 | output.append(t: { key, val }); |
140 | } |
141 | QStringList specialProps; |
142 | for (unsigned i = 0; i < sizeof(propList) / sizeof(propList[0]); i++) |
143 | specialProps.append(t: QString::fromLatin1(ba: propList[i].name)); |
144 | #ifdef QMAKE_VERSION_STR |
145 | specialProps.append(t: "QMAKE_VERSION" ); |
146 | #endif |
147 | #ifdef QT_VERSION_STR |
148 | specialProps.append(t: "QT_VERSION" ); |
149 | #endif |
150 | for (const QString &prop : std::as_const(t&: specialProps)) { |
151 | ProString val = value(vk: ProKey(prop)); |
152 | ProString pval = value(vk: ProKey(prop + "/raw" )); |
153 | ProString gval = value(vk: ProKey(prop + "/get" )); |
154 | ProString sval = value(vk: ProKey(prop + "/src" )); |
155 | ProString dval = value(vk: ProKey(prop + "/dev" )); |
156 | output.append(t: { prop, val.toQString() }); |
157 | if (!pval.isEmpty() && pval != val) |
158 | output.append(t: { prop + "/raw" , pval.toQString() }); |
159 | if (!gval.isEmpty() && gval != (pval.isEmpty() ? val : pval)) |
160 | output.append(t: { prop + "/get" , gval.toQString() }); |
161 | if (!sval.isEmpty() && sval != gval) |
162 | output.append(t: { prop + "/src" , sval.toQString() }); |
163 | if (!dval.isEmpty() && dval != pval) |
164 | output.append(t: { prop + "/dev" , dval.toQString() }); |
165 | } |
166 | } else { |
167 | for (const auto &prop : optionProperties) { |
168 | const ProKey pkey(prop); |
169 | if (!hasValue(v: pkey)) { |
170 | ret = PropFailRetCode; |
171 | output.append(t: { prop, QString("**Unknown**" ) }); |
172 | } else { |
173 | output.append(t: { prop, value(vk: pkey).toQString() }); |
174 | } |
175 | } |
176 | } |
177 | printer(output); |
178 | return ret; |
179 | } |
180 | |
181 | int QMakeProperty::setProperty(const QStringList &optionProperties) |
182 | { |
183 | for (auto it = optionProperties.cbegin(); it != optionProperties.cend(); ++it) { |
184 | QString var = (*it); |
185 | ++it; |
186 | if (it == optionProperties.cend()) { |
187 | return PropFailRetCode; |
188 | } |
189 | if (!var.startsWith(s: "." )) |
190 | setValue(var, val: (*it)); |
191 | } |
192 | return PropSuccessRetCode; |
193 | } |
194 | |
195 | void QMakeProperty::unsetProperty(const QStringList &optionProperties) |
196 | { |
197 | for (auto it = optionProperties.cbegin(); it != optionProperties.cend(); ++it) { |
198 | QString var = (*it); |
199 | if (!var.startsWith(s: "." )) |
200 | remove(var); |
201 | } |
202 | } |
203 | |
204 | QT_END_NAMESPACE |
205 | |