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
13namespace {
14constexpr int PropSuccessRetCode = 0;
15constexpr int PropFailRetCode = 101;
16}
17
18QT_BEGIN_NAMESPACE
19
20static 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
51QMakeProperty::QMakeProperty() : settings(nullptr)
52{
53 reload();
54}
55
56void 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
84QMakeProperty::~QMakeProperty()
85{
86 delete settings;
87 settings = nullptr;
88}
89
90void QMakeProperty::initSettings()
91{
92 if (!settings) {
93 settings = new QSettings(QSettings::UserScope, "QtProject", "QMake");
94 settings->setFallbacksEnabled(false);
95 }
96}
97
98ProString
99QMakeProperty::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
109bool
110QMakeProperty::hasValue(const ProKey &v)
111{
112 return !value(vk: v).isNull();
113}
114
115void
116QMakeProperty::setValue(QString var, const QString &val)
117{
118 initSettings();
119 settings->setValue(key: var, value: val);
120}
121
122void
123QMakeProperty::remove(const QString &var)
124{
125 initSettings();
126 settings->remove(key: var);
127}
128
129int 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
181int 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
195void 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
204QT_END_NAMESPACE
205

source code of qtbase/qmake/property.cpp