source: trunk/src/corelib/global/qlibraryinfo.cpp@ 846

Last change on this file since 846 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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