1
/****************************************************************************
2
**
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the QtCore module of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
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();
88
    static void cleanup()
89
    {
90
        QLibrarySettings *ls = qt_library_settings();
91
        if (ls)
92
            ls->settings.reset(0);
93
    }
94
    static QSettings *configuration()
95
    {
96
        QLibrarySettings *ls = qt_library_settings();
97
        return ls ? ls->settings.data() : 0;
98
    }
99
};
100
101
QLibrarySettings::QLibrarySettings()
102
    : settings(QLibraryInfoPrivate::findConfiguration())
103
{
104
#ifndef BOOTSTRAPPING
105
    qAddPostRoutine(QLibraryInfoPrivate::cleanup);
106
#endif
107
}
108
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
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
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
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
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
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
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();
520
void qt_core_boilerplate()
521
{
522
    printf("This is the QtCore library version " QT_VERSION_STR "\n"
523
           "Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).\n"
524
           "Contact: Nokia Corporation (qt-info@nokia.com)\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