Added build system support for installing tests.
[profile/ivi/qtbase.git] / src / corelib / global / qlibraryinfo.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 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 #include "qconfig.cpp"
66
67 QT_BEGIN_NAMESPACE
68
69 extern void qDumpCPUFeatures(); // in qsimd.cpp
70
71 #ifndef QT_NO_SETTINGS
72
73 struct QLibrarySettings
74 {
75     QLibrarySettings();
76     QScopedPointer<QSettings> settings;
77 };
78 Q_GLOBAL_STATIC(QLibrarySettings, qt_library_settings)
79
80 class QLibraryInfoPrivate
81 {
82 public:
83     static QSettings *findConfiguration();
84     static void cleanup()
85     {
86         QLibrarySettings *ls = qt_library_settings();
87         if (ls)
88             ls->settings.reset(0);
89     }
90     static QSettings *configuration()
91     {
92         QLibrarySettings *ls = qt_library_settings();
93         return ls ? ls->settings.data() : 0;
94     }
95 };
96
97 QLibrarySettings::QLibrarySettings()
98     : settings(QLibraryInfoPrivate::findConfiguration())
99 {
100 #ifndef BOOTSTRAPPING
101     qAddPostRoutine(QLibraryInfoPrivate::cleanup);
102 #endif
103 }
104
105 QSettings *QLibraryInfoPrivate::findConfiguration()
106 {
107     QString qtconfig = QLatin1String(":/qt/etc/qt.conf");
108 #ifdef BOOTSTRAPPING
109     if(!QFile::exists(qtconfig))
110         qtconfig = qmake_libraryInfoFile();
111 #else
112     if (!QFile::exists(qtconfig) && QCoreApplication::instance()) {
113 #ifdef Q_OS_MAC
114         CFBundleRef bundleRef = CFBundleGetMainBundle();
115         if (bundleRef) {
116             QCFType<CFURLRef> urlRef = CFBundleCopyResourceURL(bundleRef,
117                                                                QCFString(QLatin1String("qt.conf")),
118                                                                0,
119                                                                0);
120             if (urlRef) {
121                 QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
122                 qtconfig = QDir::cleanPath(path);
123             }
124         }
125         if (qtconfig.isEmpty())
126 #endif
127             {
128                 QDir pwd(QCoreApplication::applicationDirPath());
129                 qtconfig = pwd.filePath(QLatin1String("qt.conf"));
130             }
131     }
132 #endif
133     if (QFile::exists(qtconfig))
134         return new QSettings(qtconfig, QSettings::IniFormat);
135     return 0;     //no luck
136 }
137
138 /*!
139     \class QLibraryInfo
140     \brief The QLibraryInfo class provides information about the Qt library.
141
142     Many pieces of information are established when Qt is configured and built.
143     This class provides an abstraction for accessing that information.
144     By using the static functions of this class, an application can obtain
145     information about the instance of the Qt library which the application
146     is using at run-time.
147
148     You can also use a \c qt.conf file to override the hard-coded paths
149     that are compiled into the Qt library. For more information, see
150     the \l {Using qt.conf} documentation.
151
152     \sa QSysInfo, {Using qt.conf}
153 */
154
155 /*! \internal
156
157    You cannot create a QLibraryInfo, instead only the static functions are available to query
158    information.
159 */
160
161 QLibraryInfo::QLibraryInfo()
162 { }
163
164 /*!
165   Returns the person to whom this build of Qt is licensed.
166
167   \sa licensedProducts()
168 */
169
170 QString
171 QLibraryInfo::licensee()
172 {
173     const char *str = QT_CONFIGURE_LICENSEE;
174     return QString::fromLocal8Bit(str);
175 }
176
177 /*!
178   Returns the products that the license for this build of Qt has access to.
179
180   \sa licensee()
181 */
182
183 QString
184 QLibraryInfo::licensedProducts()
185 {
186     const char *str = QT_CONFIGURE_LICENSED_PRODUCTS;
187     return QString::fromLatin1(str);
188 }
189
190 /*!
191     \since 4.6
192     Returns the installation date for this build of Qt. The install date will
193     usually be the last time that Qt sources were configured.
194 */
195 #ifndef QT_NO_DATESTRING
196 QDate
197 QLibraryInfo::buildDate()
198 {
199     return QDate::fromString(QString::fromLatin1(qt_configure_installation + 12), Qt::ISODate);
200 }
201 #endif //QT_NO_DATESTRING
202
203 /*!
204     \since 5.0
205     Returns true if this build of Qt was built with debugging enabled, or
206     false if it was built in release mode.
207 */
208 bool
209 QLibraryInfo::isDebugBuild()
210 {
211 #ifdef QT_DEBUG
212     return true;
213 #endif
214     return false;
215 }
216
217 /*!
218   Returns the location specified by \a loc.
219
220 */
221
222 QString
223 QLibraryInfo::location(LibraryLocation loc)
224 {
225     QString ret;
226     if(!QLibraryInfoPrivate::configuration()) {
227         const char *path = 0;
228         switch (loc) {
229 #ifdef QT_CONFIGURE_PREFIX_PATH
230         case PrefixPath:
231             path = QT_CONFIGURE_PREFIX_PATH;
232             break;
233 #endif
234 #ifdef QT_CONFIGURE_DOCUMENTATION_PATH
235         case DocumentationPath:
236             path = QT_CONFIGURE_DOCUMENTATION_PATH;
237             break;
238 #endif
239 #ifdef QT_CONFIGURE_HEADERS_PATH
240         case HeadersPath:
241             path = QT_CONFIGURE_HEADERS_PATH;
242             break;
243 #endif
244 #ifdef QT_CONFIGURE_LIBRARIES_PATH
245         case LibrariesPath:
246             path = QT_CONFIGURE_LIBRARIES_PATH;
247             break;
248 #endif
249 #ifdef QT_CONFIGURE_BINARIES_PATH
250         case BinariesPath:
251             path = QT_CONFIGURE_BINARIES_PATH;
252             break;
253 #endif
254 #ifdef QT_CONFIGURE_PLUGINS_PATH
255         case PluginsPath:
256             path = QT_CONFIGURE_PLUGINS_PATH;
257             break;
258 #endif
259 #ifdef QT_CONFIGURE_IMPORTS_PATH
260         case ImportsPath:
261             path = QT_CONFIGURE_IMPORTS_PATH;
262             break;
263 #endif
264 #ifdef QT_CONFIGURE_DATA_PATH
265         case DataPath:
266             path = QT_CONFIGURE_DATA_PATH;
267             break;
268 #endif
269 #ifdef QT_CONFIGURE_TRANSLATIONS_PATH
270         case TranslationsPath:
271             path = QT_CONFIGURE_TRANSLATIONS_PATH;
272             break;
273 #endif
274 #ifdef QT_CONFIGURE_SETTINGS_PATH
275         case SettingsPath:
276             path = QT_CONFIGURE_SETTINGS_PATH;
277             break;
278 #endif
279 #ifdef QT_CONFIGURE_EXAMPLES_PATH
280         case ExamplesPath:
281             path = QT_CONFIGURE_EXAMPLES_PATH;
282             break;
283 #endif
284 #ifdef QT_CONFIGURE_TESTS_PATH
285         case TestsPath:
286             path = QT_CONFIGURE_TESTS_PATH;
287             break;
288 #endif
289         default:
290             break;
291         }
292
293         if (path)
294             ret = QString::fromLocal8Bit(path);
295     } else {
296         QString key;
297         QString defaultValue;
298         switch(loc) {
299         case PrefixPath:
300             key = QLatin1String("Prefix");
301             break;
302         case DocumentationPath:
303             key = QLatin1String("Documentation");
304             defaultValue = QLatin1String("doc");
305             break;
306         case HeadersPath:
307             key = QLatin1String("Headers");
308             defaultValue = QLatin1String("include");
309             break;
310         case LibrariesPath:
311             key = QLatin1String("Libraries");
312             defaultValue = QLatin1String("lib");
313             break;
314         case BinariesPath:
315             key = QLatin1String("Binaries");
316             defaultValue = QLatin1String("bin");
317             break;
318         case PluginsPath:
319             key = QLatin1String("Plugins");
320             defaultValue = QLatin1String("plugins");
321             break;
322         case ImportsPath:
323             key = QLatin1String("Imports");
324             defaultValue = QLatin1String("imports");
325             break;
326         case DataPath:
327             key = QLatin1String("Data");
328             break;
329         case TranslationsPath:
330             key = QLatin1String("Translations");
331             defaultValue = QLatin1String("translations");
332             break;
333         case SettingsPath:
334             key = QLatin1String("Settings");
335             break;
336         case ExamplesPath:
337             key = QLatin1String("Examples");
338             break;
339         case TestsPath:
340             key = QLatin1String("Tests");
341             defaultValue = QLatin1String("tests");
342             break;
343         default:
344             break;
345         }
346
347         if(!key.isNull()) {
348             QSettings *config = QLibraryInfoPrivate::configuration();
349             config->beginGroup(QLatin1String("Paths"));
350
351             QString subKey;
352             {
353                 /*
354                   find the child group whose version number is closest
355                   to the library version.  for example and we have the
356                   following groups:
357
358                   Paths
359                   Paths/4.0
360                   Paths/4.1.2
361                   Paths/4.2.5
362                   Paths/5
363
364                   if QT_VERSION is 4.0.1, then we use 'Paths/4.0'
365                   if QT_VERSION is 4.1.5, then we use 'Paths/4.1.2'
366                   if QT_VERSION is 4.6.3, then we use 'Paths/4.2.5'
367                   if QT_VERSION is 6.0.2, then we use 'Paths/5'
368
369                   note: any of the trailing version numbers may be
370                   omitted (in which case, they default to zero),
371                   i.e. 4 == 4.0.0, 4.1 == 4.1.0, and so on
372                 */
373                 enum {
374                     QT_MAJOR = ((QT_VERSION >> 16) & 0xFF),
375                     QT_MINOR = ((QT_VERSION >> 8) & 0xFF),
376                     QT_PATCH = (QT_VERSION & 0xFF)
377                 };
378                 int maj = 0, min = 0, pat = 0;
379                 QStringList children = config->childGroups();
380                 for(int child = 0; child < children.size(); ++child) {
381                     QString cver = children.at(child);
382                     QStringList cver_list = cver.split(QLatin1Char('.'));
383                     if(cver_list.size() > 0 && cver_list.size() < 4) {
384                         bool ok;
385                         int cmaj = -1, cmin = -1, cpat = -1;
386                         cmaj = cver_list[0].toInt(&ok);
387                         if(!ok || cmaj < 0)
388                             continue;
389                         if(cver_list.size() >= 2) {
390                             cmin = cver_list[1].toInt(&ok);
391                             if(!ok)
392                                 continue;
393                             if(cmin < 0)
394                                 cmin = -1;
395                         }
396                         if(cver_list.size() >= 3) {
397                             cpat = cver_list[2].toInt(&ok);
398                             if(!ok)
399                                 continue;
400                             if(cpat < 0)
401                                 cpat = -1;
402                         }
403                         if((cmaj >= maj && cmaj <= QT_MAJOR) &&
404                            (cmin == -1 || (cmin >= min && cmin <= QT_MINOR)) &&
405                            (cpat == -1 || (cpat >= pat && cpat <= QT_PATCH)) &&
406                            config->contains(cver + QLatin1Char('/') + key)) {
407                             subKey = cver + QLatin1Char('/');
408                             maj = cmaj;
409                             min = cmin;
410                             pat = cpat;
411                         }
412                     }
413                 }
414             }
415             ret = config->value(subKey + key, defaultValue).toString();
416             // expand environment variables in the form $(ENVVAR)
417             int rep;
418             QRegExp reg_var(QLatin1String("\\$\\(.*\\)"));
419             reg_var.setMinimal(true);
420             while((rep = reg_var.indexIn(ret)) != -1) {
421                 ret.replace(rep, reg_var.matchedLength(),
422                             QString::fromLocal8Bit(qgetenv(ret.mid(rep + 2,
423                                 reg_var.matchedLength() - 3).toLatin1().constData()).constData()));
424             }
425
426             config->endGroup();
427         }
428     }
429
430     if (QDir::isRelativePath(ret)) {
431         QString baseDir;
432         if (loc == PrefixPath) {
433             // we make the prefix path absolute to the executable's directory
434 #ifdef BOOTSTRAPPING
435             baseDir = QFileInfo(qmake_libraryInfoFile()).absolutePath();
436 #else
437             if (QCoreApplication::instance()) {
438 #ifdef Q_OS_MAC
439                 CFBundleRef bundleRef = CFBundleGetMainBundle();
440                 if (bundleRef) {
441                     QCFType<CFURLRef> urlRef = CFBundleCopyBundleURL(bundleRef);
442                     if (urlRef) {
443                         QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
444                         return QDir::cleanPath(QString(path) + QLatin1String("/Contents/") + ret);
445                     }
446                 }
447 #endif
448                 baseDir = QCoreApplication::applicationDirPath();
449             } else {
450                 baseDir = QDir::currentPath();
451             }
452 #endif
453         } else {
454             // we make any other path absolute to the prefix directory
455             baseDir = location(PrefixPath);
456         }
457         ret = QDir::cleanPath(baseDir + QLatin1Char('/') + ret);
458     }
459     return ret;
460 }
461
462 /*!
463     \enum QLibraryInfo::LibraryLocation
464
465     \keyword library location
466
467     This enum type is used to specify a specific location
468     specifier:
469
470     \value PrefixPath The default prefix for all paths.
471     \value DocumentationPath The location for documentation upon install.
472     \value HeadersPath The location for all headers.
473     \value LibrariesPath The location of installed libraries.
474     \value BinariesPath The location of installed Qt binaries (tools and applications).
475     \value PluginsPath The location of installed Qt plugins.
476     \value ImportsPath The location of installed QML extensions to import.
477     \value DataPath The location of general Qt data.
478     \value TranslationsPath The location of translation information for Qt strings.
479     \value SettingsPath The location for Qt settings.
480     \value ExamplesPath The location for examples upon install.
481     \value TestsPath The location of installed Qt testcases.
482
483     \sa location()
484 */
485
486 #endif // QT_NO_SETTINGS
487
488 QT_END_NAMESPACE
489
490 #if defined(Q_CC_GNU) && defined(ELF_INTERPRETER)
491 #  include <stdio.h>
492 #  include <stdlib.h>
493
494 extern const char qt_core_interpreter[] __attribute__((section(".interp")))
495     = ELF_INTERPRETER;
496
497 extern "C" void qt_core_boilerplate();
498 void qt_core_boilerplate()
499 {
500     printf("This is the QtCore library version " QT_VERSION_STR "\n"
501            "Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).\n"
502            "Contact: Nokia Corporation (qt-info@nokia.com)\n"
503            "\n"
504            "Build date:          %s\n"
505            "Installation prefix: %s\n"
506            "Library path:        %s\n"
507            "Include path:        %s\n",
508            qt_configure_installation + 12,
509            qt_configure_prefix_path_str + 12,
510            qt_configure_libraries_path_str + 12,
511            qt_configure_headers_path_str + 12);
512
513     QT_PREPEND_NAMESPACE(qDumpCPUFeatures)();
514
515 #ifdef QT_EVAL
516     extern void qt_core_eval_init(uint);
517     qt_core_eval_init(1);
518 #endif
519
520     exit(0);
521 }
522
523 #endif