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