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

Last change on this file since 22 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 19.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** 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 are unsure which license is appropriate for your use, please
37** contact the sales department 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 "qpointer.h"
48
49#ifdef QT_BUILD_QMAKE
50QT_BEGIN_NAMESPACE
51extern QString qmake_libraryInfoFile();
52QT_END_NAMESPACE
53#else
54# include "qcoreapplication.h"
55#endif
56
57#ifdef Q_OS_MAC
58# include "private/qcore_mac_p.h"
59#endif
60
61#include "qconfig.cpp"
62
63QT_BEGIN_NAMESPACE
64
65#ifndef QT_NO_SETTINGS
66
67struct QLibrarySettings
68{
69 QLibrarySettings();
70 ~QLibrarySettings() { delete static_cast<QSettings *>(settings); }
71 QSettings *settings;
72};
73Q_GLOBAL_STATIC(QLibrarySettings, qt_library_settings)
74
75class QLibraryInfoPrivate
76{
77public:
78 static QSettings *findConfiguration();
79 static void cleanup()
80 {
81 QLibrarySettings *ls = qt_library_settings();
82 if (ls) {
83 delete static_cast<QSettings *>(ls->settings);
84 ls->settings = 0;
85 }
86 }
87 static QSettings *configuration()
88 {
89#ifdef QT_NO_THREAD
90 // This recursion guard should be a temporary solution; the recursive
91 // dependency should be found and removed.
92 static bool initializing = false;
93 if (initializing)
94 return 0;
95 initializing = true;
96#endif
97 QLibrarySettings *ls = qt_library_settings();
98#ifdef QT_NO_THREAD
99 initializing = false;
100#endif
101 return ls ? static_cast<QSettings *>(qt_library_settings()->settings) : (QSettings*)0;
102 }
103};
104
105QLibrarySettings::QLibrarySettings()
106{
107 settings = QLibraryInfoPrivate::findConfiguration();
108#ifndef QT_BUILD_QMAKE
109 qAddPostRoutine(QLibraryInfoPrivate::cleanup);
110#endif
111}
112
113QSettings *QLibraryInfoPrivate::findConfiguration()
114{
115 QString qtconfig = QLatin1String(":/qt/etc/qt.conf");
116#ifdef QT_BUILD_QMAKE
117 if(!QFile::exists(qtconfig))
118 qtconfig = qmake_libraryInfoFile();
119#else
120 if (!QFile::exists(qtconfig) && QCoreApplication::instance()) {
121#ifdef Q_OS_MAC
122 CFBundleRef bundleRef = CFBundleGetMainBundle();
123 if (bundleRef) {
124 QCFType<CFURLRef> urlRef = CFBundleCopyResourceURL(bundleRef,
125 QCFString(QLatin1String("qt.conf")),
126 0,
127 0);
128 if (urlRef) {
129 QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
130 qtconfig = QDir::cleanPath(path);
131 }
132 }
133 if (qtconfig.isEmpty())
134#endif
135 {
136 QDir pwd(QCoreApplication::applicationDirPath());
137 qtconfig = pwd.filePath(QLatin1String("qt.conf"));
138 }
139 }
140#endif
141 if (QFile::exists(qtconfig))
142 return new QSettings(qtconfig, QSettings::IniFormat);
143 return 0; //no luck
144}
145
146/*!
147 \class QLibraryInfo
148 \brief The QLibraryInfo class provides information about the Qt library.
149
150 \ingroup misc
151 \mainclass
152
153 Many pieces of information are established when Qt is configured.
154 Installation paths, license information, and even a unique build
155 key. This class provides an abstraction for accessing this
156 information.
157
158 \table
159 \header \o Function \o Return value
160 \row \o buildKey() \o A string that identifies the Qt version and
161 the configuration. This key is used to ensure
162 that \l{plugins} link against the same version
163 of Qt as the application.
164 \row \o location() \o The path to a certain Qt
165 component (e.g., documentation, header files).
166 \row \o licensee(),
167 licensedProducts() \o Licensing information.
168 \endtable
169
170 You can also use a \c qt.conf file to override the hard-coded paths
171 that are compiled into the Qt library. For more information, see
172 the \l {Using qt.conf} documentation.
173
174 \sa QSysInfo, {Using qt.conf}
175*/
176
177/*! \internal
178
179 You cannot create a QLibraryInfo, instead only the static functions are available to query
180 information.
181*/
182
183QLibraryInfo::QLibraryInfo()
184{ }
185
186/*!
187 Returns the person to whom this build of Qt is licensed.
188
189 \sa licensedProducts()
190*/
191
192QString
193QLibraryInfo::licensee()
194{
195 const char *str = QT_CONFIGURE_LICENSEE;
196 return QString::fromLocal8Bit(str);
197}
198
199/*!
200 Returns the products that the license for this build of Qt has access to.
201
202 \sa licensee()
203*/
204
205QString
206QLibraryInfo::licensedProducts()
207{
208 const char *str = QT_CONFIGURE_LICENSED_PRODUCTS;
209 return QString::fromLatin1(str);
210}
211
212/*!
213 Returns a unique key identifying this build of Qt and its
214 configurations. This key is not globally unique, rather only useful
215 for establishing of two configurations are compatible. This can be
216 used to compare with the \c QT_BUILD_KEY preprocessor symbol.
217
218 \sa location()
219*/
220
221QString
222QLibraryInfo::buildKey()
223{
224 return QString::fromLatin1(QT_BUILD_KEY);
225}
226
227/*!
228 Returns the location specified by \a loc.
229
230*/
231
232QString
233QLibraryInfo::location(LibraryLocation loc)
234{
235 QString ret;
236 if(!QLibraryInfoPrivate::configuration()) {
237 const char *path = 0;
238 switch (loc) {
239#ifdef QT_CONFIGURE_PREFIX_PATH
240 case PrefixPath:
241 path = QT_CONFIGURE_PREFIX_PATH;
242 break;
243#endif
244#ifdef QT_CONFIGURE_DOCUMENTATION_PATH
245 case DocumentationPath:
246 path = QT_CONFIGURE_DOCUMENTATION_PATH;
247 break;
248#endif
249#ifdef QT_CONFIGURE_HEADERS_PATH
250 case HeadersPath:
251 path = QT_CONFIGURE_HEADERS_PATH;
252 break;
253#endif
254#ifdef QT_CONFIGURE_LIBRARIES_PATH
255 case LibrariesPath:
256 path = QT_CONFIGURE_LIBRARIES_PATH;
257 break;
258#endif
259#ifdef QT_CONFIGURE_BINARIES_PATH
260 case BinariesPath:
261 path = QT_CONFIGURE_BINARIES_PATH;
262 break;
263#endif
264#ifdef QT_CONFIGURE_PLUGINS_PATH
265 case PluginsPath:
266 path = QT_CONFIGURE_PLUGINS_PATH;
267 break;
268#endif
269#ifdef QT_CONFIGURE_DATA_PATH
270 case DataPath:
271 path = QT_CONFIGURE_DATA_PATH;
272 break;
273#endif
274#ifdef QT_CONFIGURE_TRANSLATIONS_PATH
275 case TranslationsPath:
276 path = QT_CONFIGURE_TRANSLATIONS_PATH;
277 break;
278#endif
279#ifdef QT_CONFIGURE_SETTINGS_PATH
280 case SettingsPath:
281 path = QT_CONFIGURE_SETTINGS_PATH;
282 break;
283#endif
284#ifdef QT_CONFIGURE_EXAMPLES_PATH
285 case ExamplesPath:
286 path = QT_CONFIGURE_EXAMPLES_PATH;
287 break;
288#endif
289#ifdef QT_CONFIGURE_DEMOS_PATH
290 case DemosPath:
291 path = QT_CONFIGURE_DEMOS_PATH;
292 break;
293#endif
294 default:
295 break;
296 }
297
298 if (path)
299 ret = QString::fromLocal8Bit(path);
300 } else {
301 QString key;
302 QString defaultValue;
303 switch(loc) {
304 case PrefixPath:
305 key = QLatin1String("Prefix");
306 break;
307 case DocumentationPath:
308 key = QLatin1String("Documentation");
309 defaultValue = QLatin1String("doc");
310 break;
311 case HeadersPath:
312 key = QLatin1String("Headers");
313 defaultValue = QLatin1String("include");
314 break;
315 case LibrariesPath:
316 key = QLatin1String("Libraries");
317 defaultValue = QLatin1String("lib");
318 break;
319 case BinariesPath:
320 key = QLatin1String("Binaries");
321 defaultValue = QLatin1String("bin");
322 break;
323 case PluginsPath:
324 key = QLatin1String("Plugins");
325 defaultValue = QLatin1String("plugins");
326 break;
327 case DataPath:
328 key = QLatin1String("Data");
329 break;
330 case TranslationsPath:
331 key = QLatin1String("Translations");
332 defaultValue = QLatin1String("translations");
333 break;
334 case SettingsPath:
335 key = QLatin1String("Settings");
336 break;
337 case ExamplesPath:
338 key = QLatin1String("Examples");
339 break;
340 case DemosPath:
341 key = QLatin1String("Demos");
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 config->endGroup();
426 }
427 }
428
429 if (QDir::isRelativePath(ret)) {
430 if (loc == PrefixPath) {
431 // we make the prefix path absolute to the executable's directory
432#ifdef QT_BUILD_QMAKE
433 return QFileInfo(qmake_libraryInfoFile()).absolutePath();
434#else
435 if (QCoreApplication::instance()) {
436#ifdef Q_OS_MAC
437 CFBundleRef bundleRef = CFBundleGetMainBundle();
438 if (bundleRef) {
439 QCFType<CFURLRef> urlRef = CFBundleCopyBundleURL(bundleRef);
440 if (urlRef) {
441 QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
442 return QDir::cleanPath(path + QLatin1String("/Contents"));
443 }
444 }
445#endif
446 return QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(ret);
447 } else {
448 return QDir::current().absoluteFilePath(ret);
449 }
450#endif
451 } else {
452 // we make any other path absolute to the prefix directory
453 return QDir(location(PrefixPath)).absoluteFilePath(ret);
454 }
455 }
456 return ret;
457}
458
459/*!
460 \enum QLibraryInfo::LibraryLocation
461
462 \keyword library location
463
464 This enum type is used to specify a specific location
465 specifier:
466
467 \value PrefixPath The default prefix for all paths.
468 \value DocumentationPath The location for documentation upon install.
469 \value HeadersPath The location for all headers.
470 \value LibrariesPath The location of installed librarires.
471 \value BinariesPath The location of installed Qt binaries (tools and applications).
472 \value PluginsPath The location of installed Qt plugins.
473 \value DataPath The location of general Qt data.
474 \value TranslationsPath The location of translation information for Qt strings.
475 \value SettingsPath The location for Qt settings.
476 \value ExamplesPath The location for examples upon install.
477 \value DemosPath The location for demos upon install.
478
479 \sa location()
480*/
481
482#endif // QT_NO_SETTINGS
483
484QT_END_NAMESPACE
485
486#if defined(Q_CC_GNU) && defined(Q_OS_LINUX) && !defined(QT_LINUXBASE) && !defined(QT_BOOTSTRAPPED)
487
488# include <sys/syscall.h>
489# include <unistd.h>
490
491static const char boilerplate[] =
492 "This is the QtCore library version " QT_VERSION_STR "\n"
493 "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).\n"
494 "Contact: Qt Software Information ([email protected])\n"
495 "\n"
496 "Build key: " QT_BUILD_KEY;
497
498extern "C" {
499void qt_core_init_boilerplate() __attribute__((noreturn));
500}
501
502# if defined(QT_ARCH_I386)
503#define sysinit() (void)0
504#define syswrite(msg, len) \
505 ({ int res; \
506 asm volatile ("movl %%ebx, %%edi\n" \
507 "movl $1, %%ebx\n" \
508 "int $0x80\n" \
509 "movl %%edi, %%ebx\n" \
510 : "=a" (res) : "0" (SYS_write), "c" (msg), "d" (len) : "edi"); res; })
511#define sysexit(c) \
512 asm ("xor %%ebx, %%ebx\n" \
513 "int $0x80\n" \
514 : : "a" (SYS_exit)); _exit(c)
515
516# elif defined(QT_ARCH_X86_64)
517#define sysinit() (void)0
518#define syswrite(msg, len) \
519 ({ int res; \
520 asm volatile ("syscall\n" \
521 : "=a" (res) : "0" (SYS_write), "D" (1), "S" (msg), "d" (len) : "rcx"); res; })
522#define sysexit(c) \
523 asm ("syscall\n" \
524 : : "a" (SYS_exit), "D" (0)); _exit(c)
525
526# elif defined(QT_ARCH_IA64)
527#define sysinit() \
528 asm volatile ("{.mlx\n" \
529 " nop.m 0\n" \
530 " movl r2 = @pcrel(boilerplate);;" \
531 "}\n" \
532 "{.mii\n" \
533 " mov r10 = @ltoffx(boilerplate)\n" \
534 " mov r1 = ip\n" \
535 " adds r2 = -16, r2\n;;\n" \
536 "}\n" \
537 " add r1 = r2, r1;;\n" \
538 " sub r1 = r1, r10;;\n" \
539 : : : "r2", "r10")
540#define syswrite(msg, len) \
541 ({ const char *_msg = msg; \
542 asm ("mov out0=%1\n" \
543 "mov out1=%2\n" \
544 "mov out2=%3\n" \
545 ";;\n" \
546 "mov r15=%0\n" \
547 "break 0x100000;;\n" \
548 : : "I" (SYS_write), "I" (1), "r" (_msg), "r" (len)); })
549#define sysexit(c) \
550 asm ("mov out0=%1\n" \
551 ";;\n" \
552 "mov r15=%0\n" \
553 "break 0x100000;;\n" \
554 : : "I" (SYS_exit), "O" (0)); write(1, 0, 0); _exit(c)
555# else
556#define sysinit() (void)0
557#define syswrite(msg, len) (msg); (len)
558#define sysexit(c) __builtin_exit(c)
559# endif
560
561#define sysputs(msg) syswrite(msg, -1 + sizeof(msg))
562#define sysendl() syswrite("\n", 1)
563#define print_qt_configure(_which) \
564 ({const char *which = _which; \
565 which += 12; \
566 int len = 0; \
567 while (which[len]) ++len; \
568 syswrite(which, len); })
569
570void qt_core_init_boilerplate()
571{
572 sysinit();
573 sysputs(boilerplate);
574 sysputs("\nInstallation prefix: ");
575 print_qt_configure(qt_configure_prefix_path_str);
576 sysputs("\nLibrary path: ");
577 print_qt_configure(qt_configure_libraries_path_str);
578 sysputs("\nInclude path: ");
579 print_qt_configure(qt_configure_headers_path_str);
580 sysendl();
581 sysexit(0);
582}
583
584#endif
Note: See TracBrowser for help on using the repository browser.