1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdir.h"
43 #include "qfile.h"
44 #include "qconfig.h"
45 #include "qsettings.h"
46 #include "qlibraryinfo.h"
47 #include "qscopedpointer.h"
48
49 #if defined(QT_BUILD_QMAKE) || defined(QT_BOOTSTRAPPED)
50 # define BOOTSTRAPPING
51 #endif
52
53 #ifdef BOOTSTRAPPING
54 QT_BEGIN_NAMESPACE
55 extern QString qmake_libraryInfoFile();
56 QT_END_NAMESPACE
57 #else
58 # include "qcoreapplication.h"
59 #endif
60
61 #ifdef Q_OS_MAC
62 # include "private/qcore_mac_p.h"
63 #endif
64
65 #ifdef QLIBRARYINFO_EPOCROOT
66 # include "symbian/epocroot_p.h"
67 #endif
68
69 #include "qconfig.cpp"
70
71 QT_BEGIN_NAMESPACE
72
73 extern void qDumpCPUFeatures(); // in qsimd.cpp
74
75 #ifndef QT_NO_SETTINGS
76
77 struct QLibrarySettings
78 {
79 QLibrarySettings();
80 QScopedPointer<QSettings> settings;
81 };
82 Q_GLOBAL_STATIC(QLibrarySettings, qt_library_settings)
83
84 class QLibraryInfoPrivate
85 {
86 public:
87 static QSettings *findConfiguration();
cleanup()88 static void cleanup()
89 {
90 QLibrarySettings *ls = qt_library_settings();
91 if (ls)
92 ls->settings.reset(0);
93 }
configuration()94 static QSettings *configuration()
95 {
96 QLibrarySettings *ls = qt_library_settings();
97 return ls ? ls->settings.data() : 0;
98 }
99 };
100
QLibrarySettings()101 QLibrarySettings::QLibrarySettings()
102 : settings(QLibraryInfoPrivate::findConfiguration())
103 {
104 #ifndef BOOTSTRAPPING
105 qAddPostRoutine(QLibraryInfoPrivate::cleanup);
106 #endif
107 }
108
findConfiguration()109 QSettings *QLibraryInfoPrivate::findConfiguration()
110 {
111 QString qtconfig = QLatin1String(":/qt/etc/qt.conf");
112 #ifdef BOOTSTRAPPING
113 if(!QFile::exists(qtconfig))
114 qtconfig = qmake_libraryInfoFile();
115 #else
116 if (!QFile::exists(qtconfig) && QCoreApplication::instance()) {
117 #ifdef Q_OS_MAC
118 CFBundleRef bundleRef = CFBundleGetMainBundle();
119 if (bundleRef) {
120 QCFType<CFURLRef> urlRef = CFBundleCopyResourceURL(bundleRef,
121 QCFString(QLatin1String("qt.conf")),
122 0,
123 0);
124 if (urlRef) {
125 QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
126 qtconfig = QDir::cleanPath(path);
127 }
128 }
129 if (qtconfig.isEmpty())
130 #endif
131 {
132 QDir pwd(QCoreApplication::applicationDirPath());
133 qtconfig = pwd.filePath(QLatin1String("qt.conf"));
134 }
135 }
136 #endif
137 if (QFile::exists(qtconfig))
138 return new QSettings(qtconfig, QSettings::IniFormat);
139 return 0; //no luck
140 }
141
142 /*!
143 \class QLibraryInfo
144 \brief The QLibraryInfo class provides information about the Qt library.
145
146 Many pieces of information are established when Qt is configured.
147 Installation paths, license information, and even a unique build
148 key. This class provides an abstraction for accessing this
149 information.
150
151 \table
152 \header \o Function \o Return value
153 \row \o buildKey() \o A string that identifies the Qt version and
154 the configuration. This key is used to ensure
155 that \l{plugins} link against the same version
156 of Qt as the application.
157 \row \o location() \o The path to a certain Qt
158 component (e.g., documentation, header files).
159 \row \o licensee(),
160 licensedProducts() \o Licensing information.
161 \endtable
162
163 You can also use a \c qt.conf file to override the hard-coded paths
164 that are compiled into the Qt library. For more information, see
165 the \l {Using qt.conf} documentation.
166
167 \sa QSysInfo, {Using qt.conf}
168 */
169
170 /*! \internal
171
172 You cannot create a QLibraryInfo, instead only the static functions are available to query
173 information.
174 */
175
QLibraryInfo()176 QLibraryInfo::QLibraryInfo()
177 { }
178
179 /*!
180 Returns the person to whom this build of Qt is licensed.
181
182 \sa licensedProducts()
183 */
184
185 QString
licensee()186 QLibraryInfo::licensee()
187 {
188 const char *str = QT_CONFIGURE_LICENSEE;
189 return QString::fromLocal8Bit(str);
190 }
191
192 /*!
193 Returns the products that the license for this build of Qt has access to.
194
195 \sa licensee()
196 */
197
198 QString
licensedProducts()199 QLibraryInfo::licensedProducts()
200 {
201 const char *str = QT_CONFIGURE_LICENSED_PRODUCTS;
202 return QString::fromLatin1(str);
203 }
204
205 /*!
206 Returns a unique key identifying this build of Qt and its
207 configurations. This key is not globally unique, rather only useful
208 for establishing of two configurations are compatible. This can be
209 used to compare with the \c QT_BUILD_KEY preprocessor symbol.
210
211 \sa location()
212 */
213
214 QString
buildKey()215 QLibraryInfo::buildKey()
216 {
217 return QString::fromLatin1(QT_BUILD_KEY);
218 }
219
220 /*!
221 \since 4.6
222 Returns the installation date for this build of Qt. The install date will
223 usually be the last time that Qt sources were configured.
224 */
225 #ifndef QT_NO_DATESTRING
226 QDate
buildDate()227 QLibraryInfo::buildDate()
228 {
229 return QDate::fromString(QString::fromLatin1(qt_configure_installation + 12), Qt::ISODate);
230 }
231 #endif //QT_NO_DATESTRING
232
233 /*!
234 Returns the location specified by \a loc.
235
236 */
237
238 QString
location(LibraryLocation loc)239 QLibraryInfo::location(LibraryLocation loc)
240 {
241 QString ret;
242 if(!QLibraryInfoPrivate::configuration()) {
243 const char *path = 0;
244 switch (loc) {
245 #ifdef QT_CONFIGURE_PREFIX_PATH
246 case PrefixPath:
247 path = QT_CONFIGURE_PREFIX_PATH;
248 break;
249 #endif
250 #ifdef QT_CONFIGURE_DOCUMENTATION_PATH
251 case DocumentationPath:
252 path = QT_CONFIGURE_DOCUMENTATION_PATH;
253 break;
254 #endif
255 #ifdef QT_CONFIGURE_HEADERS_PATH
256 case HeadersPath:
257 path = QT_CONFIGURE_HEADERS_PATH;
258 break;
259 #endif
260 #ifdef QT_CONFIGURE_LIBRARIES_PATH
261 case LibrariesPath:
262 path = QT_CONFIGURE_LIBRARIES_PATH;
263 break;
264 #endif
265 #ifdef QT_CONFIGURE_BINARIES_PATH
266 case BinariesPath:
267 path = QT_CONFIGURE_BINARIES_PATH;
268 break;
269 #endif
270 #ifdef QT_CONFIGURE_PLUGINS_PATH
271 case PluginsPath:
272 path = QT_CONFIGURE_PLUGINS_PATH;
273 break;
274 #endif
275 #ifdef QT_CONFIGURE_IMPORTS_PATH
276 case ImportsPath:
277 path = QT_CONFIGURE_IMPORTS_PATH;
278 break;
279 #endif
280 #ifdef QT_CONFIGURE_DATA_PATH
281 case DataPath:
282 path = QT_CONFIGURE_DATA_PATH;
283 break;
284 #endif
285 #ifdef QT_CONFIGURE_TRANSLATIONS_PATH
286 case TranslationsPath:
287 path = QT_CONFIGURE_TRANSLATIONS_PATH;
288 break;
289 #endif
290 #ifdef QT_CONFIGURE_SETTINGS_PATH
291 case SettingsPath:
292 path = QT_CONFIGURE_SETTINGS_PATH;
293 break;
294 #endif
295 #ifdef QT_CONFIGURE_EXAMPLES_PATH
296 case ExamplesPath:
297 path = QT_CONFIGURE_EXAMPLES_PATH;
298 break;
299 #endif
300 #ifdef QT_CONFIGURE_DEMOS_PATH
301 case DemosPath:
302 path = QT_CONFIGURE_DEMOS_PATH;
303 break;
304 #endif
305 default:
306 break;
307 }
308
309 if (path)
310 ret = QString::fromLocal8Bit(path);
311 } else {
312 QString key;
313 QString defaultValue;
314 switch(loc) {
315 case PrefixPath:
316 key = QLatin1String("Prefix");
317 break;
318 case DocumentationPath:
319 key = QLatin1String("Documentation");
320 defaultValue = QLatin1String("doc");
321 break;
322 case HeadersPath:
323 key = QLatin1String("Headers");
324 defaultValue = QLatin1String("include");
325 break;
326 case LibrariesPath:
327 key = QLatin1String("Libraries");
328 defaultValue = QLatin1String("lib");
329 break;
330 case BinariesPath:
331 key = QLatin1String("Binaries");
332 defaultValue = QLatin1String("bin");
333 break;
334 case PluginsPath:
335 key = QLatin1String("Plugins");
336 defaultValue = QLatin1String("plugins");
337 break;
338 case ImportsPath:
339 key = QLatin1String("Imports");
340 defaultValue = QLatin1String("imports");
341 break;
342 case DataPath:
343 key = QLatin1String("Data");
344 break;
345 case TranslationsPath:
346 key = QLatin1String("Translations");
347 defaultValue = QLatin1String("translations");
348 break;
349 case SettingsPath:
350 key = QLatin1String("Settings");
351 break;
352 case ExamplesPath:
353 key = QLatin1String("Examples");
354 break;
355 case DemosPath:
356 key = QLatin1String("Demos");
357 break;
358 default:
359 break;
360 }
361
362 if(!key.isNull()) {
363 QSettings *config = QLibraryInfoPrivate::configuration();
364 config->beginGroup(QLatin1String("Paths"));
365
366 QString subKey;
367 {
368 /*
369 find the child group whose version number is closest
370 to the library version. for example and we have the
371 following groups:
372
373 Paths
374 Paths/4.0
375 Paths/4.1.2
376 Paths/4.2.5
377 Paths/5
378
379 if QT_VERSION is 4.0.1, then we use 'Paths/4.0'
380 if QT_VERSION is 4.1.5, then we use 'Paths/4.1.2'
381 if QT_VERSION is 4.6.3, then we use 'Paths/4.2.5'
382 if QT_VERSION is 6.0.2, then we use 'Paths/5'
383
384 note: any of the trailing version numbers may be
385 omitted (in which case, they default to zero),
386 i.e. 4 == 4.0.0, 4.1 == 4.1.0, and so on
387 */
388 enum {
389 QT_MAJOR = ((QT_VERSION >> 16) & 0xFF),
390 QT_MINOR = ((QT_VERSION >> 8) & 0xFF),
391 QT_PATCH = (QT_VERSION & 0xFF)
392 };
393 int maj = 0, min = 0, pat = 0;
394 QStringList children = config->childGroups();
395 for(int child = 0; child < children.size(); ++child) {
396 QString cver = children.at(child);
397 QStringList cver_list = cver.split(QLatin1Char('.'));
398 if(cver_list.size() > 0 && cver_list.size() < 4) {
399 bool ok;
400 int cmaj = -1, cmin = -1, cpat = -1;
401 cmaj = cver_list[0].toInt(&ok);
402 if(!ok || cmaj < 0)
403 continue;
404 if(cver_list.size() >= 2) {
405 cmin = cver_list[1].toInt(&ok);
406 if(!ok)
407 continue;
408 if(cmin < 0)
409 cmin = -1;
410 }
411 if(cver_list.size() >= 3) {
412 cpat = cver_list[2].toInt(&ok);
413 if(!ok)
414 continue;
415 if(cpat < 0)
416 cpat = -1;
417 }
418 if((cmaj >= maj && cmaj <= QT_MAJOR) &&
419 (cmin == -1 || (cmin >= min && cmin <= QT_MINOR)) &&
420 (cpat == -1 || (cpat >= pat && cpat <= QT_PATCH)) &&
421 config->contains(cver + QLatin1Char('/') + key)) {
422 subKey = cver + QLatin1Char('/');
423 maj = cmaj;
424 min = cmin;
425 pat = cpat;
426 }
427 }
428 }
429 }
430 ret = config->value(subKey + key, defaultValue).toString();
431 // expand environment variables in the form $(ENVVAR)
432 int rep;
433 QRegExp reg_var(QLatin1String("\\$\\(.*\\)"));
434 reg_var.setMinimal(true);
435 while((rep = reg_var.indexIn(ret)) != -1) {
436 ret.replace(rep, reg_var.matchedLength(),
437 QString::fromLocal8Bit(qgetenv(ret.mid(rep + 2,
438 reg_var.matchedLength() - 3).toLatin1().constData()).constData()));
439 }
440
441 #ifdef QLIBRARYINFO_EPOCROOT
442 // $${EPOCROOT} is a special case, resolve it similarly to qmake.
443 QRegExp epocrootMatcher(QLatin1String("\\$\\$\\{EPOCROOT\\}"));
444 if ((rep = epocrootMatcher.indexIn(ret)) != -1)
445 ret.replace(rep, epocrootMatcher.matchedLength(), qt_epocRoot());
446 #endif
447
448 config->endGroup();
449 }
450 }
451
452 if (QDir::isRelativePath(ret)) {
453 QString baseDir;
454 if (loc == PrefixPath) {
455 // we make the prefix path absolute to the executable's directory
456 #ifdef BOOTSTRAPPING
457 baseDir = QFileInfo(qmake_libraryInfoFile()).absolutePath();
458 #else
459 if (QCoreApplication::instance()) {
460 #ifdef Q_OS_MAC
461 CFBundleRef bundleRef = CFBundleGetMainBundle();
462 if (bundleRef) {
463 QCFType<CFURLRef> urlRef = CFBundleCopyBundleURL(bundleRef);
464 if (urlRef) {
465 QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
466 return QDir::cleanPath(QString(path) + QLatin1String("/Contents/") + ret);
467 }
468 }
469 #endif
470 baseDir = QCoreApplication::applicationDirPath();
471 } else {
472 baseDir = QDir::currentPath();
473 }
474 #endif
475 } else {
476 // we make any other path absolute to the prefix directory
477 baseDir = location(PrefixPath);
478 }
479 ret = QDir::cleanPath(baseDir + QLatin1Char('/') + ret);
480 }
481 return ret;
482 }
483
484 /*!
485 \enum QLibraryInfo::LibraryLocation
486
487 \keyword library location
488
489 This enum type is used to specify a specific location
490 specifier:
491
492 \value PrefixPath The default prefix for all paths.
493 \value DocumentationPath The location for documentation upon install.
494 \value HeadersPath The location for all headers.
495 \value LibrariesPath The location of installed libraries.
496 \value BinariesPath The location of installed Qt binaries (tools and applications).
497 \value PluginsPath The location of installed Qt plugins.
498 \value ImportsPath The location of installed QML extensions to import.
499 \value DataPath The location of general Qt data.
500 \value TranslationsPath The location of translation information for Qt strings.
501 \value SettingsPath The location for Qt settings.
502 \value ExamplesPath The location for examples upon install.
503 \value DemosPath The location for demos upon install.
504
505 \sa location()
506 */
507
508 #endif // QT_NO_SETTINGS
509
510 QT_END_NAMESPACE
511
512 #if defined(Q_CC_GNU) && defined(ELF_INTERPRETER)
513 # include <stdio.h>
514 # include <stdlib.h>
515
516 extern const char qt_core_interpreter[] __attribute__((section(".interp")))
517 = ELF_INTERPRETER;
518
519 extern "C" void qt_core_boilerplate();
qt_core_boilerplate()520 void qt_core_boilerplate()
521 {
522 printf("This is the QtCore library version " QT_VERSION_STR "\n"
523 "Copyright (C) 2015 The Qt Company Ltd.\n"
524 "Contact: http://www.qt.io/licensing/\n"
525 "\n"
526 "Build key: " QT_BUILD_KEY "\n"
527 "Compat build key: "
528 #ifdef QT_BUILD_KEY_COMPAT
529 "| " QT_BUILD_KEY_COMPAT " "
530 #endif
531 #ifdef QT_BUILD_KEY_COMPAT2
532 "| " QT_BUILD_KEY_COMPAT2 " "
533 #endif
534 #ifdef QT_BUILD_KEY_COMPAT3
535 "| " QT_BUILD_KEY_COMPAT3 " "
536 #endif
537 "|\n"
538 "Build date: %s\n"
539 "Installation prefix: %s\n"
540 "Library path: %s\n"
541 "Include path: %s\n",
542 qt_configure_installation + 12,
543 qt_configure_prefix_path_str + 12,
544 qt_configure_libraries_path_str + 12,
545 qt_configure_headers_path_str + 12);
546
547 QT_PREPEND_NAMESPACE(qDumpCPUFeatures)();
548
549 #ifdef QT_EVAL
550 extern void qt_core_eval_init(uint);
551 qt_core_eval_init(1);
552 #endif
553
554 exit(0);
555 }
556
557 #endif
558