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