src/corelib/global/qlibraryinfo.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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