/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "configureapp.h" #include "environment.h" #include "tools.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE enum Platforms { WINDOWS, WINDOWS_RT, QNX, ANDROID, OTHER }; std::ostream &operator<<(std::ostream &s, const QString &val) { s << val.toLocal8Bit().data(); return s; } using namespace std; // Macros to simplify options marking #define MARK_OPTION(x,y) ( dictionary[ #x ] == #y ? "*" : " " ) static inline void promptKeyPress() { cout << "(Press any key to continue...)"; if (_getch() == 3) // _Any_ keypress w/no echo(eat for stdout) exit(0); // Exit cleanly for Ctrl+C } Configure::Configure(int& argc, char** argv) : verbose(0) { // Default values for indentation optionIndent = 4; descIndent = 25; outputWidth = 0; // Get console buffer output width CONSOLE_SCREEN_BUFFER_INFO info; HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); if (GetConsoleScreenBufferInfo(hStdout, &info)) outputWidth = info.dwSize.X - 1; outputWidth = qMin(outputWidth, 79); // Anything wider gets unreadable if (outputWidth < 35) // Insanely small, just use 79 outputWidth = 79; int i; for (i = 1; i < argc; i++) configCmdLine += argv[ i ]; if (configCmdLine.size() >= 2 && configCmdLine.at(0) == "-srcdir") { sourcePath = QDir::cleanPath(configCmdLine.at(1)); sourceDir = QDir(sourcePath); configCmdLine.erase(configCmdLine.begin(), configCmdLine.begin() + 2); } else { // Get the path to the executable wchar_t module_name[MAX_PATH]; GetModuleFileName(0, module_name, sizeof(module_name) / sizeof(wchar_t)); QFileInfo sourcePathInfo = QString::fromWCharArray(module_name); sourcePath = sourcePathInfo.absolutePath(); sourceDir = sourcePathInfo.dir(); } buildPath = QDir::currentPath(); #if 0 const QString installPath = QString("C:\\Qt\\%1").arg(QT_VERSION_STR); #else const QString installPath = buildPath; #endif if (sourceDir != buildDir) { //shadow builds! QDir(buildPath).mkpath("bin"); buildDir.mkpath("mkspecs"); } defaultBuildParts << QStringLiteral("libs") << QStringLiteral("tools") << QStringLiteral("examples"); allBuildParts = defaultBuildParts; allBuildParts << QStringLiteral("tests"); dictionary[ "QT_INSTALL_PREFIX" ] = installPath; dictionary[ "QMAKESPEC" ] = getenv("QMAKESPEC"); if (dictionary[ "QMAKESPEC" ].size() == 0) { dictionary[ "QMAKESPEC" ] = Environment::detectQMakeSpec(); dictionary[ "QMAKESPEC_FROM" ] = "detected"; } else { dictionary[ "QMAKESPEC_FROM" ] = "env"; } dictionary[ "WIDGETS" ] = "yes"; dictionary[ "GUI" ] = "yes"; dictionary[ "RTTI" ] = "yes"; dictionary[ "STRIP" ] = "yes"; dictionary[ "PCH" ] = "yes"; dictionary[ "SEPARATE_DEBUG_INFO" ] = "no"; dictionary[ "SSE2" ] = "auto"; dictionary[ "SSE3" ] = "auto"; dictionary[ "SSSE3" ] = "auto"; dictionary[ "SSE4_1" ] = "auto"; dictionary[ "SSE4_2" ] = "auto"; dictionary[ "AVX" ] = "auto"; dictionary[ "AVX2" ] = "auto"; dictionary[ "AVX512" ] = "auto"; dictionary[ "SYNCQT" ] = "auto"; dictionary[ "WMF_BACKEND" ] = "no"; dictionary[ "QML_DEBUG" ] = "yes"; dictionary[ "PLUGIN_MANIFESTS" ] = "no"; dictionary[ "DIRECTWRITE" ] = "auto"; dictionary[ "DIRECTWRITE2" ] = "auto"; dictionary[ "DIRECT2D" ] = "no"; dictionary[ "NIS" ] = "no"; dictionary[ "NEON" ] = "auto"; dictionary[ "LARGE_FILE" ] = "yes"; dictionary[ "FONT_CONFIG" ] = "no"; dictionary[ "POSIX_IPC" ] = "no"; dictionary[ "QT_GLIB" ] = "no"; dictionary[ "QT_ICONV" ] = "auto"; dictionary[ "QT_EVDEV" ] = "auto"; dictionary[ "QT_MTDEV" ] = "auto"; dictionary[ "QT_TSLIB" ] = "auto"; dictionary[ "QT_INOTIFY" ] = "auto"; dictionary[ "QT_EVENTFD" ] = "auto"; dictionary[ "QT_CUPS" ] = "auto"; dictionary[ "CFG_GCC_SYSROOT" ] = "yes"; dictionary[ "SLOG2" ] = "no"; dictionary[ "QNX_IMF" ] = "no"; dictionary[ "PPS" ] = "no"; dictionary[ "LGMON" ] = "no"; dictionary[ "SYSTEM_PROXIES" ] = "yes"; dictionary[ "SCTP" ] = "no"; dictionary[ "WERROR" ] = "auto"; dictionary[ "QREAL" ] = "double"; dictionary[ "ATOMIC64" ] = "auto"; //Only used when cross compiling. dictionary[ "QT_INSTALL_SETTINGS" ] = "/etc/xdg"; QString version; QFile qmake_conf(sourcePath + "/.qmake.conf"); if (qmake_conf.open(QFile::ReadOnly)) { while (!qmake_conf.atEnd()) { static const char beginning[] = "MODULE_VERSION = "; QByteArray line = qmake_conf.readLine(); if (!line.startsWith(beginning)) continue; version = qMove(line).mid(int(strlen(beginning))).trimmed(); break; } qmake_conf.close(); } if (version.isEmpty()) version = QString("%1.%2.%3").arg(QT_VERSION>>16).arg(((QT_VERSION>>8)&0xff)).arg(QT_VERSION&0xff); dictionary[ "VERSION" ] = version; { QRegExp version_re("([0-9]*)\\.([0-9]*)\\.([0-9]*)(|-.*)"); if (version_re.exactMatch(version)) { dictionary[ "VERSION_MAJOR" ] = version_re.cap(1); dictionary[ "VERSION_MINOR" ] = version_re.cap(2); dictionary[ "VERSION_PATCH" ] = version_re.cap(3); } } dictionary[ "REDO" ] = "no"; dictionary[ "BUILD" ] = "debug"; dictionary[ "BUILDALL" ] = "auto"; // Means yes, but not explicitly dictionary[ "FORCEDEBUGINFO" ] = "no"; dictionary[ "RELEASE_TOOLS" ] = "no"; dictionary[ "BUILDTYPE" ] = "none"; dictionary[ "BUILDDEV" ] = "no"; dictionary[ "COMPILE_EXAMPLES" ] = "yes"; dictionary[ "C++STD" ] = "auto"; dictionary[ "USE_GOLD_LINKER" ] = "no"; dictionary[ "ENABLE_NEW_DTAGS" ] = "no"; dictionary[ "SHARED" ] = "yes"; dictionary[ "STATIC_RUNTIME" ] = "no"; dictionary[ "SYSTEM_ZLIB" ] = "auto"; dictionary[ "PCRE" ] = "auto"; dictionary[ "ICU" ] = "no"; dictionary[ "ANGLE" ] = "auto"; dictionary[ "DYNAMICGL" ] = "no"; dictionary[ "GIF" ] = "yes"; dictionary[ "JPEG" ] = "yes"; dictionary[ "PNG" ] = "yes"; dictionary[ "LIBJPEG" ] = "auto"; dictionary[ "LIBPNG" ] = "auto"; dictionary[ "DOUBLECONVERSION" ] = "auto"; dictionary[ "FREETYPE" ] = "yes"; dictionary[ "FREETYPE_FROM" ] = "default"; dictionary[ "HARFBUZZ" ] = "qt"; dictionary[ "ACCESSIBILITY" ] = "yes"; dictionary[ "OPENGL" ] = "yes"; dictionary[ "OPENGL_ES_2" ] = "yes"; dictionary[ "SSL" ] = "auto"; dictionary[ "OPENSSL" ] = "auto"; dictionary[ "LIBPROXY" ] = "no"; dictionary[ "DBUS" ] = "auto"; dictionary[ "STYLE_WINDOWS" ] = "yes"; dictionary[ "STYLE_WINDOWSXP" ] = "auto"; dictionary[ "STYLE_WINDOWSVISTA" ] = "auto"; dictionary[ "STYLE_FUSION" ] = "yes"; dictionary[ "SQL_MYSQL" ] = "no"; dictionary[ "SQL_ODBC" ] = "no"; dictionary[ "SQL_OCI" ] = "no"; dictionary[ "SQL_PSQL" ] = "no"; dictionary[ "SQL_TDS" ] = "no"; dictionary[ "SQL_DB2" ] = "no"; dictionary[ "SQL_SQLITE" ] = "auto"; dictionary[ "SQL_SQLITE_LIB" ] = "qt"; dictionary[ "SQL_SQLITE2" ] = "no"; dictionary[ "SQL_IBASE" ] = "no"; QString tmp = dictionary[ "QMAKESPEC" ]; if (tmp.contains("\\")) { tmp = tmp.mid(tmp.lastIndexOf("\\") + 1); } else { tmp = tmp.mid(tmp.lastIndexOf("/") + 1); } dictionary[ "QMAKESPEC" ] = tmp; dictionary[ "INCREDIBUILD_XGE" ] = "auto"; dictionary[ "LTCG" ] = "no"; dictionary[ "MSVC_MP" ] = "no"; if (dictionary["QMAKESPEC"].startsWith("win32-g++")) { const QString zero = QStringLiteral("0"); const QStringList parts = Environment::gccVersion().split(QLatin1Char('.')); dictionary["QT_GCC_MAJOR_VERSION"] = parts.value(0, zero); dictionary["QT_GCC_MINOR_VERSION"] = parts.value(1, zero); dictionary["QT_GCC_PATCH_VERSION"] = parts.value(2, zero); } } Configure::~Configure() { } QString Configure::formatPath(const QString &path) { QString ret = QDir::cleanPath(path); // This amount of quoting is deemed sufficient. if (ret.contains(QLatin1Char(' '))) { ret.prepend(QLatin1Char('"')); ret.append(QLatin1Char('"')); } return ret; } QString Configure::formatPaths(const QStringList &paths) { QString ret; foreach (const QString &path, paths) { if (!ret.isEmpty()) ret += QLatin1Char(' '); ret += formatPath(path); } return ret; } // #### somehow I get a compiler error about vc++ reaching the nesting limit without // undefining the ansi for scoping. #ifdef for #undef for #endif void Configure::parseCmdLine() { if (configCmdLine.size() && configCmdLine.at(0) == "-top-level") { dictionary[ "TOPLEVEL" ] = "yes"; configCmdLine.removeAt(0); } int argCount = configCmdLine.size(); int i = 0; // Look first for -redo for (int k = 0 ; k < argCount; ++k) { if (configCmdLine.at(k) == "-redo") { dictionary["REDO"] = "yes"; configCmdLine.removeAt(k); reloadCmdLine(k); argCount = configCmdLine.size(); break; } } // Then look for XQMAKESPEC bool isDeviceMkspec = false; for (int j = 0 ; j < argCount; ++j) { if ((configCmdLine.at(j) == "-xplatform") || (configCmdLine.at(j) == "-device")) { isDeviceMkspec = (configCmdLine.at(j) == "-device"); ++j; if (j == argCount) break; dictionary["XQMAKESPEC"] = configCmdLine.at(j); applySpecSpecifics(); break; } } for (; i 1) { dictionary[ "DONE" ] = "error"; cout << "Error: Multiple matches for device '" << dictionary["XQMAKESPEC"] << "'. Candidates are:" << endl; foreach (const QString &device, family) cout << "\t* " << device << endl; } else { Q_ASSERT(family.size() == 1); dictionary["XQMAKESPEC"] = family.at(0); } } else { // Ensure that -spec (XQMAKESPEC) exists in the mkspecs folder as well if (dictionary.contains("XQMAKESPEC") && !mkspecs.contains(dictionary["XQMAKESPEC"], Qt::CaseInsensitive)) { dictionary[ "DONE" ] = "error"; cout << "Invalid option \"" << dictionary["XQMAKESPEC"] << "\" for -xplatform." << endl; } } // Allow tests for private classes to be compiled against internal builds if (dictionary["BUILDDEV"] == "yes") { qtConfig << "private_tests"; if (dictionary["WERROR"] != "no") qmakeConfig << "warnings_are_errors"; if (dictionary["HEADERSCLEAN"] != "no") qmakeConfig << "headersclean"; } else { if (dictionary["WERROR"] == "yes") qmakeConfig << "warnings_are_errors"; if (dictionary["HEADERSCLEAN"] == "yes") qmakeConfig << "headersclean"; } if (dictionary["FORCE_ASSERTS"] == "yes") qtConfig += "force_asserts"; for (QStringList::Iterator dis = disabledModules.begin(); dis != disabledModules.end(); ++dis) { modules.removeAll((*dis)); } for (QStringList::Iterator ena = enabledModules.begin(); ena != enabledModules.end(); ++ena) { if (modules.indexOf((*ena)) == -1) modules += (*ena); } qtConfig += modules; for (QStringList::Iterator it = disabledModules.begin(); it != disabledModules.end(); ++it) qtConfig.removeAll(*it); if ((dictionary["REDO"] != "yes") && (dictionary["DONE"] != "error")) saveCmdLine(); } /*! Modifies the default configuration based on given -platform option. Eg. switches to different default styles for Windows CE. */ void Configure::applySpecSpecifics() { if (dictionary.contains("XQMAKESPEC")) { //Disable building tools when cross compiling. nobuildParts << "tools"; } if (dictionary.value("XQMAKESPEC").startsWith("winphone") || dictionary.value("XQMAKESPEC").startsWith("winrt")) { dictionary[ "STYLE_WINDOWSXP" ] = "no"; dictionary[ "STYLE_WINDOWSVISTA" ] = "no"; dictionary[ "LIBJPEG" ] = "qt"; dictionary[ "LIBPNG" ] = "qt"; dictionary[ "FREETYPE" ] = "yes"; dictionary[ "SSL" ] = "yes"; dictionary[ "OPENSSL" ] = "no"; dictionary[ "DBUS" ] = "no"; dictionary[ "SYSTEM_ZLIB" ] = "no"; dictionary[ "PCRE" ] = "qt"; dictionary[ "ICU" ] = "qt"; dictionary[ "LARGE_FILE" ] = "no"; } else if (dictionary.value("XQMAKESPEC").startsWith("linux")) { //TODO actually wrong. //TODO dictionary[ "STYLE_WINDOWSXP" ] = "no"; dictionary[ "STYLE_WINDOWSVISTA" ] = "no"; dictionary[ "OPENGL" ] = "no"; dictionary[ "DBUS"] = "no"; dictionary[ "QT_INOTIFY" ] = "no"; dictionary[ "QT_CUPS" ] = "no"; dictionary[ "QT_GLIB" ] = "no"; dictionary[ "QT_ICONV" ] = "no"; dictionary[ "QT_EVDEV" ] = "no"; dictionary[ "QT_MTDEV" ] = "no"; dictionary[ "FONT_CONFIG" ] = "auto"; dictionary[ "ANGLE" ] = "no"; } else if (platform() == QNX) { dictionary[ "REDUCE_EXPORTS" ] = "yes"; dictionary["STACK_PROTECTOR_STRONG"] = "auto"; dictionary["SLOG2"] = "auto"; dictionary["QNX_IMF"] = "auto"; dictionary["PPS"] = "auto"; dictionary["LGMON"] = "auto"; dictionary["QT_XKBCOMMON"] = "no"; dictionary[ "ANGLE" ] = "no"; dictionary[ "DYNAMICGL" ] = "no"; dictionary[ "FONT_CONFIG" ] = "auto"; dictionary[ "ICU" ] = "auto"; dictionary[ "POLL" ] = "poll"; dictionary[ "ZLIB" ] = "system"; } else if (platform() == ANDROID) { dictionary[ "REDUCE_EXPORTS" ] = "yes"; dictionary[ "BUILD" ] = "release"; dictionary[ "BUILDALL" ] = "no"; dictionary[ "LARGE_FILE" ] = "no"; dictionary[ "ANGLE" ] = "no"; dictionary[ "DYNAMICGL" ] = "no"; dictionary[ "REDUCE_RELOCATIONS" ] = "yes"; dictionary[ "QT_GETIFADDRS" ] = "no"; dictionary[ "QT_XKBCOMMON" ] = "no"; dictionary["ANDROID_STYLE_ASSETS"] = "yes"; dictionary[ "STYLE_ANDROID" ] = "yes"; dictionary[ "POLL" ] = "poll"; dictionary[ "ZLIB" ] = "system"; } } // Locate a file and return its containing directory. QString Configure::locateFile(const QString &fileName) const { const QString mkspec = dictionary.contains(QStringLiteral("XQMAKESPEC")) ? dictionary[QStringLiteral("XQMAKESPEC")] : dictionary[QStringLiteral("QMAKESPEC")]; const QString file = fileName.toLower(); QStringList pathList; if (file.endsWith(".h")) { static const QStringList headerPaths = Environment::headerPaths(Environment::compilerFromQMakeSpec(mkspec)); pathList = qmakeIncludes; pathList += headerPaths; } else if (file.endsWith(".lib") || file.endsWith(".a")) { static const QStringList libPaths = Environment::libraryPaths(Environment::compilerFromQMakeSpec(mkspec)); pathList = libPaths; } else { // Fallback for .exe and .dll (latter are not covered by QStandardPaths). static const QStringList exePaths = Environment::path(); pathList = exePaths; } return Environment::findFileInPaths(file, pathList); } /*! Default value for options marked as "auto" if the test passes. (Used both by the autoDetection() below, and the desc() function to mark (+) the default option of autodetecting options. */ QString Configure::defaultTo(const QString &option) { // We prefer using the system version of the 3rd party libs if (option == "PCRE" || option == "LIBJPEG" || option == "LIBPNG") return "system"; // These database drivers and image formats can be built-in or plugins. // Prefer plugins when Qt is shared. if (dictionary[ "SHARED" ] == "yes") { if (option == "SQL_MYSQL" || option == "SQL_MYSQL" || option == "SQL_ODBC" || option == "SQL_OCI" || option == "SQL_PSQL" || option == "SQL_TDS" || option == "SQL_DB2" || option == "SQL_SQLITE" || option == "SQL_SQLITE2" || option == "SQL_IBASE") return "yes"; } // By default we do not want to compile OCI driver when compiling with // MinGW, due to lack of such support from Oracle. It prob. won't work. // (Customer may force the use though) if (dictionary["QMAKESPEC"].endsWith("-g++") && option == "SQL_OCI") return "no"; // keep 'auto' default for msvc, since we can't set the language supported if (option == "C++STD" && dictionary["QMAKESPEC"].contains("msvc")) return "auto"; if (option == "SYNCQT" && (!QFile::exists(sourcePath + "/.git"))) return "no"; return "yes"; } bool Configure::checkAngleAvailability(QString *errorMessage /* = 0 */) const { // Check for Direct X SDK (include lib and direct shader compiler 'fxc'). // Up to Direct X SDK June 2010 and for MinGW, this is pointed to by the // DXSDK_DIR variable. Starting with Windows Kit 8, it is included // in the Windows SDK. Checking for the header is not sufficient since // it is also present in MinGW. const QString directXSdk = Environment::detectDirectXSdk(); const Compiler compiler = Environment::compilerFromQMakeSpec(dictionary[QStringLiteral("QMAKESPEC")]); const QString compilerHeader = QStringLiteral("d3dcompiler.h"); if (!findFile(compilerHeader)) { if (errorMessage) *errorMessage = QString::fromLatin1("The header '%1' could not be found.").arg(compilerHeader); return false; } if (dictionary["SSE2"] != "no") { const QString intrinHeader = QStringLiteral("intrin.h"); // Not present on MinGW-32 if (!findFile(intrinHeader)) { if (errorMessage) *errorMessage = QString::fromLatin1("The header '%1' required for SSE2 could not be found.").arg(intrinHeader); return false; } } const QString directXLibrary = QStringLiteral("d3d11.lib"); // Ensures at least the June 2010 DXSDK is present if (!findFile(directXLibrary)) { if (errorMessage) *errorMessage = QString::fromLatin1("The library '%1' could not be found.").arg(directXLibrary); return false; } const QString fxcBinary = QStringLiteral("fxc.exe"); QStringList additionalPaths; if (!directXSdk.isEmpty()) additionalPaths.push_back(directXSdk + QStringLiteral("/Utilities/bin/x86")); QString fxcPath = QStandardPaths::findExecutable(fxcBinary, additionalPaths); if (fxcPath.isEmpty()) { if (errorMessage) *errorMessage = QString::fromLatin1("The shader compiler '%1' could not be found.").arg(fxcBinary); return false; } return true; } QString Configure::checkAvx512Availability() { static const char avx512features[][5] = { "cd", "er", "pf", "bw", "dq", "vl", "ifma", "vbmi" }; // try AVX512 Foundation. No Foundation, nothing else works. if (!tryCompileProject("common/avx512", "AVX512=F")) return QString(); QString available = "avx512f"; for (size_t i = 0; i < sizeof(avx512features)/sizeof(avx512features[0]); ++i) { if (tryCompileProject("common/avx512", QStringLiteral("AVX512=%0").arg(avx512features[i]).toUpper())) { available += " avx512"; available += avx512features[i]; } } return available; } /*! Checks the system for the availability of a feature. Returns true if the feature is available, else false. */ bool Configure::checkAvailability(const QString &part) { bool available = false; if (part == "STYLE_WINDOWSXP") available = (platform() == WINDOWS) && findFile("uxtheme.h"); else if (part == "OBJCOPY") available = tryCompileProject("unix/objcopy"); else if (part == "ATOMIC64") available = tryCompileProject("common/atomic64"); else if (part == "ATOMIC64-LIBATOMIC") available = tryCompileProject("common/atomic64", "LIBS+=-latomic"); else if (part == "ATOMICFPTR") available = tryCompileProject("common/atomicfptr"); else if (part == "SYSTEM_ZLIB") available = findFile("zlib.h"); else if (part == "PCRE") available = findFile("pcre.h"); else if (part == "ICU") available = tryCompileProject("unix/icu"); else if (part == "HARFBUZZ") available = tryCompileProject("unix/harfbuzz"); else if (part == "LIBJPEG") available = findFile("jpeglib.h"); else if (part == "LIBPNG") available = findFile("png.h"); else if (part == "SQL_MYSQL") available = findFile("mysql.h") && findFile("libmySQL.lib"); else if (part == "SQL_ODBC") available = findFile("sql.h") && findFile("sqlext.h") && findFile("odbc32.lib"); else if (part == "SQL_OCI") available = findFile("oci.h") && findFile("oci.lib"); else if (part == "SQL_PSQL") available = findFile("libpq-fe.h") && findFile("libpq.lib") && findFile("ws2_32.lib") && findFile("advapi32.lib"); else if (part == "SQL_TDS") available = findFile("sybfront.h") && findFile("sybdb.h") && findFile("ntwdblib.lib"); else if (part == "SQL_DB2") available = findFile("sqlcli.h") && findFile("sqlcli1.h") && findFile("db2cli.lib"); else if (part == "SQL_SQLITE") available = true; // Built in, we have a fork else if (part == "SQL_SQLITE_LIB") { if (dictionary[ "SQL_SQLITE_LIB" ] == "system") { if (platform() == QNX) { available = true; dictionary[ "QMAKE_LIBS_SQLITE" ] += "-lsqlite3 -lz"; } else { available = findFile("sqlite3.h") && findFile("sqlite3.lib"); if (available) dictionary[ "QMAKE_LIBS_SQLITE" ] += "sqlite3.lib"; } } else { available = true; } } else if (part == "SQL_SQLITE2") available = findFile("sqlite.h") && findFile("sqlite.lib"); else if (part == "SQL_IBASE") available = findFile("ibase.h") && (findFile("gds32_ms.lib") || findFile("gds32.lib")); else if (part == "SSE2") available = tryCompileProject("common/sse2"); else if (part == "SSE3") available = tryCompileProject("common/sse3"); else if (part == "SSSE3") available = tryCompileProject("common/ssse3"); else if (part == "SSE4_1") available = tryCompileProject("common/sse4_1"); else if (part == "SSE4_2") available = tryCompileProject("common/sse4_2"); else if (part == "AVX") available = tryCompileProject("common/avx"); else if (part == "AVX2") available = tryCompileProject("common/avx2"); else if (part == "OPENSSL") available = findFile("openssl\\ssl.h"); else if (part == "LIBPROXY") available = dictionary.contains("XQMAKESPEC") && tryCompileProject("common/libproxy"); else if (part == "DBUS") available = findFile("dbus\\dbus.h"); else if (part == "INCREDIBUILD_XGE") { available = !QStandardPaths::findExecutable(QStringLiteral("BuildConsole.exe")).isEmpty() && !QStandardPaths::findExecutable(QStringLiteral("xgConsole.exe")).isEmpty(); } else if (part == "WMF_BACKEND") { available = findFile("mfapi.h") && findFile("mf.lib"); } else if (part == "DIRECTWRITE") { available = tryCompileProject("win/directwrite"); } else if (part == "DIRECTWRITE2") { available = tryCompileProject("win/directwrite2"); } else if (part == "DIRECT2D") { available = tryCompileProject("qpa/direct2d"); } else if (part == "ICONV") { available = tryCompileProject("unix/iconv") || tryCompileProject("unix/gnu-libiconv"); } else if (part == "EVDEV") { available = tryCompileProject("unix/evdev"); } else if (part == "MTDEV") { available = tryCompileProject("unix/mtdev"); } else if (part == "TSLIB") { available = tryCompileProject("unix/tslib"); } else if (part == "INOTIFY") { available = tryCompileProject("unix/inotify"); } else if (part == "QT_EVENTFD") { available = tryCompileProject("unix/eventfd"); } else if (part == "CUPS") { available = (platform() != WINDOWS) && (platform() != WINDOWS_RT) && tryCompileProject("unix/cups"); } else if (part == "STACK_PROTECTOR_STRONG") { available = (platform() == QNX) && compilerSupportsFlag("qcc -fstack-protector-strong"); } else if (part == "SLOG2") { available = tryCompileProject("unix/slog2"); } else if (part == "QNX_IMF") { available = tryCompileProject("unix/qqnx_imf"); } else if (part == "PPS") { available = (platform() == QNX) && tryCompileProject("unix/pps"); } else if (part == "LGMON") { available = (platform() == QNX) && tryCompileProject("unix/lgmon"); } else if (part == "SCTP") { available = tryCompileProject("unix/sctp"); } else if (part == "NEON") { available = dictionary["QT_CPU_FEATURES"].contains("neon"); } else if (part == "FONT_CONFIG") { available = tryCompileProject("unix/fontconfig"); } else if (part == "DOUBLECONVERSION") { available = tryCompileProject("unix/doubleconversion"); } return available; } /* Autodetect options marked as "auto". */ void Configure::autoDetection() { cout << "Running configuration tests..." << endl; // Auto-detect CPU architectures. detectArch(); if (dictionary["C++STD"] == "auto" && !dictionary["QMAKESPEC"].contains("msvc")) { if (!tryCompileProject("common/c++14")) { dictionary["C++STD"] = "c++11"; } else if (!tryCompileProject("common/c++1z")) { dictionary["C++STD"] = "c++14"; } else { dictionary["C++STD"] = "c++1z"; } } if (dictionary["ATOMIC64"] == "auto") dictionary["ATOMIC64"] = checkAvailability("ATOMIC64") ? "yes" : checkAvailability("ATOMIC64-LIBATOMIC") ? "libatomic" : "no"; // special case: if (!checkAvailability("ATOMICFPTR")) { dictionary["DONE"] = "error"; cout << "ERROR: detected an std::atomic implementation that fails for function pointers." << endl << "Please apply the patch corresponding to your Standard Library vendor, found in" << endl << sourcePath << "/config.tests/common/atomicfptr" << endl; return; } // Style detection if (dictionary["STYLE_WINDOWSXP"] == "auto") dictionary["STYLE_WINDOWSXP"] = checkAvailability("STYLE_WINDOWSXP") ? defaultTo("STYLE_WINDOWSXP") : "no"; if (dictionary["STYLE_WINDOWSVISTA"] == "auto") // Vista style has the same requirements as XP style dictionary["STYLE_WINDOWSVISTA"] = checkAvailability("STYLE_WINDOWSXP") ? defaultTo("STYLE_WINDOWSVISTA") : "no"; // Compression detection if (dictionary["SYSTEM_ZLIB"] == "auto") dictionary["SYSTEM_ZLIB"] = checkAvailability("SYSTEM_ZLIB") ? "yes" : "no"; // PCRE detection if (dictionary["PCRE"] == "auto") dictionary["PCRE"] = checkAvailability("PCRE") ? defaultTo("PCRE") : "qt"; // ICU detection if (dictionary["ICU"] == "auto") dictionary["ICU"] = checkAvailability("ICU") ? "yes" : "no"; // ANGLE detection if (dictionary["ANGLE"] == "auto") { if (dictionary["OPENGL_ES_2"] == "yes" || dictionary["DYNAMICGL"] == "yes") { QString err; dictionary["ANGLE"] = checkAngleAvailability(&err) ? "yes" : "no"; dictionary["ANGLE_FROM"] = "detected"; dictionary["ANGLE_ERR"] = err; } else { dictionary["ANGLE"] = "no"; } } // Image format detection if (dictionary["LIBJPEG"] == "auto") dictionary["LIBJPEG"] = checkAvailability("LIBJPEG") ? defaultTo("LIBJPEG") : "qt"; if (dictionary["LIBPNG"] == "auto") dictionary["LIBPNG"] = checkAvailability("LIBPNG") ? defaultTo("LIBPNG") : "qt"; // SQL detection (not on by default) if (dictionary["SQL_MYSQL"] == "auto") dictionary["SQL_MYSQL"] = checkAvailability("SQL_MYSQL") ? defaultTo("SQL_MYSQL") : "no"; if (dictionary["SQL_ODBC"] == "auto") dictionary["SQL_ODBC"] = checkAvailability("SQL_ODBC") ? defaultTo("SQL_ODBC") : "no"; if (dictionary["SQL_OCI"] == "auto") dictionary["SQL_OCI"] = checkAvailability("SQL_OCI") ? defaultTo("SQL_OCI") : "no"; if (dictionary["SQL_PSQL"] == "auto") dictionary["SQL_PSQL"] = checkAvailability("SQL_PSQL") ? defaultTo("SQL_PSQL") : "no"; if (dictionary["SQL_TDS"] == "auto") dictionary["SQL_TDS"] = checkAvailability("SQL_TDS") ? defaultTo("SQL_TDS") : "no"; if (dictionary["SQL_DB2"] == "auto") dictionary["SQL_DB2"] = checkAvailability("SQL_DB2") ? defaultTo("SQL_DB2") : "no"; if (dictionary["SQL_SQLITE"] == "auto") dictionary["SQL_SQLITE"] = checkAvailability("SQL_SQLITE") ? defaultTo("SQL_SQLITE") : "no"; if (dictionary["SQL_SQLITE_LIB"] == "system") if (!checkAvailability("SQL_SQLITE_LIB")) dictionary["SQL_SQLITE_LIB"] = "no"; if (dictionary["SQL_SQLITE2"] == "auto") dictionary["SQL_SQLITE2"] = checkAvailability("SQL_SQLITE2") ? defaultTo("SQL_SQLITE2") : "no"; if (dictionary["SQL_IBASE"] == "auto") dictionary["SQL_IBASE"] = checkAvailability("SQL_IBASE") ? defaultTo("SQL_IBASE") : "no"; if (dictionary["SSE2"] == "auto") dictionary["SSE2"] = checkAvailability("SSE2") ? "yes" : "no"; if (dictionary["SSE3"] == "auto") dictionary["SSE3"] = checkAvailability("SSE3") ? "yes" : "no"; if (dictionary["SSSE3"] == "auto") dictionary["SSSE3"] = checkAvailability("SSSE3") ? "yes" : "no"; if (dictionary["SSE4_1"] == "auto") dictionary["SSE4_1"] = checkAvailability("SSE4_1") ? "yes" : "no"; if (dictionary["SSE4_2"] == "auto") dictionary["SSE4_2"] = checkAvailability("SSE4_2") ? "yes" : "no"; if (dictionary["AVX"] == "auto") dictionary["AVX"] = checkAvailability("AVX") ? "yes" : "no"; if (dictionary["AVX2"] == "auto") dictionary["AVX2"] = checkAvailability("AVX2") ? "yes" : "no"; if (dictionary["AVX512"] == "auto") dictionary["AVX512"] = checkAvx512Availability(); if (dictionary["NEON"] == "auto") dictionary["NEON"] = checkAvailability("NEON") ? "yes" : "no"; if (dictionary["SSL"] == "auto") { if (platform() == WINDOWS_RT) { dictionary["SSL"] = "yes"; } else { // On Desktop Windows openssl and ssl always have the same value (for now). OpenSSL is // the only backend and if it is available and should be built, that also means that // SSL support in general is enabled. if (dictionary["OPENSSL"] == "auto") dictionary["OPENSSL"] = checkAvailability("OPENSSL") ? "yes" : "no"; dictionary["SSL"] = dictionary["OPENSSL"]; } } if (dictionary["OPENSSL"] == "auto") dictionary["OPENSSL"] = checkAvailability("OPENSSL") ? "yes" : "no"; if (dictionary["LIBPROXY"] == "auto") dictionary["LIBPROXY"] = checkAvailability("LIBPROXY") ? "yes" : "no"; if (dictionary["DBUS"] == "auto") dictionary["DBUS"] = checkAvailability("DBUS") ? "linked" : "runtime"; if (dictionary["QML_DEBUG"] == "auto") dictionary["QML_DEBUG"] = dictionary["QML"] == "yes" ? "yes" : "no"; if (dictionary["WMF_BACKEND"] == "auto") dictionary["WMF_BACKEND"] = checkAvailability("WMF_BACKEND") ? "yes" : "no"; // Detection of IncrediBuild buildconsole if (dictionary["INCREDIBUILD_XGE"] == "auto") dictionary["INCREDIBUILD_XGE"] = checkAvailability("INCREDIBUILD_XGE") ? "yes" : "no"; // Detection of iconv support if (dictionary["QT_ICONV"] == "auto") dictionary["QT_ICONV"] = checkAvailability("ICONV") ? "yes" : "no"; // Detection of evdev support if (dictionary["QT_EVDEV"] == "auto") dictionary["QT_EVDEV"] = checkAvailability("EVDEV") ? "yes" : "no"; // Detection of mtdev support if (dictionary["QT_MTDEV"] == "auto") dictionary["QT_MTDEV"] = checkAvailability("MTDEV") ? "yes" : "no"; // Detection of tslib support if (dictionary["QT_TSLIB"] == "auto") dictionary["QT_TSLIB"] = checkAvailability("TSLIB") ? "yes" : "no"; // Detection of inotify if (dictionary["QT_INOTIFY"] == "auto") dictionary["QT_INOTIFY"] = checkAvailability("INOTIFY") ? "yes" : "no"; // Detection of cups support if (dictionary["QT_CUPS"] == "auto") dictionary["QT_CUPS"] = checkAvailability("CUPS") ? "yes" : "no"; // Detection of -fstack-protector-strong support if (dictionary["STACK_PROTECTOR_STRONG"] == "auto") dictionary["STACK_PROTECTOR_STRONG"] = checkAvailability("STACK_PROTECTOR_STRONG") ? "yes" : "no"; if (platform() == QNX && dictionary["SLOG2"] == "auto") { dictionary["SLOG2"] = checkAvailability("SLOG2") ? "yes" : "no"; } if (platform() == QNX && dictionary["QNX_IMF"] == "auto") { dictionary["QNX_IMF"] = checkAvailability("QNX_IMF") ? "yes" : "no"; } if (dictionary["PPS"] == "auto") { dictionary["PPS"] = checkAvailability("PPS") ? "yes" : "no"; } if (platform() == QNX && dictionary["LGMON"] == "auto") { dictionary["LGMON"] = checkAvailability("LGMON") ? "yes" : "no"; } if (dictionary["SCTP"] == "auto") { dictionary["SCTP"] = checkAvailability("SCTP") ? "yes" : "no"; } if (dictionary["QT_EVENTFD"] == "auto") dictionary["QT_EVENTFD"] = checkAvailability("QT_EVENTFD") ? "yes" : "no"; if (dictionary["FONT_CONFIG"] == "auto") dictionary["FONT_CONFIG"] = checkAvailability("FONT_CONFIG") ? "yes" : "no"; if ((dictionary["FONT_CONFIG"] == "yes") && (dictionary["FREETYPE_FROM"] == "default")) dictionary["FREETYPE"] = "system"; if (dictionary["DOUBLECONVERSION"] == "auto") dictionary["DOUBLECONVERSION"] = checkAvailability("DOUBLECONVERSION") ? "system" : "qt"; if (dictionary["DIRECTWRITE"] == "auto") dictionary["DIRECTWRITE"] = checkAvailability("DIRECTWRITE") ? "yes" : "no"; if (dictionary["DIRECTWRITE"] == "no") dictionary["DIRECTWRITE2"] = "no"; else if (dictionary["DIRECTWRITE2"] == "auto") dictionary["DIRECTWRITE2"] = checkAvailability("DIRECTWRITE2") ? "yes" : "no"; // Mark all unknown "auto" to the default value.. for (QMap::iterator i = dictionary.begin(); i != dictionary.end(); ++i) { if (i.value() == "auto") i.value() = defaultTo(i.key()); } cout << "Done running configuration tests." << endl; } bool Configure::verifyConfiguration() { bool prompt = false; if (dictionary["C++STD"] != "auto" && dictionary["QMAKESPEC"].contains("msvc")) { cout << "WARNING: It is not possible to change the C++ standard edition with MSVC compilers. " "Therefore, the option -c++std " << dictionary["C++STD"] << " was ignored." << endl << endl; dictionary["C++STD"] = "auto"; } if (dictionary["STATIC_RUNTIME"] == "yes" && dictionary["SHARED"] == "yes") { cout << "ERROR: -static-runtime requires -static" << endl << endl; dictionary[ "DONE" ] = "error"; } if (dictionary["SEPARATE_DEBUG_INFO"] == "yes") { if (dictionary[ "SHARED" ] == "no") { cout << "ERROR: -separate-debug-info is incompatible with -static" << endl << endl; dictionary[ "DONE" ] = "error"; } else if (dictionary[ "BUILD" ] != "debug" && dictionary[ "BUILDALL" ] == "no" && dictionary[ "FORCEDEBUGINFO" ] == "no") { cout << "ERROR: -separate-debug-info needs -debug, -debug-and-release, or -force-debug-info" << endl << endl; dictionary[ "DONE" ] = "error"; } else if (dictionary["SEPARATE_DEBUG_INFO"] == "yes" && !checkAvailability("OBJCOPY")) { cout << "ERROR: -separate-debug-info was requested but this binutils does not support it." << endl; dictionary[ "DONE" ] = "error"; } } if (dictionary["SQL_SQLITE_LIB"] == "no" && dictionary["SQL_SQLITE"] != "no") { cout << "WARNING: Configure could not detect the presence of a system SQLite3 lib." << endl << "Configure will therefore continue with the SQLite3 lib bundled with Qt." << endl; dictionary["SQL_SQLITE_LIB"] = "qt"; // Set to Qt's bundled lib an continue prompt = true; } if (dictionary["QMAKESPEC"].endsWith("-g++") && dictionary["SQL_OCI"] != "no") { cout << "WARNING: Qt does not support compiling the Oracle database driver with" << endl << "MinGW, due to lack of such support from Oracle. Consider disabling the" << endl << "Oracle driver, as the current build will most likely fail." << endl; prompt = true; } if (dictionary["DIRECTWRITE"] == "yes" && !checkAvailability("DIRECTWRITE")) { cout << "WARNING: To be able to compile the DirectWrite font engine you will" << endl << "need the Microsoft DirectWrite and Microsoft Direct2D development" << endl << "files such as headers and libraries." << endl; prompt = true; } if (dictionary["DIRECT2D"] == "yes" && !checkAvailability("DIRECT2D")) { cout << "WARNING: To be able to build the Direct2D platform plugin you will" << endl << "need the Microsoft DirectWrite and Microsoft Direct2D development" << endl << "files such as headers and libraries." << endl; prompt = true; } if (dictionary["ANGLE"] == "no") { if (dictionary["ANGLE_FROM"] == "detected") { QString errorMessage = dictionary["ANGLE_ERR"]; cout << "WARNING: The DirectX SDK could not be detected:" << endl << " " << qPrintable(errorMessage) << endl << "Disabling the ANGLE backend." << endl; prompt = true; } if (dictionary["OPENGL_ES_2"] == "yes" && (platform() == WINDOWS || platform() == WINDOWS_RT)) { cout << endl << "WARNING: Using OpenGL ES 2.0 without ANGLE." << endl << "Specify -opengl desktop to use Open GL." << endl << "The build will most likely fail." << endl; prompt = true; } } else if (dictionary["ANGLE_FROM"] == "commandline") { QString errorMessage; if (!checkAngleAvailability(&errorMessage)) { cout << "WARNING: ANGLE specified, but the DirectX SDK could not be detected:" << endl << " " << qPrintable(errorMessage) << endl << "The build will most likely fail." << endl; } } if (dictionary["OPENGL"] == "no" || dictionary["OPENGL_ES_2"] == "no") { if (dictionary.value("XQMAKESPEC").startsWith("winphone") || dictionary.value("XQMAKESPEC").startsWith("winrt")) { cout << "ERROR: Only '-opengl es2' is valid for WinRT." << endl; dictionary[ "DONE" ] = "error"; } } if ((dictionary["FONT_CONFIG"] == "yes") && (dictionary["FREETYPE_FROM"] == "commandline")) { if (dictionary["FREETYPE"] == "yes") { cout << "WARNING: Bundled FreeType can't be used." " FontConfig use requires system FreeType." << endl; dictionary["FREETYPE"] = "system"; dictionary["FREETYPE_FROM"] = "override"; prompt = true; } else if (dictionary["FREETYPE"] == "no") { cout << "WARNING: FreeType can't be disabled." " FontConfig use requires system FreeType." << endl; dictionary["FREETYPE"] = "system"; dictionary["FREETYPE_FROM"] = "override"; prompt = true; } } if (prompt) promptKeyPress(); return true; } void Configure::prepareConfigTests() { // Generate an empty .qmake.cache file for config.tests QDir buildDir(buildPath); bool success = true; if (!buildDir.exists("config.tests")) success = buildDir.mkdir("config.tests"); QString fileName(buildPath + "/config.tests/.qmake.cache"); QFile cacheFile(fileName); success &= cacheFile.open(QIODevice::WriteOnly); cacheFile.close(); if (!success) { cout << "Failed to create file " << qPrintable(QDir::toNativeSeparators(fileName)) << endl; dictionary[ "DONE" ] = "error"; } } void Configure::generateOutputVars() { // Generate variables for output QString build = dictionary[ "BUILD" ]; bool buildAll = (dictionary[ "BUILDALL" ] == "yes"); if (build == "debug") { if (buildAll) qtConfig += "debug_and_release build_all release"; qtConfig += "debug"; } else if (build == "release") { if (buildAll) qtConfig += "debug_and_release build_all debug"; qtConfig += "release"; } if (dictionary[ "RELEASE_TOOLS" ] == "yes") qtConfig += "release_tools"; if (dictionary[ "PCH" ] == "yes") qmakeConfig += "precompile_header"; else qmakeVars += "CONFIG -= precompile_header"; if (dictionary[ "C++STD" ] == "c++11") qtConfig += "c++11"; else if (dictionary[ "C++STD" ] == "c++14") qtConfig += "c++11 c++14"; else if (dictionary[ "C++STD" ] == "c++1z") qtConfig += "c++11 c++14 c++1z"; if (dictionary[ "USE_GOLD_LINKER" ] == "yes") qmakeConfig += "use_gold_linker"; if (dictionary[ "ENABLE_NEW_DTAGS" ] == "yes") qmakeConfig += "enable_new_dtags"; if (dictionary[ "SHARED" ] == "no") qtConfig += "static"; else qtConfig += "shared"; if (dictionary[ "STATIC_RUNTIME" ] == "yes") qtConfig += "static_runtime"; if (dictionary[ "GUI" ] == "no") { qtConfig += "no-gui"; dictionary [ "WIDGETS" ] = "no"; } if (dictionary[ "WIDGETS" ] == "no") qtConfig += "no-widgets"; // Compression -------------------------------------------------- if (dictionary[ "SYSTEM_ZLIB" ] == "yes") qtConfig += "system-zlib"; // PCRE --------------------------------------------------------- if (dictionary[ "PCRE" ] == "qt") qmakeConfig += "pcre"; // ICU --------------------------------------------------------- if (dictionary[ "ICU" ] == "yes") qtConfig += "icu"; // ANGLE -------------------------------------------------------- if (dictionary[ "ANGLE" ] != "no") { qtConfig += "angle"; } // Dynamic OpenGL loading --------------------------------------- if (dictionary[ "DYNAMICGL" ] != "no") { qtConfig += "dynamicgl"; } // Image formates ----------------------------------------------- if (dictionary[ "GIF" ] == "yes") qtConfig += "gif"; if (dictionary[ "JPEG" ] == "yes") qtConfig += "jpeg"; if (dictionary[ "LIBJPEG" ] == "system") qtConfig += "system-jpeg"; if (dictionary[ "PNG" ] == "yes") qtConfig += "png"; if (dictionary[ "LIBPNG" ] == "system") qtConfig += "system-png"; // Double conversion ----------------------------------------------- if (dictionary[ "DOUBLECONVERSION" ] != "no") qtConfig += "doubleconversion"; if (dictionary[ "DOUBLECONVERSION" ] == "system") qtConfig += "system-doubleconversion"; // Text rendering -------------------------------------------------- if (dictionary[ "FREETYPE" ] != "no") qtConfig += "freetype"; if (dictionary[ "FREETYPE" ] == "system") qtConfig += "system-freetype"; if (dictionary[ "HARFBUZZ" ] != "no") qtConfig += "harfbuzz"; if (dictionary[ "HARFBUZZ" ] == "system") qtConfig += "system-harfbuzz"; // Styles ------------------------------------------------------- if (dictionary[ "STYLE_WINDOWS" ] == "yes") qmakeStyles += "windows"; if (dictionary[ "STYLE_FUSION" ] == "yes") qmakeStyles += "fusion"; if (dictionary[ "STYLE_WINDOWSXP" ] == "yes") qmakeStyles += "windowsxp"; if (dictionary[ "STYLE_WINDOWSVISTA" ] == "yes") qmakeStyles += "windowsvista"; if (dictionary[ "STYLE_ANDROID" ] == "yes") qmakeStyles += "android"; // Databases ---------------------------------------------------- if (dictionary[ "SQL_MYSQL" ] == "yes") qmakeSql += "mysql"; if (dictionary[ "SQL_ODBC" ] == "yes") qmakeSql += "odbc"; if (dictionary[ "SQL_OCI" ] == "yes") qmakeSql += "oci"; if (dictionary[ "SQL_PSQL" ] == "yes") qmakeSql += "psql"; if (dictionary[ "SQL_TDS" ] == "yes") qmakeSql += "tds"; if (dictionary[ "SQL_DB2" ] == "yes") qmakeSql += "db2"; if (dictionary[ "SQL_SQLITE2" ] == "yes") qmakeSql += "sqlite2"; if (dictionary[ "SQL_IBASE" ] == "yes") qmakeSql += "ibase"; if (dictionary[ "SQL_SQLITE" ] == "yes") qmakeSql += "sqlite"; if (dictionary[ "SQL_SQLITE_LIB" ] == "system") qmakeConfig += "system-sqlite"; // Other options ------------------------------------------------ if (dictionary[ "BUILDALL" ] == "yes") { qtConfig += "build_all"; } if (dictionary[ "SEPARATE_DEBUG_INFO" ] == "yes") qtConfig += "separate_debug_info"; if (dictionary[ "FORCEDEBUGINFO" ] == "yes") qmakeConfig += "force_debug_info"; qmakeConfig += dictionary[ "BUILD" ]; if (buildParts.isEmpty()) { buildParts = defaultBuildParts; if (dictionary["BUILDDEV"] == "yes") buildParts += "tests"; } while (!nobuildParts.isEmpty()) buildParts.removeAll(nobuildParts.takeFirst()); if (!buildParts.contains("libs")) buildParts += "libs"; buildParts.removeDuplicates(); if (dictionary[ "COMPILE_EXAMPLES" ] == "yes") qmakeConfig += "compile_examples"; if (dictionary["MSVC_MP"] == "yes") qmakeConfig += "msvc_mp"; if (dictionary["ATOMIC64"] == "libatomic") qmakeConfig += "atomic64-libatomic"; if (dictionary[ "ACCESSIBILITY" ] == "yes") qtConfig += "accessibility"; if (!qmakeLibs.isEmpty()) qmakeVars += "EXTRA_LIBDIR += " + formatPaths(qmakeLibs); if (!dictionary["QMAKE_LIBS_SQLITE"].isEmpty()) qmakeVars += "QMAKE_LIBS_SQLITE += " + dictionary["QMAKE_LIBS_SQLITE"]; if (dictionary[ "OPENGL" ] == "yes") qtConfig += "opengl"; if (dictionary["OPENGL_ES_2"] == "yes") { qtConfig += "opengles2"; qtConfig += "egl"; } if (dictionary[ "SSL" ] == "yes") qtConfig += "ssl"; if (dictionary[ "OPENSSL" ] == "yes") qtConfig += "openssl"; else if (dictionary[ "OPENSSL" ] == "linked") qtConfig += "openssl-linked"; if (dictionary[ "LIBPROXY" ] == "yes") qtConfig += "libproxy"; if (dictionary[ "DBUS" ] == "runtime") qtConfig += "dbus"; else if (dictionary[ "DBUS" ] == "linked") qtConfig += "dbus dbus-linked"; if (dictionary["QML_DEBUG"] == "no") qtConfig += "no-qml-debug"; if (dictionary["WMF_BACKEND"] == "yes") qtConfig += "wmf-backend"; if (dictionary["DIRECTWRITE"] == "yes") qtConfig += "directwrite"; if (dictionary["DIRECTWRITE2"] == "yes") qtConfig += "directwrite2"; if (dictionary["DIRECT2D"] == "yes") qtConfig += "direct2d"; if (dictionary["NIS"] == "yes") qtConfig += "nis"; if (dictionary["QT_CUPS"] == "yes") qtConfig += "cups"; if (dictionary["QT_ICONV"] != "no") qtConfig += "iconv"; if (dictionary["QT_ICONV"] == "sun") qtConfig += "sun-libiconv"; else if (dictionary["QT_ICONV"] == "gnu") qtConfig += "gnu-libiconv"; if (dictionary["QT_EVDEV"] == "yes") qtConfig += "evdev"; if (dictionary["QT_MTDEV"] == "yes") qtConfig += "mtdev"; if (dictionary[ "QT_TSLIB" ] == "yes") qtConfig += "tslib"; if (dictionary["QT_INOTIFY"] == "yes") qtConfig += "inotify"; if (dictionary["QT_EVENTFD"] == "yes") qtConfig += "eventfd"; if (dictionary["FONT_CONFIG"] == "yes") { qtConfig += "fontconfig"; qmakeVars += "QMAKE_CFLAGS_FONTCONFIG ="; qmakeVars += "QMAKE_LIBS_FONTCONFIG = -lfreetype -lfontconfig"; } if (dictionary["QT_GLIB"] == "yes") qtConfig += "glib"; if (dictionary["STACK_PROTECTOR_STRONG"] == "yes") qtConfig += "stack-protector-strong"; if (dictionary["REDUCE_EXPORTS"] == "yes") qtConfig += "reduce_exports"; if (!dictionary["POLL"].isEmpty()) qtConfig += "poll_" + dictionary["POLL"]; // We currently have no switch for QtConcurrent, so add it unconditionally. qtConfig += "concurrent"; if (dictionary[ "SYSTEM_PROXIES" ] == "yes") qtConfig += "system-proxies"; if (dictionary[ "SCTP" ] == "yes") qtConfig += "sctp"; if (dictionary.contains("XQMAKESPEC") && (dictionary["QMAKESPEC"] != dictionary["XQMAKESPEC"])) { qmakeConfig += "cross_compile"; dictionary["CROSS_COMPILE"] = "yes"; } // Directories and settings for .qmake.cache -------------------- if (dictionary.contains("XQMAKESPEC") && dictionary[ "XQMAKESPEC" ].startsWith("linux")) qtConfig += "rpath"; if (!qmakeDefines.isEmpty()) qmakeVars += QString("EXTRA_DEFINES += ") + qmakeDefines.join(' '); if (!qmakeIncludes.isEmpty()) qmakeVars += QString("EXTRA_INCLUDEPATH += ") + formatPaths(qmakeIncludes); if (!opensslLibs.isEmpty()) qmakeVars += opensslLibs; if (dictionary[ "OPENSSL" ] == "linked") { if (!opensslLibsDebug.isEmpty() || !opensslLibsRelease.isEmpty()) { if (opensslLibsDebug.isEmpty() || opensslLibsRelease.isEmpty()) { cout << "Error: either both or none of OPENSSL_LIBS_DEBUG/_RELEASE must be defined." << endl; exit(1); } qmakeVars += opensslLibsDebug; qmakeVars += opensslLibsRelease; } else if (opensslLibs.isEmpty()) { qmakeVars += QString("OPENSSL_LIBS = -lssleay32 -llibeay32"); } if (!opensslPath.isEmpty()) { qmakeVars += QString("OPENSSL_CFLAGS += -I%1/include").arg(opensslPath); qmakeVars += QString("OPENSSL_LIBS += -L%1/lib").arg(opensslPath); } } if (dictionary[ "DBUS" ] == "linked") { if (!dbusPath.isEmpty()) { qmakeVars += QString("QMAKE_CFLAGS_DBUS = -I%1/include").arg(dbusPath); qmakeVars += QString("QMAKE_LIBS_DBUS = -L%1/lib").arg(dbusPath); if (dbusHostPath.isEmpty()) qmakeVars += QString("QT_HOST_CFLAGS_DBUS = -I%1/include").arg(dbusPath); } if (!dbusHostPath.isEmpty()) qmakeVars += QString("QT_HOST_CFLAGS_DBUS = -I%1/include").arg(dbusHostPath); } if (dictionary[ "SQL_MYSQL" ] != "no" && !mysqlPath.isEmpty()) { qmakeVars += QString("QMAKE_CFLAGS_MYSQL = -I%1/include").arg(mysqlPath); qmakeVars += QString("QMAKE_LIBS_MYSQL = -L%1/lib").arg(mysqlPath); } if (!psqlLibs.isEmpty()) qmakeVars += QString("QMAKE_LIBS_PSQL=") + psqlLibs.section("=", 1); if (!zlibLibs.isEmpty()) qmakeVars += zlibLibs; { QStringList lflagsTDS; if (!sybase.isEmpty()) lflagsTDS += QString("-L") + formatPath(sybase.section("=", 1) + "/lib"); if (!sybaseLibs.isEmpty()) lflagsTDS += sybaseLibs.section("=", 1); if (!lflagsTDS.isEmpty()) qmakeVars += QString("QMAKE_LIBS_TDS=") + lflagsTDS.join(' '); } if (!qmakeSql.isEmpty()) qmakeVars += QString("sql-drivers += ") + qmakeSql.join(' '); if (!qmakeStyles.isEmpty()) qmakeVars += QString("styles += ") + qmakeStyles.join(' '); if (!dictionary[ "QMAKESPEC" ].length()) { cout << "Configure could not detect your compiler. QMAKESPEC must either" << endl << "be defined as an environment variable, or specified as an" << endl << "argument with -platform" << endl; QStringList winPlatforms; QDir mkspecsDir(sourcePath + "/mkspecs"); const QFileInfoList &specsList = mkspecsDir.entryInfoList(); for (int i = 0; i < specsList.size(); ++i) { const QFileInfo &fi = specsList.at(i); if (fi.fileName().left(5) == "win32") { winPlatforms += fi.fileName(); } } cout << "Available platforms are: " << qPrintable(winPlatforms.join(", ")) << endl; dictionary[ "DONE" ] = "error"; } } void Configure::generateCachefile() { // Generate qmodule.pri, which is loaded only by Qt modules { FileWriter moduleStream(buildPath + "/mkspecs/qmodule.pri"); moduleStream << "QT_BUILD_PARTS += " << buildParts.join(' ') << endl; if (!skipModules.isEmpty()) moduleStream << "QT_SKIP_MODULES += " << skipModules.join(' ') << endl; moduleStream << endl; moduleStream << "host_build {" << endl; moduleStream << " QT_CPU_FEATURES." << dictionary["QT_HOST_ARCH"] << " = " << dictionary["QT_HOST_CPU_FEATURES"] << endl; moduleStream << "} else {" << endl; moduleStream << " QT_CPU_FEATURES." << dictionary["QT_ARCH"] << " = " << dictionary["QT_CPU_FEATURES"] << endl; moduleStream << "}" << endl; moduleStream << "QT_COORD_TYPE += " << dictionary["QREAL"] << endl; if (dictionary["QT_XKBCOMMON"] == "no") moduleStream << "DEFINES += QT_NO_XKBCOMMON" << endl; moduleStream << "CONFIG += " << qmakeConfig.join(' '); if (dictionary[ "SSE2" ] == "yes") moduleStream << " sse2"; if (dictionary[ "SSE3" ] == "yes") moduleStream << " sse3"; if (dictionary[ "SSSE3" ] == "yes") moduleStream << " ssse3"; if (dictionary[ "SSE4_1" ] == "yes") moduleStream << " sse4_1"; if (dictionary[ "SSE4_2" ] == "yes") moduleStream << " sse4_2"; if (dictionary[ "AVX" ] == "yes") moduleStream << " avx"; if (dictionary[ "AVX2" ] == "yes") moduleStream << " avx2"; if (!dictionary[ "AVX512" ].isEmpty()) moduleStream << ' ' << dictionary[ "AVX512" ]; if (dictionary[ "NEON" ] == "yes") moduleStream << " neon"; if (dictionary[ "LARGE_FILE" ] == "yes") moduleStream << " largefile"; if (dictionary[ "STRIP" ] == "no") moduleStream << " nostrip"; if (dictionary[ "LTCG" ] == "yes") moduleStream << " ltcg"; moduleStream << endl; for (QStringList::Iterator var = qmakeVars.begin(); var != qmakeVars.end(); ++var) moduleStream << (*var) << endl; if (!moduleStream.flush()) dictionary[ "DONE" ] = "error"; } } void Configure::addSysroot(QString *command) { const QString &sysroot = dictionary["CFG_SYSROOT"]; if (!sysroot.isEmpty() && dictionary["CFG_GCC_SYSROOT"] == "yes") { command->append(" QMAKE_LFLAGS+=--sysroot=" + sysroot); command->append(" QMAKE_CXXFLAGS+=--sysroot=" + sysroot); } } struct ArchData { bool isHost; const char *qmakespec; const char *key; const char *subarchKey; const char *type; ArchData() {} ArchData(bool h, const char *t, const char *qm, const char *k, const char *sak) : isHost(h), qmakespec(qm), key(k), subarchKey(sak), type(t) {} }; /* Runs qmake on config.tests/arch/arch.pro, which will detect the target arch for the compiler we are using */ void Configure::detectArch() { QString oldpwd = QDir::currentPath(); QString newpwd = QString("%1/config.tests/arch").arg(buildPath); if (!QDir().exists(newpwd) && !QDir().mkpath(newpwd)) { cout << "Failed to create directory " << qPrintable(QDir::toNativeSeparators(newpwd)) << endl; dictionary["DONE"] = "error"; return; } if (!QDir::setCurrent(newpwd)) { cout << "Failed to change working directory to " << qPrintable(QDir::toNativeSeparators(newpwd)) << endl; dictionary["DONE"] = "error"; return; } QVector qmakespecs; if (dictionary.contains("XQMAKESPEC")) qmakespecs << ArchData(false, "target", "XQMAKESPEC", "QT_ARCH", "QT_CPU_FEATURES"); qmakespecs << ArchData(true, "host", "QMAKESPEC", "QT_HOST_ARCH", "QT_HOST_CPU_FEATURES"); for (int i = 0; i < qmakespecs.count(); ++i) { const ArchData &data = qmakespecs.at(i); QString qmakespec = dictionary.value(data.qmakespec); QString key = data.key; QString subarchKey = data.subarchKey; // run qmake QString command = QString("%1 -spec %2 %3") .arg(QDir::toNativeSeparators(QDir(newpwd).relativeFilePath(buildPath + "/bin/qmake.exe")), QDir::toNativeSeparators(qmakespec), QDir::toNativeSeparators(sourcePath + "/config.tests/arch/arch" + (data.isHost ? "_host" : "") + ".pro")); if (!data.isHost) { if (qmakespec.startsWith("winrt") || qmakespec.startsWith("winphone")) command.append(" QMAKE_LFLAGS+=/ENTRY:main"); addSysroot(&command); } int returnValue = 0; Environment::execute(command, &returnValue); if (returnValue != 0) { cout << "QMake failed!" << endl; dictionary["DONE"] = "error"; return; } // compile command = dictionary[ "MAKE" ]; if (command.contains("nmake") || command.contains("jom")) command += " /NOLOGO"; command += " -s"; Environment::execute(command); // find the executable that was generated QString arch_exe; if (qmakespec.startsWith("android")) { arch_exe = "libarch.so"; } else { arch_exe = "arch.exe"; } QFile exe(arch_exe); if (!exe.open(QFile::ReadOnly)) { // no Text, this is binary exe.setFileName("arch"); if (!exe.open(QFile::ReadOnly)) { cout << "Could not find output file '" << qPrintable(arch_exe) << "' or 'arch' in " << qPrintable(newpwd) << " : " << qPrintable(exe.errorString()) << endl; dictionary["DONE"] = "error"; return; } } QByteArray exeContents = exe.readAll(); exe.close(); static const char archMagic[] = "==Qt=magic=Qt== Architecture:"; int magicPos = exeContents.indexOf(archMagic); if (magicPos == -1) { cout << "Internal error, could not find the architecture of the " << data.type << " executable" << endl; dictionary["DONE"] = "error"; return; } //cout << "Found magic at offset 0x" << hex << magicPos << endl; // the conversion from QByteArray will stop at the ending NUL anyway QString arch = QString::fromLatin1(exeContents.constData() + magicPos + sizeof(archMagic) - 1); dictionary[key] = arch; static const char subarchMagic[] = "==Qt=magic=Qt== Sub-architecture:"; magicPos = exeContents.indexOf(subarchMagic); if (magicPos == -1) { cout << "Internal error, could not find the sub-architecture of the " << data.type << " executable" << endl; dictionary["DONE"] = "error"; return; } QString subarch = QString::fromLatin1(exeContents.constData() + magicPos + sizeof(subarchMagic) - 1); dictionary[subarchKey] = subarch; //cout << "Detected arch '" << qPrintable(arch) << "'\n"; //cout << "Detected sub-arch '" << qPrintable(subarch) << "'\n"; // clean up Environment::execute(command + " distclean"); } if (!dictionary.contains("QT_HOST_ARCH")) dictionary["QT_HOST_ARCH"] = "unknown"; if (!dictionary.contains("QT_ARCH")) { dictionary["QT_ARCH"] = dictionary["QT_HOST_ARCH"]; dictionary["QT_CPU_FEATURES"] = dictionary["QT_HOST_CPU_FEATURES"]; } QDir::setCurrent(oldpwd); } bool Configure::tryCompileProject(const QString &projectPath, const QString &extraOptions, bool distClean) { QString oldpwd = QDir::currentPath(); QString newpwd = QString("%1/config.tests/%2").arg(buildPath, projectPath); if (!QDir().exists(newpwd) && !QDir().mkpath(newpwd)) { cout << "Failed to create directory " << qPrintable(QDir::toNativeSeparators(newpwd)) << endl; dictionary["DONE"] = "error"; return false; } if (!QDir::setCurrent(newpwd)) { cout << "Failed to change working directory to " << qPrintable(QDir::toNativeSeparators(newpwd)) << endl; dictionary["DONE"] = "error"; return false; } // run qmake QString command = QString("%1 %2 %3") .arg(QDir::toNativeSeparators(QDir(newpwd).relativeFilePath(buildPath + "/bin/qmake.exe")), QDir::toNativeSeparators(sourcePath + "/config.tests/" + projectPath), extraOptions); if (dictionary.contains("XQMAKESPEC")) { const QString qmakespec = dictionary["XQMAKESPEC"]; if (qmakespec.startsWith("winrt") || qmakespec.startsWith("winphone")) command.append(" QMAKE_LFLAGS+=/ENTRY:main"); addSysroot(&command); } if (verbose) cout << qPrintable(command) << endl; else command += " 2>&1"; int code = 0; QString output = Environment::execute(command, &code); //cout << output << endl; if (code == 0) { // compile command = dictionary[ "MAKE" ]; if (command.contains("nmake") || command.contains("jom")) command += " /NOLOGO"; if (verbose) cout << qPrintable(command) << endl; else command += " -s 2>&1"; output = Environment::execute(command, &code); //cout << output << endl; // clean up if (distClean) Environment::execute(command + " distclean 2>&1"); } QDir::setCurrent(oldpwd); return code == 0; } bool Configure::compilerSupportsFlag(const QString &compilerAndArgs) { QFile file("conftest.cpp"); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { cout << "could not open temp file for writing" << endl; return false; } if (!file.write("int main() { return 0; }\r\n")) { cout << "could not write to temp file" << endl; return false; } file.close(); // compilerAndArgs contains compiler because there is no way to query it QString command = compilerAndArgs + " -o conftest-out.o conftest.cpp"; int code = 0; QString output = Environment::execute(command, &code); file.remove(); QFile::remove("conftest-out.o"); return code == 0; } void Configure::generateQDevicePri() { FileWriter deviceStream(buildPath + "/mkspecs/qdevice.pri"); if (dictionary.contains("DEVICE_OPTION")) { const QString devoptionlist = dictionary["DEVICE_OPTION"]; const QStringList optionlist = devoptionlist.split(QStringLiteral("\n")); foreach (const QString &entry, optionlist) deviceStream << entry << "\n"; } if (dictionary.contains("ANDROID_SDK_ROOT") && dictionary.contains("ANDROID_NDK_ROOT")) { deviceStream << "android_install {" << endl; deviceStream << " DEFAULT_ANDROID_SDK_ROOT = " << formatPath(dictionary["ANDROID_SDK_ROOT"]) << endl; deviceStream << " DEFAULT_ANDROID_NDK_ROOT = " << formatPath(dictionary["ANDROID_NDK_ROOT"]) << endl; if (dictionary.contains("ANDROID_HOST")) deviceStream << " DEFAULT_ANDROID_NDK_HOST = " << dictionary["ANDROID_HOST"] << endl; else if (QSysInfo::WordSize == 64) deviceStream << " DEFAULT_ANDROID_NDK_HOST = windows-x86_64" << endl; else deviceStream << " DEFAULT_ANDROID_NDK_HOST = windows" << endl; QString android_arch(dictionary.contains("ANDROID_TARGET_ARCH") ? dictionary["ANDROID_TARGET_ARCH"] : QString("armeabi-v7a")); QString android_tc_vers(dictionary.contains("ANDROID_NDK_TOOLCHAIN_VERSION") ? dictionary["ANDROID_NDK_TOOLCHAIN_VERSION"] : QString("4.9")); bool targetIs64Bit = android_arch == QString("arm64-v8a") || android_arch == QString("x86_64") || android_arch == QString("mips64"); QString android_platform(dictionary.contains("ANDROID_PLATFORM") ? dictionary["ANDROID_PLATFORM"] : (targetIs64Bit ? QString("android-21") : QString("android-9"))); deviceStream << " DEFAULT_ANDROID_PLATFORM = " << android_platform << endl; deviceStream << " DEFAULT_ANDROID_TARGET_ARCH = " << android_arch << endl; deviceStream << " DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION = " << android_tc_vers << endl; deviceStream << "}" << endl; } if (!deviceStream.flush()) dictionary[ "DONE" ] = "error"; } void Configure::generateQConfigPri() { // Generate qconfig.pri { FileWriter configStream(buildPath + "/mkspecs/qconfig.pri"); configStream << "CONFIG+= "; configStream << dictionary[ "BUILD" ]; configStream << (dictionary[ "SHARED" ] == "no" ? " static" : " shared"); if (dictionary["STATIC_RUNTIME"] == "yes") configStream << " static_runtime"; if (dictionary[ "RTTI" ] == "yes") configStream << " rtti"; if (dictionary["INCREDIBUILD_XGE"] == "yes") configStream << " incredibuild_xge"; if (dictionary["PLUGIN_MANIFESTS"] == "no") configStream << " no_plugin_manifest"; if (dictionary["CROSS_COMPILE"] == "yes") configStream << " cross_compile"; if (dictionary[ "SLOG2" ] == "yes") configStream << " slog2"; if (dictionary[ "QNX_IMF" ] == "yes") configStream << " qqnx_imf"; if (dictionary[ "PPS" ] == "yes") configStream << " qqnx_pps"; if (dictionary[ "LGMON" ] == "yes") configStream << " lgmon"; if (dictionary["ANDROID_STYLE_ASSETS"] == "yes") configStream << " android-style-assets"; configStream << endl; configStream << "host_build {" << endl; configStream << " QT_ARCH = " << dictionary["QT_HOST_ARCH"] << endl; configStream << " QT_TARGET_ARCH = " << dictionary["QT_ARCH"] << endl; configStream << "} else {" << endl; configStream << " QT_ARCH = " << dictionary["QT_ARCH"] << endl; configStream << "}" << endl; configStream << "QT_CONFIG += " << qtConfig.join(' ') << endl; configStream << "#versioning " << endl << "QT_VERSION = " << dictionary["VERSION"] << endl << "QT_MAJOR_VERSION = " << dictionary["VERSION_MAJOR"] << endl << "QT_MINOR_VERSION = " << dictionary["VERSION_MINOR"] << endl << "QT_PATCH_VERSION = " << dictionary["VERSION_PATCH"] << endl; configStream << endl << "QT_EDITION = " << dictionary["EDITION"] << endl; if (dictionary["EDITION"] != "OpenSource" && dictionary["EDITION"] != "Preview") { configStream << "QT_LICHECK = " << dictionary["LICHECK"] << endl; configStream << "QT_RELEASE_DATE = " << dictionary["RELEASEDATE"] << endl; } if (!dictionary["CFG_SYSROOT"].isEmpty() && dictionary["CFG_GCC_SYSROOT"] == "yes") { configStream << endl << "# sysroot" << endl << "!host_build {" << endl << " QMAKE_CFLAGS += --sysroot=$$[QT_SYSROOT]" << endl << " QMAKE_CXXFLAGS += --sysroot=$$[QT_SYSROOT]" << endl << " QMAKE_LFLAGS += --sysroot=$$[QT_SYSROOT]" << endl << "}" << endl; } if (!dictionary["QT_LIBINFIX"].isEmpty()) configStream << "QT_LIBINFIX = " << dictionary["QT_LIBINFIX"] << endl; if (!dictionary["QT_NAMESPACE"].isEmpty()) configStream << "#namespaces" << endl << "QT_NAMESPACE = " << dictionary["QT_NAMESPACE"] << endl; if (dictionary[ "SHARED" ] == "no") configStream << "QT_DEFAULT_QPA_PLUGIN = q" << qpaPlatformName() << endl; if (!dictionary["QT_GCC_MAJOR_VERSION"].isEmpty()) { configStream << "QT_GCC_MAJOR_VERSION = " << dictionary["QT_GCC_MAJOR_VERSION"] << endl << "QT_GCC_MINOR_VERSION = " << dictionary["QT_GCC_MINOR_VERSION"] << endl << "QT_GCC_PATCH_VERSION = " << dictionary["QT_GCC_PATCH_VERSION"] << endl; } if (!configStream.flush()) dictionary[ "DONE" ] = "error"; } } QString Configure::addDefine(QString def) { QString result, defNeg, defD = def; defD.replace(QRegExp("=.*"), ""); def.replace(QRegExp("="), " "); if (def.startsWith("QT_NO_")) { defNeg = defD; defNeg.replace("QT_NO_", "QT_"); } else if (def.startsWith("QT_")) { defNeg = defD; defNeg.replace("QT_", "QT_NO_"); } if (defNeg.isEmpty()) { result = "#ifndef $DEFD\n" "# define $DEF\n" "#endif\n\n"; } else { result = "#if defined($DEFD) && defined($DEFNEG)\n" "# undef $DEFD\n" "#elif !defined($DEFD)\n" "# define $DEF\n" "#endif\n\n"; } result.replace("$DEFNEG", defNeg); result.replace("$DEFD", defD); result.replace("$DEF", def); return result; } void Configure::generateConfigfiles() { { FileWriter tmpStream(buildPath + "/src/corelib/global/qconfig.h"); tmpStream << "#define QT_VERSION_MAJOR " << dictionary["VERSION_MAJOR"] << endl << "#define QT_VERSION_MINOR " << dictionary["VERSION_MINOR"] << endl << "#define QT_VERSION_PATCH " << dictionary["VERSION_PATCH"] << endl << "#define QT_VERSION_STR \"" << dictionary["VERSION"] << "\"\n" << endl; tmpStream << endl; if (dictionary[ "SHARED" ] == "no") { tmpStream << "/* Qt was configured for a static build */" << endl << "#if !defined(QT_SHARED) && !defined(QT_STATIC)" << endl << "# define QT_STATIC" << endl << "#endif" << endl << endl; } tmpStream << "/* License information */" << endl; tmpStream << "#define QT_PRODUCT_LICENSEE \"" << dictionary[ "LICENSEE" ] << "\"" << endl; tmpStream << "#define QT_PRODUCT_LICENSE \"" << dictionary[ "EDITION" ] << "\"" << endl; tmpStream << endl; if (dictionary["BUILDDEV"] == "yes") { tmpStream << "/* Used for example to export symbols for the certain autotests*/" << endl; tmpStream << "#define QT_BUILD_INTERNAL" << endl; tmpStream << endl; } tmpStream << endl << "// Compiler sub-arch support" << endl; if (dictionary[ "SSE2" ] == "yes") tmpStream << "#define QT_COMPILER_SUPPORTS_SSE2 1" << endl; if (dictionary[ "SSE3" ] == "yes") tmpStream << "#define QT_COMPILER_SUPPORTS_SSE3 1" << endl; if (dictionary[ "SSSE3" ] == "yes") tmpStream << "#define QT_COMPILER_SUPPORTS_SSSE3 1" << endl; if (dictionary[ "SSE4_1" ] == "yes") tmpStream << "#define QT_COMPILER_SUPPORTS_SSE4_1 1" << endl; if (dictionary[ "SSE4_2" ] == "yes") tmpStream << "#define QT_COMPILER_SUPPORTS_SSE4_2 1" << endl; if (dictionary[ "AVX" ] == "yes") tmpStream << "#define QT_COMPILER_SUPPORTS_AVX 1" << endl; if (dictionary[ "AVX2" ] == "yes") tmpStream << "#define QT_COMPILER_SUPPORTS_AVX2 1" << endl; foreach (const QString &avx512feature, dictionary[ "AVX512" ].split(' ', QString::SkipEmptyParts)) tmpStream << "#define QT_COMPILER_SUPPRTS_" << avx512feature.toUpper() << " 1" << endl; if (dictionary["QREAL"] != "double") { tmpStream << "#define QT_COORD_TYPE " << dictionary["QREAL"] << endl; tmpStream << "#define QT_COORD_TYPE_STRING " << dictionary["QREAL_STRING"] << endl; } tmpStream << endl << "// Compile time features" << endl; QStringList qconfigList; if (dictionary["PNG"] != "yes") qconfigList += "QT_NO_IMAGEFORMAT_PNG"; if (dictionary["ACCESSIBILITY"] == "no") qconfigList += "QT_NO_ACCESSIBILITY"; if (dictionary["WIDGETS"] == "no") qconfigList += "QT_NO_WIDGETS"; if (dictionary["GUI"] == "no") qconfigList += "QT_NO_GUI"; if (dictionary["OPENGL"] == "no") qconfigList += "QT_NO_OPENGL"; if (dictionary["SSL"] == "no") qconfigList += "QT_NO_SSL"; if (dictionary["OPENSSL"] == "no") qconfigList += "QT_NO_OPENSSL"; if (dictionary["OPENSSL"] == "linked") qconfigList += "QT_LINKED_OPENSSL"; if (dictionary["DBUS"] == "no") qconfigList += "QT_NO_DBUS"; if (dictionary["FREETYPE"] == "no") qconfigList += "QT_NO_FREETYPE"; if (dictionary["HARFBUZZ"] == "no") qconfigList += "QT_NO_HARFBUZZ"; if (dictionary["OPENGL_ES_2"] == "yes") qconfigList += "QT_OPENGL_ES"; if (dictionary["OPENGL_ES_2"] == "yes") qconfigList += "QT_OPENGL_ES_2"; if (dictionary["DYNAMICGL"] == "yes") qconfigList += "QT_OPENGL_DYNAMIC"; if (dictionary["POSIX_IPC"] == "yes") qconfigList += "QT_POSIX_IPC"; else if ((platform() != ANDROID) && (platform() != WINDOWS) && (platform() != WINDOWS_RT)) qconfigList << "QT_NO_SYSTEMSEMAPHORE" << "QT_NO_SHAREDMEMORY"; if (dictionary["FONT_CONFIG"] == "no") qconfigList += "QT_NO_FONTCONFIG"; if (dictionary["NIS"] == "yes") qconfigList += "QT_NIS"; else qconfigList += "QT_NO_NIS"; if (dictionary["SCTP"] == "no") qconfigList += "QT_NO_SCTP"; if (dictionary["LARGE_FILE"] == "yes") qconfigList += "QT_LARGEFILE_SUPPORT=64"; if (dictionary["QT_CUPS"] == "no") qconfigList += "QT_NO_CUPS"; if (dictionary["QT_ICONV"] == "no") qconfigList += "QT_NO_ICONV"; if (dictionary["QT_EVDEV"] == "no") qconfigList += "QT_NO_EVDEV"; if (dictionary["QT_MTDEV"] == "no") qconfigList += "QT_NO_MTDEV"; if (dictionary["QT_TSLIB"] == "no") qconfigList += "QT_NO_TSLIB"; if (dictionary["QT_GLIB"] == "no") qconfigList += "QT_NO_GLIB"; if (dictionary["QT_INOTIFY"] == "no") qconfigList += "QT_NO_INOTIFY"; if (dictionary["QT_EVENTFD"] == "no") qconfigList += "QT_NO_EVENTFD"; if (dictionary["ATOMIC64"] == "no") qconfigList += "QT_NO_STD_ATOMIC64"; if (dictionary["REDUCE_EXPORTS"] == "yes") qconfigList += "QT_VISIBILITY_AVAILABLE"; if (dictionary["REDUCE_RELOCATIONS"] == "yes") qconfigList += "QT_REDUCE_RELOCATIONS"; if (dictionary["QT_GETIFADDRS"] == "no") qconfigList += "QT_NO_GETIFADDRS"; qconfigList.sort(); for (int i = 0; i < qconfigList.count(); ++i) tmpStream << addDefine(qconfigList.at(i)); tmpStream<<"#define QT_QPA_DEFAULT_PLATFORM_NAME \"" << qpaPlatformName() << "\""<" : "SSE2") << (dictionary[ "SSE3" ] == "no" ? "" : " SSE3") << (dictionary[ "SSSE3" ] == "no" ? "" : " SSSE3") << (dictionary[ "SSE4_1" ] == "no" ? "" : " SSE4.1") << (dictionary[ "SSE4_2" ] == "no" ? "" : " SSE4.2") << endl; sout << "AVX support................." << (dictionary[ "AVX" ] == "no" ? "" : "AVX") << (dictionary[ "AVX2" ] == "no" ? "" : " AVX2") << endl; sout << "AVX512 support.............." << (dictionary[ "AVX512" ].isEmpty() ? QString("") : dictionary[ "AVX512" ].toUpper()) << endl; sout << "NEON support................" << dictionary[ "NEON" ] << endl; sout << "OpenGL support.............." << dictionary[ "OPENGL" ] << endl; sout << "NIS support................." << dictionary[ "NIS" ] << endl; sout << "Iconv support..............." << dictionary[ "QT_ICONV" ] << endl; sout << "Evdev support..............." << dictionary[ "QT_EVDEV" ] << endl; sout << "Mtdev support..............." << dictionary[ "QT_MTDEV" ] << endl; sout << "Inotify support............." << dictionary[ "QT_INOTIFY" ] << endl; sout << "eventfd(7) support.........." << dictionary[ "QT_EVENTFD" ] << endl; sout << "Glib support................" << dictionary[ "QT_GLIB" ] << endl; sout << "CUPS support................" << dictionary[ "QT_CUPS" ] << endl; sout << "SSL support................." << dictionary[ "SSL" ] << endl; sout << "OpenSSL support............." << dictionary[ "OPENSSL" ] << endl; sout << "libproxy support............" << dictionary[ "LIBPROXY" ] << endl; sout << "Qt D-Bus support............" << dictionary[ "DBUS" ] << endl; sout << "Qt Widgets module support..." << dictionary[ "WIDGETS" ] << endl; sout << "Qt GUI module support......." << dictionary[ "GUI" ] << endl; sout << "QML debugging..............." << dictionary[ "QML_DEBUG" ] << endl; sout << "DirectWrite support........." << dictionary[ "DIRECTWRITE" ] << endl; sout << "DirectWrite 2 support......." << dictionary[ "DIRECTWRITE2" ] << endl; sout << "Use system proxies.........." << dictionary[ "SYSTEM_PROXIES" ] << endl; sout << "SCTP support................" << dictionary[ "SCTP" ] << endl; sout << endl; sout << "QPA Backends:" << endl; sout << " GDI....................." << "yes" << endl; sout << " Direct2D................" << dictionary[ "DIRECT2D" ] << endl; sout << endl; sout << "Third Party Libraries:" << endl; sout << " ZLIB support............" << (dictionary[ "SYSTEM_ZLIB" ] == QLatin1String("yes") ? QLatin1String("system") : QLatin1String("qt")) << endl; sout << " GIF support............." << dictionary[ "GIF" ] << endl; sout << " JPEG support............" << dictionary[ "JPEG" ] << " (" << dictionary[ "LIBJPEG" ] << ")" << endl; sout << " PNG support............." << dictionary[ "PNG" ] << " (" << dictionary[ "LIBPNG" ] << ")" << endl; sout << " DoubleConversion........" << dictionary[ "DOUBLECONVERSION" ] << endl; sout << " FreeType support........" << dictionary[ "FREETYPE" ] << endl; sout << " Fontconfig support......" << dictionary[ "FONT_CONFIG" ] << endl; sout << " HarfBuzz support........" << dictionary[ "HARFBUZZ" ] << endl; sout << " PCRE support............" << dictionary[ "PCRE" ] << endl; sout << " ICU support............." << dictionary[ "ICU" ] << endl; if (platform() == QNX) { sout << " SLOG2 support..........." << dictionary[ "SLOG2" ] << endl; sout << " IMF support............." << dictionary[ "QNX_IMF" ] << endl; sout << " PPS support............." << dictionary[ "PPS" ] << endl; sout << " LGMON support..........." << dictionary[ "LGMON" ] << endl; } sout << " ANGLE..................." << dictionary[ "ANGLE" ] << endl; sout << " Dynamic OpenGL.........." << dictionary[ "DYNAMICGL" ] << endl; sout << endl; sout << "Styles:" << endl; sout << " Windows................." << dictionary[ "STYLE_WINDOWS" ] << endl; sout << " Windows XP.............." << dictionary[ "STYLE_WINDOWSXP" ] << endl; sout << " Windows Vista..........." << dictionary[ "STYLE_WINDOWSVISTA" ] << endl; sout << " Fusion.................." << dictionary[ "STYLE_FUSION" ] << endl; sout << endl; sout << "Sql Drivers:" << endl; sout << " ODBC...................." << dictionary[ "SQL_ODBC" ] << endl; sout << " MySQL..................." << dictionary[ "SQL_MYSQL" ] << endl; sout << " OCI....................." << dictionary[ "SQL_OCI" ] << endl; sout << " PostgreSQL.............." << dictionary[ "SQL_PSQL" ] << endl; sout << " TDS....................." << dictionary[ "SQL_TDS" ] << endl; sout << " DB2....................." << dictionary[ "SQL_DB2" ] << endl; sout << " SQLite.................." << dictionary[ "SQL_SQLITE" ] << " (" << dictionary[ "SQL_SQLITE_LIB" ] << ")" << endl; sout << " SQLite2................." << dictionary[ "SQL_SQLITE2" ] << endl; sout << " InterBase..............." << dictionary[ "SQL_IBASE" ] << endl; sout << endl; sout << "Sources are in.............." << QDir::toNativeSeparators(sourcePath) << endl; sout << "Build is done in............" << QDir::toNativeSeparators(buildPath) << endl; sout << "Install prefix.............." << QDir::toNativeSeparators(dictionary["QT_INSTALL_PREFIX"]) << endl; sout << "Headers installed to........" << formatConfigPath("QT_REL_INSTALL_HEADERS") << endl; sout << "Libraries installed to......" << formatConfigPath("QT_REL_INSTALL_LIBS") << endl; sout << "Arch-dep. data to..........." << formatConfigPath("QT_REL_INSTALL_ARCHDATA") << endl; sout << "Plugins installed to........" << formatConfigPath("QT_REL_INSTALL_PLUGINS") << endl; sout << "Library execs installed to.." << formatConfigPath("QT_REL_INSTALL_LIBEXECS") << endl; sout << "QML1 imports installed to..." << formatConfigPath("QT_REL_INSTALL_IMPORTS") << endl; sout << "QML2 imports installed to..." << formatConfigPath("QT_REL_INSTALL_QML") << endl; sout << "Binaries installed to......." << formatConfigPath("QT_REL_INSTALL_BINS") << endl; sout << "Arch-indep. data to........." << formatConfigPath("QT_REL_INSTALL_DATA") << endl; sout << "Docs installed to..........." << formatConfigPath("QT_REL_INSTALL_DOCS") << endl; sout << "Translations installed to..." << formatConfigPath("QT_REL_INSTALL_TRANSLATIONS") << endl; sout << "Examples installed to......." << formatConfigPath("QT_REL_INSTALL_EXAMPLES") << endl; sout << "Tests installed to.........." << formatConfigPath("QT_REL_INSTALL_TESTS") << endl; if (checkAvailability("INCREDIBUILD_XGE")) sout << "Using IncrediBuild XGE......" << dictionary["INCREDIBUILD_XGE"] << endl; if (!qmakeDefines.isEmpty()) { sout << "Defines....................."; for (QStringList::Iterator defs = qmakeDefines.begin(); defs != qmakeDefines.end(); ++defs) sout << (*defs) << " "; sout << endl; } if (!qmakeIncludes.isEmpty()) { sout << "Include paths..............."; for (QStringList::Iterator incs = qmakeIncludes.begin(); incs != qmakeIncludes.end(); ++incs) sout << (*incs) << " "; sout << endl; } if (!qmakeLibs.isEmpty()) { sout << "Additional libraries........"; for (QStringList::Iterator libs = qmakeLibs.begin(); libs != qmakeLibs.end(); ++libs) sout << (*libs) << " "; sout << endl; } if (dictionary[ "SHARED" ] == "no") { sout << "WARNING: Using static linking will disable the use of plugins." << endl; sout << " Make sure you compile ALL needed modules into the library." << endl; } if (dictionary[ "OPENSSL" ] == "linked") { if (!opensslLibsDebug.isEmpty() || !opensslLibsRelease.isEmpty()) { sout << "Using OpenSSL libraries:" << endl; sout << " debug : " << opensslLibsDebug << endl; sout << " release: " << opensslLibsRelease << endl; sout << " both : " << opensslLibs << endl; } else if (opensslLibs.isEmpty()) { sout << "NOTE: When linking against OpenSSL, you can override the default" << endl; sout << "library names through OPENSSL_LIBS and optionally OPENSSL_LIBS_DEBUG/OPENSSL_LIBS_RELEASE" << endl; sout << "For example:" << endl; sout << " configure -openssl-linked OPENSSL_LIBS=\"-lssleay32 -llibeay32\"" << endl; } } if (dictionary["RELEASE_TOOLS"] == "yes" && dictionary["BUILD"] != "debug" ) { sout << endl << "NOTE: -optimized-tools is not useful in -release mode." << endl; } if (!dictionary["PREFIX_COMPLAINTS"].isEmpty()) { sout << endl << dictionary["PREFIX_COMPLAINTS"] << endl << endl; } // display config.summary sout.seekg(0, ios::beg); while (sout.good()) { string str; getline(sout, str); cout << str << endl; } } void Configure::generateHeaders() { if (dictionary["SYNCQT"] == "auto") dictionary["SYNCQT"] = defaultTo("SYNCQT"); if (dictionary["SYNCQT"] == "yes") { if (!QStandardPaths::findExecutable(QStringLiteral("perl.exe")).isEmpty()) { cout << "Running syncqt..." << endl; QStringList args; args << "perl" << "-w"; args += sourcePath + "/bin/syncqt.pl"; args << "-version" << dictionary["VERSION"] << "-minimal" << "-module" << "QtCore"; args += sourcePath; int retc = Environment::execute(args, QStringList(), QStringList()); if (retc) { cout << "syncqt failed, return code " << retc << endl << endl; dictionary["DONE"] = "error"; } } else { cout << "Perl not found in environment - cannot run syncqt." << endl; dictionary["DONE"] = "error"; } } } void Configure::addConfStr(int group, const QString &val) { confStrOffsets[group] += ' ' + QString::number(confStringOff) + ','; confStrings[group] += " \"" + val + "\\0\"\n"; confStringOff += val.length() + 1; } void Configure::generateQConfigCpp() { QString hostSpec = dictionary["QMAKESPEC"]; QString targSpec = dictionary.contains("XQMAKESPEC") ? dictionary["XQMAKESPEC"] : hostSpec; dictionary["CFG_SYSROOT"] = QDir::cleanPath(dictionary["CFG_SYSROOT"]); bool qipempty = false; if (dictionary["QT_INSTALL_PREFIX"].isEmpty()) qipempty = true; else dictionary["QT_INSTALL_PREFIX"] = QDir::cleanPath(dictionary["QT_INSTALL_PREFIX"]); bool sysrootifyPrefix; if (dictionary["QT_EXT_PREFIX"].isEmpty()) { dictionary["QT_EXT_PREFIX"] = dictionary["QT_INSTALL_PREFIX"]; sysrootifyPrefix = !dictionary["CFG_SYSROOT"].isEmpty(); } else { dictionary["QT_EXT_PREFIX"] = QDir::cleanPath(dictionary["QT_EXT_PREFIX"]); sysrootifyPrefix = false; } bool haveHpx; if (dictionary["QT_HOST_PREFIX"].isEmpty()) { dictionary["QT_HOST_PREFIX"] = (sysrootifyPrefix ? dictionary["CFG_SYSROOT"] : QString()) + dictionary["QT_INSTALL_PREFIX"]; haveHpx = false; } else { dictionary["QT_HOST_PREFIX"] = QDir::cleanPath(dictionary["QT_HOST_PREFIX"]); haveHpx = true; } static const struct { const char *basevar, *baseoption, *var, *option; } varmod[] = { { "INSTALL_", "-prefix", "DOCS", "-docdir" }, { "INSTALL_", "-prefix", "HEADERS", "-headerdir" }, { "INSTALL_", "-prefix", "LIBS", "-libdir" }, { "INSTALL_", "-prefix", "LIBEXECS", "-libexecdir" }, { "INSTALL_", "-prefix", "BINS", "-bindir" }, { "INSTALL_", "-prefix", "PLUGINS", "-plugindir" }, { "INSTALL_", "-prefix", "IMPORTS", "-importdir" }, { "INSTALL_", "-prefix", "QML", "-qmldir" }, { "INSTALL_", "-prefix", "ARCHDATA", "-archdatadir" }, { "INSTALL_", "-prefix", "DATA", "-datadir" }, { "INSTALL_", "-prefix", "TRANSLATIONS", "-translationdir" }, { "INSTALL_", "-prefix", "EXAMPLES", "-examplesdir" }, { "INSTALL_", "-prefix", "TESTS", "-testsdir" }, { "INSTALL_", "-prefix", "SETTINGS", "-sysconfdir" }, { "HOST_", "-hostprefix", "BINS", "-hostbindir" }, { "HOST_", "-hostprefix", "LIBS", "-hostlibdir" }, { "HOST_", "-hostprefix", "DATA", "-hostdatadir" }, }; bool prefixReminder = false; for (uint i = 0; i < sizeof(varmod) / sizeof(varmod[0]); i++) { QString path = QDir::cleanPath( dictionary[QLatin1String("QT_") + varmod[i].basevar + varmod[i].var]); if (path.isEmpty()) continue; QString base = dictionary[QLatin1String("QT_") + varmod[i].basevar + "PREFIX"]; if (!path.startsWith(base)) { if (i != 13) { dictionary["PREFIX_COMPLAINTS"] += QLatin1String("\n NOTICE: ") + varmod[i].option + " is not a subdirectory of " + varmod[i].baseoption + "."; if (i < 13 ? qipempty : !haveHpx) prefixReminder = true; } } else { path.remove(0, base.size()); if (path.startsWith('/')) path.remove(0, 1); } dictionary[QLatin1String("QT_REL_") + varmod[i].basevar + varmod[i].var] = path.isEmpty() ? "." : path; } if (prefixReminder) { dictionary["PREFIX_COMPLAINTS"] += "\n Maybe you forgot to specify -prefix/-hostprefix?"; } if (!qipempty) { // If QT_INSTALL_* have not been specified on the command line, // default them here, unless prefix is empty (WinCE). if (dictionary["QT_REL_INSTALL_HEADERS"].isEmpty()) dictionary["QT_REL_INSTALL_HEADERS"] = "include"; if (dictionary["QT_REL_INSTALL_LIBS"].isEmpty()) dictionary["QT_REL_INSTALL_LIBS"] = "lib"; if (dictionary["QT_REL_INSTALL_BINS"].isEmpty()) dictionary["QT_REL_INSTALL_BINS"] = "bin"; if (dictionary["QT_REL_INSTALL_ARCHDATA"].isEmpty()) dictionary["QT_REL_INSTALL_ARCHDATA"] = "."; if (dictionary["QT_REL_INSTALL_ARCHDATA"] != ".") dictionary["QT_REL_INSTALL_ARCHDATA_PREFIX"] = dictionary["QT_REL_INSTALL_ARCHDATA"] + '/'; if (dictionary["QT_REL_INSTALL_LIBEXECS"].isEmpty()) { if (targSpec.startsWith("win")) dictionary["QT_REL_INSTALL_LIBEXECS"] = dictionary["QT_REL_INSTALL_ARCHDATA_PREFIX"] + "bin"; else dictionary["QT_REL_INSTALL_LIBEXECS"] = dictionary["QT_REL_INSTALL_ARCHDATA_PREFIX"] + "libexec"; } if (dictionary["QT_REL_INSTALL_PLUGINS"].isEmpty()) dictionary["QT_REL_INSTALL_PLUGINS"] = dictionary["QT_REL_INSTALL_ARCHDATA_PREFIX"] + "plugins"; if (dictionary["QT_REL_INSTALL_IMPORTS"].isEmpty()) dictionary["QT_REL_INSTALL_IMPORTS"] = dictionary["QT_REL_INSTALL_ARCHDATA_PREFIX"] + "imports"; if (dictionary["QT_REL_INSTALL_QML"].isEmpty()) dictionary["QT_REL_INSTALL_QML"] = dictionary["QT_REL_INSTALL_ARCHDATA_PREFIX"] + "qml"; if (dictionary["QT_REL_INSTALL_DATA"].isEmpty()) dictionary["QT_REL_INSTALL_DATA"] = "."; if (dictionary["QT_REL_INSTALL_DATA"] != ".") dictionary["QT_REL_INSTALL_DATA_PREFIX"] = dictionary["QT_REL_INSTALL_DATA"] + '/'; if (dictionary["QT_REL_INSTALL_DOCS"].isEmpty()) dictionary["QT_REL_INSTALL_DOCS"] = dictionary["QT_REL_INSTALL_DATA_PREFIX"] + "doc"; if (dictionary["QT_REL_INSTALL_TRANSLATIONS"].isEmpty()) dictionary["QT_REL_INSTALL_TRANSLATIONS"] = dictionary["QT_REL_INSTALL_DATA_PREFIX"] + "translations"; if (dictionary["QT_REL_INSTALL_EXAMPLES"].isEmpty()) dictionary["QT_REL_INSTALL_EXAMPLES"] = "examples"; if (dictionary["QT_REL_INSTALL_TESTS"].isEmpty()) dictionary["QT_REL_INSTALL_TESTS"] = "tests"; } if (dictionary["QT_REL_HOST_BINS"].isEmpty()) dictionary["QT_REL_HOST_BINS"] = haveHpx ? "bin" : dictionary["QT_REL_INSTALL_BINS"]; if (dictionary["QT_REL_HOST_LIBS"].isEmpty()) dictionary["QT_REL_HOST_LIBS"] = haveHpx ? "lib" : dictionary["QT_REL_INSTALL_LIBS"]; if (dictionary["QT_REL_HOST_DATA"].isEmpty()) dictionary["QT_REL_HOST_DATA"] = haveHpx ? "." : dictionary["QT_REL_INSTALL_ARCHDATA"]; confStringOff = 0; addConfStr(0, dictionary["QT_REL_INSTALL_DOCS"]); addConfStr(0, dictionary["QT_REL_INSTALL_HEADERS"]); addConfStr(0, dictionary["QT_REL_INSTALL_LIBS"]); addConfStr(0, dictionary["QT_REL_INSTALL_LIBEXECS"]); addConfStr(0, dictionary["QT_REL_INSTALL_BINS"]); addConfStr(0, dictionary["QT_REL_INSTALL_PLUGINS"]); addConfStr(0, dictionary["QT_REL_INSTALL_IMPORTS"]); addConfStr(0, dictionary["QT_REL_INSTALL_QML"]); addConfStr(0, dictionary["QT_REL_INSTALL_ARCHDATA"]); addConfStr(0, dictionary["QT_REL_INSTALL_DATA"]); addConfStr(0, dictionary["QT_REL_INSTALL_TRANSLATIONS"]); addConfStr(0, dictionary["QT_REL_INSTALL_EXAMPLES"]); addConfStr(0, dictionary["QT_REL_INSTALL_TESTS"]); addConfStr(1, dictionary["CFG_SYSROOT"]); addConfStr(1, dictionary["QT_REL_HOST_BINS"]); addConfStr(1, dictionary["QT_REL_HOST_LIBS"]); addConfStr(1, dictionary["QT_REL_HOST_DATA"]); addConfStr(1, targSpec); addConfStr(1, hostSpec); // Generate the new qconfig.cpp file { FileWriter tmpStream(buildPath + "/src/corelib/global/qconfig.cpp"); tmpStream << "/* Build date */" << endl << "static const char qt_configure_installation [11 + 12] = \"qt_instdate=2012-12-20\";" << endl << endl << "/* Installation Info */" << endl << "static const char qt_configure_prefix_path_str [512 + 12] = \"qt_prfxpath=" << dictionary["QT_INSTALL_PREFIX"] << "\";" << endl << "#ifdef QT_BUILD_QMAKE" << endl << "static const char qt_configure_ext_prefix_path_str [512 + 12] = \"qt_epfxpath=" << dictionary["QT_EXT_PREFIX"] << "\";" << endl << "static const char qt_configure_host_prefix_path_str [512 + 12] = \"qt_hpfxpath=" << dictionary["QT_HOST_PREFIX"] << "\";" << endl << "#endif" << endl << endl << "static const short qt_configure_str_offsets[] = {\n" << " " << confStrOffsets[0] << endl << "#ifdef QT_BUILD_QMAKE\n" << " " << confStrOffsets[1] << endl << "#endif\n" << "};\n" << "static const char qt_configure_strs[] =\n" << confStrings[0] << "#ifdef QT_BUILD_QMAKE\n" << confStrings[1] << "#endif\n" << ";\n" << endl; if ((platform() != WINDOWS) && (platform() != WINDOWS_RT)) tmpStream << "#define QT_CONFIGURE_SETTINGS_PATH \"" << dictionary["QT_REL_INSTALL_SETTINGS"] << "\"" << endl; tmpStream << endl << "#ifdef QT_BUILD_QMAKE\n" << "# define QT_CONFIGURE_SYSROOTIFY_PREFIX " << (sysrootifyPrefix ? "true" : "false") << endl << "#endif\n\n" << endl << "#define QT_CONFIGURE_PREFIX_PATH qt_configure_prefix_path_str + 12\n" << "#ifdef QT_BUILD_QMAKE\n" << "# define QT_CONFIGURE_EXT_PREFIX_PATH qt_configure_ext_prefix_path_str + 12\n" << "# define QT_CONFIGURE_HOST_PREFIX_PATH qt_configure_host_prefix_path_str + 12\n" << "#endif\n"; if (!tmpStream.flush()) dictionary[ "DONE" ] = "error"; } } void Configure::buildQmake() { { QStringList args; // Build qmake QString pwd = QDir::currentPath(); if (!QDir(buildPath).mkpath("qmake")) { cout << "Cannot create qmake build dir." << endl; dictionary[ "DONE" ] = "error"; return; } if (!QDir::setCurrent(buildPath + "/qmake")) { cout << "Cannot enter qmake build dir." << endl; dictionary[ "DONE" ] = "error"; return; } QString makefile = "Makefile"; { QFile out(makefile); if (out.open(QFile::WriteOnly | QFile::Text)) { QTextStream stream(&out); stream << "#AutoGenerated by configure.exe" << endl << "BUILD_PATH = .." << endl << "SOURCE_PATH = " << QDir::toNativeSeparators(sourcePath) << endl << "INC_PATH = " << QDir::toNativeSeparators( (QFile::exists(sourcePath + "/.git") ? ".." : sourcePath) + "/include") << endl; stream << "QT_VERSION = " << dictionary["VERSION"] << endl << "QT_MAJOR_VERSION = " << dictionary["VERSION_MAJOR"] << endl << "QT_MINOR_VERSION = " << dictionary["VERSION_MINOR"] << endl << "QT_PATCH_VERSION = " << dictionary["VERSION_PATCH"] << endl; if (dictionary[ "QMAKESPEC" ].startsWith("win32-g++")) { stream << "QMAKESPEC = $(SOURCE_PATH)\\mkspecs\\" << dictionary[ "QMAKESPEC" ] << endl << "EXTRA_CFLAGS = -DUNICODE -ffunction-sections" << endl << "EXTRA_CXXFLAGS = -std=c++11 -DUNICODE -ffunction-sections" << endl << "EXTRA_LFLAGS = -Wl,--gc-sections" << endl << "QTOBJS = qfilesystemengine_win.o \\" << endl << " qfilesystemiterator_win.o \\" << endl << " qfsfileengine_win.o \\" << endl << " qlocale_win.o \\" << endl << " qsettings_win.o \\" << endl << " qsystemlibrary.o \\" << endl << " registry.o" << endl << "QTSRCS=\"$(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp\" \\" << endl << " \"$(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp\" \\" << endl << " \"$(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp\" \\" << endl << " \"$(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp\" \\" << endl << " \"$(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp\" \\" << endl\ << " \"$(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp\" \\" << endl << " \"$(SOURCE_PATH)/tools/shared/windows/registry.cpp\"" << endl << "EXEEXT=.exe" << endl << "LFLAGS=-static -s -lole32 -luuid -ladvapi32 -lkernel32" << endl; /* ** SHELL is the full path of sh.exe, unless ** 1) it is found in the current directory ** 2) it is not found at all ** 3) it is overridden on the command line with an existing file ** ... otherwise it is always sh.exe. Specifically, SHELL from the ** environment has no effect. ** ** This check will fail if SHELL is explicitly set to a not ** sh-compatible shell. This is not a problem, because configure.bat ** will not do that. */ stream << "ifeq ($(SHELL), sh.exe)" << endl << " ifeq ($(wildcard $(CURDIR)/sh.exe), )" << endl << " SH = 0" << endl << " else" << endl << " SH = 1" << endl << " endif" << endl << "else" << endl << " SH = 1" << endl << "endif" << endl << "\n" << "ifeq ($(SH), 1)" << endl << " RM_F = rm -f" << endl << " RM_RF = rm -rf" << endl << "else" << endl << " RM_F = del /f" << endl << " RM_RF = rmdir /s /q" << endl << "endif" << endl; stream << "\n\n"; } else { stream << "QMAKESPEC = " << dictionary["QMAKESPEC"] << endl; } stream << "\n\n"; QFile in(sourcePath + "/qmake/" + dictionary["QMAKEMAKEFILE"]); if (in.open(QFile::ReadOnly | QFile::Text)) { QString d = in.readAll(); //### need replaces (like configure.sh)? --Sam stream << d << endl; } stream.flush(); out.close(); } } args += dictionary[ "MAKE" ]; args += "-f"; args += makefile; cout << "Creating qmake..." << endl; int exitCode = Environment::execute(args, QStringList(), QStringList()); if (exitCode) { args.clear(); args += dictionary[ "MAKE" ]; args += "-f"; args += makefile; args += "clean"; exitCode = Environment::execute(args, QStringList(), QStringList()); if (exitCode) { cout << "Cleaning qmake failed, return code " << exitCode << endl << endl; dictionary[ "DONE" ] = "error"; } else { args.clear(); args += dictionary[ "MAKE" ]; args += "-f"; args += makefile; exitCode = Environment::execute(args, QStringList(), QStringList()); if (exitCode) { cout << "Building qmake failed, return code " << exitCode << endl << endl; dictionary[ "DONE" ] = "error"; } } } QDir::setCurrent(pwd); } // Generate qt.conf QFile confFile(buildPath + "/bin/qt.conf"); if (confFile.open(QFile::WriteOnly | QFile::Text)) { // Truncates any existing file. QTextStream confStream(&confFile); confStream << "[EffectivePaths]" << endl << "Prefix=.." << endl; if (sourcePath != buildPath) confStream << "[EffectiveSourcePaths]" << endl << "Prefix=" << sourcePath << endl; confStream.flush(); confFile.close(); } } void Configure::generateMakefiles() { QString pwd = QDir::currentPath(); { QString sourcePathMangled = sourcePath; QString buildPathMangled = buildPath; if (dictionary.contains("TOPLEVEL")) { sourcePathMangled = QFileInfo(sourcePath).path(); buildPathMangled = QFileInfo(buildPath).path(); } QStringList args; args << buildPath + "/bin/qmake" << sourcePathMangled; QDir::setCurrent(buildPathMangled); if (int exitCode = Environment::execute(args, QStringList(), QStringList())) { cout << "Qmake failed, return code " << exitCode << endl << endl; dictionary[ "DONE" ] = "error"; } } QDir::setCurrent(pwd); } void Configure::showSummary() { QString make = dictionary[ "MAKE" ]; cout << endl << endl << "Qt is now configured for building. Just run " << qPrintable(make) << "." << endl; cout << "To reconfigure, run " << qPrintable(make) << " confclean and configure." << endl << endl; } bool Configure::showLicense(QString orgLicenseFile) { if (dictionary["LICENSE_CONFIRMED"] == "yes") { cout << "You have already accepted the terms of the license." << endl << endl; return true; } bool showGpl2 = true; QString licenseFile = orgLicenseFile; QString theLicense; if (dictionary["EDITION"] == "OpenSource") { if (platform() != WINDOWS_RT && (platform() != ANDROID || dictionary["ANDROID_STYLE_ASSETS"] == "no")) { theLicense = "GNU Lesser General Public License (LGPL) version 3\n" "or the GNU General Public License (GPL) version 2"; } else { theLicense = "GNU Lesser General Public License (LGPL) version 3"; showGpl2 = false; } } else { // the first line of the license file tells us which license it is QFile file(licenseFile); if (!file.open(QFile::ReadOnly)) { cout << "Failed to load LICENSE file" << endl; return false; } theLicense = file.readLine().trimmed(); } forever { char accept = '?'; cout << "You are licensed to use this software under the terms of" << endl << "the " << theLicense << "." << endl << endl; if (dictionary["EDITION"] == "OpenSource") { cout << "Type 'L' to view the GNU Lesser General Public License version 3 (LGPLv3)." << endl; if (showGpl2) cout << "Type 'G' to view the GNU General Public License version 2 (GPLv2)." << endl; } else { cout << "Type '?' to view the " << theLicense << "." << endl; } cout << "Type 'y' to accept this license offer." << endl << "Type 'n' to decline this license offer." << endl << endl << "Do you accept the terms of the license?" << endl; cin >> accept; accept = tolower(accept); if (accept == 'y') { return true; } else if (accept == 'n') { return false; } else { if (dictionary["EDITION"] == "OpenSource") { if (accept == 'L') licenseFile = orgLicenseFile + "/LICENSE.LGPL3"; else licenseFile = orgLicenseFile + "/LICENSE.GPL2"; } // Get console line height, to fill the screen properly int i = 0, screenHeight = 25; // default CONSOLE_SCREEN_BUFFER_INFO consoleInfo; HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE); if (GetConsoleScreenBufferInfo(stdOut, &consoleInfo)) screenHeight = consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top - 1; // Some overlap for context // Prompt the license content to the user QFile file(licenseFile); if (!file.open(QFile::ReadOnly)) { cout << "Failed to load LICENSE file" << licenseFile << endl; return false; } QStringList licenseContent = QString(file.readAll()).split('\n'); while (i < licenseContent.size()) { cout << licenseContent.at(i) << endl; if (++i % screenHeight == 0) { promptKeyPress(); cout << "\r"; // Overwrite text above } } } } } void Configure::readLicense() { dictionary["PLATFORM NAME"] = platformName(); dictionary["LICENSE FILE"] = sourcePath; bool openSource = false; bool hasOpenSource = QFile::exists(dictionary["LICENSE FILE"] + "/LICENSE.LGPL3") || QFile::exists(dictionary["LICENSE FILE"] + "/LICENSE.GPL2"); if (dictionary["BUILDTYPE"] == "commercial") { openSource = false; } else if (dictionary["BUILDTYPE"] == "opensource") { openSource = true; } else if (hasOpenSource) { // No Open Source? Just display the commercial license right away forever { char accept = '?'; cout << "Which edition of Qt do you want to use ?" << endl; cout << "Type 'c' if you want to use the Commercial Edition." << endl; cout << "Type 'o' if you want to use the Open Source Edition." << endl; cin >> accept; accept = tolower(accept); if (accept == 'c') { openSource = false; break; } else if (accept == 'o') { openSource = true; break; } } } if (hasOpenSource && openSource) { cout << endl << "This is the " << dictionary["PLATFORM NAME"] << " Open Source Edition." << endl; dictionary["LICENSEE"] = "Open Source"; dictionary["EDITION"] = "OpenSource"; cout << endl; if (!showLicense(dictionary["LICENSE FILE"])) { cout << "Configuration aborted since license was not accepted"; dictionary["DONE"] = "error"; return; } } else if (openSource) { cout << endl << "Cannot find the GPL license files! Please download the Open Source version of the library." << endl; dictionary["DONE"] = "error"; } else { Tools::checkLicense(dictionary, sourcePath, buildPath); } } void Configure::reloadCmdLine(int idx) { if (dictionary[ "REDO" ] == "yes") { QFile inFile(buildPath + "/config.opt"); if (!inFile.open(QFile::ReadOnly)) { inFile.setFileName(buildPath + "/configure.cache"); if (!inFile.open(QFile::ReadOnly)) return; } QTextStream inStream(&inFile); while (!inStream.atEnd()) configCmdLine.insert(idx++, inStream.readLine().trimmed()); } } void Configure::saveCmdLine() { if (dictionary[ "REDO" ] != "yes") { QFile outFile(buildPath + "/config.opt"); if (outFile.open(QFile::WriteOnly | QFile::Text)) { QTextStream outStream(&outFile); for (QStringList::Iterator it = configCmdLine.begin(); it != configCmdLine.end(); ++it) { outStream << (*it) << endl; } outStream.flush(); outFile.close(); } } } bool Configure::isDone() { return !dictionary["DONE"].isEmpty(); } bool Configure::isOk() { return (dictionary[ "DONE" ] != "error"); } QString Configure::platformName() const { switch (platform()) { default: case WINDOWS: return QStringLiteral("Qt for Windows"); case WINDOWS_RT: return QStringLiteral("Qt for Windows Runtime"); case QNX: return QStringLiteral("Qt for QNX"); case ANDROID: return QStringLiteral("Qt for Android"); case OTHER: return QStringLiteral("Qt for ???"); } } QString Configure::qpaPlatformName() const { switch (platform()) { default: case WINDOWS: return QStringLiteral("windows"); case WINDOWS_RT: return QStringLiteral("winrt"); case QNX: return QStringLiteral("qnx"); case ANDROID: return QStringLiteral("android"); case OTHER: return QStringLiteral("xcb"); } } int Configure::platform() const { const QString xQMakeSpec = dictionary.value("XQMAKESPEC"); if ((xQMakeSpec.startsWith("winphone") || xQMakeSpec.startsWith("winrt"))) return WINDOWS_RT; if (xQMakeSpec.contains("qnx")) return QNX; if (xQMakeSpec.contains("android")) return ANDROID; if (!xQMakeSpec.isEmpty()) return OTHER; return WINDOWS; } FileWriter::FileWriter(const QString &name) : QTextStream() , m_name(name) { m_buffer.open(QIODevice::WriteOnly); setDevice(&m_buffer); } bool FileWriter::flush() { QTextStream::flush(); QFile oldFile(m_name); if (oldFile.open(QIODevice::ReadOnly | QIODevice::Text)) { if (oldFile.readAll() == m_buffer.data()) return true; oldFile.close(); } QString dir = QFileInfo(m_name).absolutePath(); if (!QDir().mkpath(dir)) { cout << "Cannot create directory " << qPrintable(QDir::toNativeSeparators(dir)) << ".\n"; return false; } QFile file(m_name + ".new"); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { if (file.write(m_buffer.data()) == m_buffer.data().size()) { file.close(); if (file.error() == QFile::NoError) { ::SetFileAttributes((wchar_t*)m_name.utf16(), FILE_ATTRIBUTE_NORMAL); QFile::remove(m_name); if (!file.rename(m_name)) { cout << "Cannot replace file " << qPrintable(QDir::toNativeSeparators(m_name)) << ".\n"; return false; } return true; } } } cout << "Cannot create file " << qPrintable(QDir::toNativeSeparators(file.fileName())) << ": " << qPrintable(file.errorString()) << ".\n"; file.remove(); return false; } QT_END_NAMESPACE