diff options
Diffstat (limited to 'qmake/generators')
-rw-r--r-- | qmake/generators/mac/pbuilder_pbx.cpp | 199 | ||||
-rw-r--r-- | qmake/generators/projectgenerator.cpp | 13 | ||||
-rw-r--r-- | qmake/generators/unix/unixmake.cpp | 9 | ||||
-rw-r--r-- | qmake/generators/unix/unixmake2.cpp | 102 | ||||
-rw-r--r-- | qmake/generators/win32/msbuild_objectmodel.cpp | 4 | ||||
-rw-r--r-- | qmake/generators/win32/msbuild_objectmodel.h | 3 | ||||
-rw-r--r-- | qmake/generators/win32/msvc_nmake.cpp | 64 | ||||
-rw-r--r-- | qmake/generators/win32/msvc_nmake.h | 1 | ||||
-rw-r--r-- | qmake/generators/win32/msvc_objectmodel.cpp | 33 | ||||
-rw-r--r-- | qmake/generators/win32/msvc_objectmodel.h | 5 | ||||
-rw-r--r-- | qmake/generators/win32/msvc_vcproj.cpp | 132 |
11 files changed, 243 insertions, 322 deletions
diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index dce22ed712..7507b26c09 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -1113,6 +1113,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) } bool copyBundleResources = project->isActiveConfig("app_bundle") && project->first("TEMPLATE") == "app"; ProStringList bundle_resources_files; + ProStringList embedded_frameworks; + QMap<ProString, ProStringList> embedded_plugins; // Copy Bundle Data if (!project->isEmpty("QMAKE_BUNDLE_DATA")) { ProStringList bundle_file_refs; @@ -1123,6 +1125,11 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) for(int i = 0; i < bundle_data.count(); i++) { ProStringList bundle_files; ProString path = project->first(ProKey(bundle_data[i] + ".path")); + const bool isEmbeddedFramework = ((!osx && path == QLatin1String("Frameworks")) + || (osx && path == QLatin1String("Contents/Frameworks"))); + const ProString pluginsPrefix = ProString(osx ? QLatin1String("Contents/PlugIns") : QLatin1String("PlugIns")); + const bool isEmbeddedPlugin = (path == pluginsPrefix) || path.startsWith(pluginsPrefix + "/"); + //all files const ProStringList &files = project->values(ProKey(bundle_data[i] + ".files")); for(int file = 0; file < files.count(); file++) { @@ -1140,19 +1147,29 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) bundle_files += file_key; t << "\t\t" << file_key << " = {\n" << "\t\t\t" << writeSettings("fileRef", file_ref_key) << ";\n" - << "\t\t\t" << writeSettings("isa", "PBXBuildFile", SettingsNoQuote) << ";\n" - << "\t\t};\n"; + << "\t\t\t" << writeSettings("isa", "PBXBuildFile", SettingsNoQuote) << ";\n"; + if (isEmbeddedFramework || isEmbeddedPlugin || name.endsWith(".dylib") || name.endsWith(".framework")) + t << "\t\t\t" << writeSettings("settings", "{ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }", SettingsNoQuote) << ";\n"; + t << "\t\t};\n"; } if (copyBundleResources && ((!osx && path.isEmpty()) || (osx && path == QLatin1String("Contents/Resources")))) { for (const ProString &s : qAsConst(bundle_files)) bundle_resources_files << s; + } else if (copyBundleResources && isEmbeddedFramework) { + for (const ProString &s : qAsConst(bundle_files)) + embedded_frameworks << s; + } else if (copyBundleResources && isEmbeddedPlugin) { + for (const ProString &s : qAsConst(bundle_files)) { + ProString subpath = (path == pluginsPrefix) ? ProString() : path.mid(pluginsPrefix.size() + 1); + embedded_plugins[subpath] << s; + } } else { QString phase_key = keyFor("QMAKE_PBX_BUNDLE_COPY." + bundle_data[i]); - if (!project->isEmpty(ProKey(bundle_data[i] + ".version"))) { - //### - } + //if (!project->isActiveConfig("shallow_bundle") + // && !project->isEmpty(ProKey(bundle_data[i] + ".version"))) { + //} project->values("QMAKE_PBX_BUILDPHASES").append(phase_key); t << "\t\t" << phase_key << " = {\n" @@ -1196,6 +1213,35 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" << "\t\t\t" << writeSettings("name", grp) << ";\n" << "\t\t};\n"; + + QString grp2("Embed Frameworks"), key2 = keyFor(grp2); + project->values("QMAKE_PBX_BUILDPHASES").append(key2); + t << "\t\t" << key2 << " = {\n" + << "\t\t\t" << writeSettings("isa", "PBXCopyFilesBuildPhase", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("dstPath", "") << ";\n" + << "\t\t\t" << writeSettings("dstSubfolderSpec", "10", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("files", embedded_frameworks, SettingsAsList, 4) << ";\n" + << "\t\t\t" << writeSettings("name", grp2) << ";\n" + << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" + << "\t\t};\n"; + + QMapIterator<ProString, ProStringList> it(embedded_plugins); + while (it.hasNext()) { + it.next(); + QString suffix = !it.key().isEmpty() ? (" (" + it.key() + ")") : QString(); + QString grp3("Embed PlugIns" + suffix), key3 = keyFor(grp3); + project->values("QMAKE_PBX_BUILDPHASES").append(key3); + t << "\t\t" << key3 << " = {\n" + << "\t\t\t" << writeSettings("isa", "PBXCopyFilesBuildPhase", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("dstPath", it.key()) << ";\n" + << "\t\t\t" << writeSettings("dstSubfolderSpec", "13", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("files", it.value(), SettingsAsList, 4) << ";\n" + << "\t\t\t" << writeSettings("name", grp3) << ";\n" + << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" + << "\t\t};\n"; + } } //REFERENCE @@ -1431,14 +1477,22 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) QMap<QString, QString> settings; if (!project->isActiveConfig("no_xcode_development_team")) { - const QList<QVariantMap> teams = provisioningTeams(); - if (!teams.isEmpty()) { - // first suitable team we find is the one we'll use by default - settings.insert("DEVELOPMENT_TEAM", - teams.first().value(QLatin1String("teamID")).toString()); + QString teamId; + if (!project->isEmpty("QMAKE_DEVELOPMENT_TEAM")) { + teamId = project->first("QMAKE_DEVELOPMENT_TEAM").toQString(); + } else { + const QList<QVariantMap> teams = provisioningTeams(); + if (!teams.isEmpty()) // first suitable team we find is the one we'll use by default + teamId = teams.first().value(QLatin1String("teamID")).toString(); } + if (!teamId.isEmpty()) + settings.insert("DEVELOPMENT_TEAM", teamId); + if (!project->isEmpty("QMAKE_PROVISIONING_PROFILE")) + settings.insert("PROVISIONING_PROFILE_SPECIFIER", project->first("QMAKE_PROVISIONING_PROFILE").toQString()); } + settings.insert("COPY_PHASE_STRIP", (as_release ? "YES" : "NO")); + settings.insert("APPLICATION_EXTENSION_API_ONLY", project->isActiveConfig("app_extension_api_only") ? "YES" : "NO"); // required for tvOS (and watchos), optional on iOS (deployment target >= iOS 6.0) settings.insert("ENABLE_BITCODE", project->isActiveConfig("bitcode") ? "YES" : "NO"); settings.insert("GCC_GENERATE_DEBUGGING_SYMBOLS", as_release ? "NO" : "YES"); @@ -1515,9 +1569,15 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) plist_in_text.replace(QLatin1String("@ICON@"), (project->isEmpty("ICON") ? QString("") : project->first("ICON").toQString().section(Option::dir_sep, -1))); if (project->first("TEMPLATE") == "app") { - plist_in_text.replace(QLatin1String("@EXECUTABLE@"), project->first("QMAKE_ORIG_TARGET").toQString()); + ProString app_bundle_name = project->first("QMAKE_APPLICATION_BUNDLE_NAME"); + if (app_bundle_name.isEmpty()) + app_bundle_name = project->first("QMAKE_ORIG_TARGET"); + plist_in_text.replace(QLatin1String("@EXECUTABLE@"), app_bundle_name.toQString()); } else { - plist_in_text.replace(QLatin1String("@LIBRARY@"), project->first("QMAKE_ORIG_TARGET").toQString()); + ProString lib_bundle_name = project->first("QMAKE_FRAMEWORK_BUNDLE_NAME"); + if (lib_bundle_name.isEmpty()) + lib_bundle_name = project->first("QMAKE_ORIG_TARGET"); + plist_in_text.replace(QLatin1String("@LIBRARY@"), lib_bundle_name.toQString()); } QString bundlePrefix = project->first("QMAKE_TARGET_BUNDLE_PREFIX").toQString(); if (bundlePrefix.isEmpty()) @@ -1834,108 +1894,12 @@ ProjectBuilderMakefileGenerator::openOutput(QFile &file, const QString &build) c return UnixMakefileGenerator::openOutput(file, build); } -/* This function is such a hack it is almost pointless, but it - eliminates the warning message from ProjectBuilder that the project - file is for an older version. I guess this could be used someday if - the format of the output is dependant upon the version of - ProjectBuilder as well. -*/ int ProjectBuilderMakefileGenerator::pbuilderVersion() const { - QString ret; - if(!project->isEmpty("QMAKE_PBUILDER_VERSION")) { - ret = project->first("QMAKE_PBUILDER_VERSION").toQString(); - } else { - QString version, version_plist = project->first("QMAKE_PBUILDER_VERSION_PLIST").toQString(); - if(version_plist.isEmpty()) { -#ifdef Q_OS_DARWIN - ret = QLatin1String("34"); - QCFType<CFURLRef> cfurl; - // Check for XCode 4 first - OSStatus err = LSFindApplicationForInfo(0, CFSTR("com.apple.dt.Xcode"), 0, 0, &cfurl); - // Now check for XCode 3 - if (err == kLSApplicationNotFoundErr) - err = LSFindApplicationForInfo(0, CFSTR("com.apple.Xcode"), 0, 0, &cfurl); - if (err == noErr) { - QCFType<CFBundleRef> bundle = CFBundleCreate(0, cfurl); - if (bundle) { - CFStringRef str = CFStringRef(CFBundleGetValueForInfoDictionaryKey(bundle, - CFSTR("CFBundleShortVersionString"))); - if (str) { - QStringList versions = QString::fromCFString(str).split(QLatin1Char('.')); - int versionMajor = versions.at(0).toInt(); - int versionMinor = versions.at(1).toInt(); - if (versionMajor >= 3) { - ret = QLatin1String("46"); - } else if (versionMajor >= 2) { - ret = QLatin1String("42"); - } else if (versionMajor == 1 && versionMinor >= 5) { - ret = QLatin1String("39"); - } - } - } - } -#else - if(exists("/Developer/Applications/Xcode.app/Contents/version.plist")) - version_plist = "/Developer/Applications/Xcode.app/Contents/version.plist"; - else - version_plist = "/Developer/Applications/Project Builder.app/Contents/version.plist"; -#endif - } - if (ret.isEmpty()) { - QFile version_file(version_plist); - if (version_file.open(QIODevice::ReadOnly)) { - debug_msg(1, "pbuilder: version.plist: Reading file: %s", version_plist.toLatin1().constData()); - QTextStream plist(&version_file); - - bool in_dict = false; - QString current_key; - QRegExp keyreg("^<key>(.*)</key>$"), stringreg("^<string>(.*)</string>$"); - while(!plist.atEnd()) { - QString line = plist.readLine().trimmed(); - if(line == "<dict>") - in_dict = true; - else if(line == "</dict>") - in_dict = false; - else if(in_dict) { - if(keyreg.exactMatch(line)) - current_key = keyreg.cap(1); - else if(current_key == "CFBundleShortVersionString" && stringreg.exactMatch(line)) - version = stringreg.cap(1); - } - } - plist.flush(); - version_file.close(); - } else { - debug_msg(1, "pbuilder: version.plist: Failure to open %s", version_plist.toLatin1().constData()); - } - if(version.isEmpty() && version_plist.contains("Xcode")) { - ret = "39"; - } else { - int versionMajor = version.left(1).toInt(); - if(versionMajor >= 2) - ret = "42"; - else if(version == "1.5") - ret = "39"; - else if(version == "1.1") - ret = "34"; - } - } - } - - if(!ret.isEmpty()) { - bool ok; - int int_ret = ret.toInt(&ok); - if(ok) { - debug_msg(1, "pbuilder: version.plist: Got version: %d", int_ret); - if (int_ret < 46) - warn_msg(WarnLogic, "XCode version is too old, at least XCode 3.2 is required"); - return int_ret; - } - } - debug_msg(1, "pbuilder: version.plist: Fallback to default version"); - return 46; //my fallback + if (!project->isEmpty("QMAKE_PBUILDER_VERSION")) + return project->first("QMAKE_PBUILDER_VERSION").toQString().toInt(); + return 46; // Xcode 3.2-compatible; default format since that version } int @@ -1950,22 +1914,13 @@ ProjectBuilderMakefileGenerator::reftypeForFile(const QString &where) QString ProjectBuilderMakefileGenerator::projectSuffix() const { - const int pbVersion = pbuilderVersion(); - if(pbVersion >= 42) - return ".xcodeproj"; - else if(pbVersion >= 38) - return ".xcode"; - return ".pbproj"; + return ".xcodeproj"; } QString ProjectBuilderMakefileGenerator::pbxbuild() { - if(exists("/usr/bin/pbbuild")) - return "pbbuild"; - if(exists("/usr/bin/xcodebuild")) - return "xcodebuild"; - return (pbuilderVersion() >= 38 ? "xcodebuild" : "pbxbuild"); + return "xcodebuild"; } static QString quotedStringLiteral(const QString &value) diff --git a/qmake/generators/projectgenerator.cpp b/qmake/generators/projectgenerator.cpp index 3f6af8fc08..eb4f46cd7e 100644 --- a/qmake/generators/projectgenerator.cpp +++ b/qmake/generators/projectgenerator.cpp @@ -150,7 +150,7 @@ ProjectGenerator::init() QString newdir = pd; QFileInfo fi(fileInfo(newdir)); if(fi.isDir()) { - newdir = fileFixify(newdir); + newdir = fileFixify(newdir, FileFixifyFromOutdir); ProStringList &subdirs = v["SUBDIRS"]; if(exists(fi.filePath() + QDir::separator() + fi.fileName() + Option::pro_ext) && !subdirs.contains(newdir, Qt::CaseInsensitive)) { @@ -344,6 +344,17 @@ ProjectGenerator::writeMakefile(QTextStream &t) << getWritableVar("CONFIG_REMOVE", false) << getWritableVar("INCLUDEPATH") << endl; + t << "# The following define makes your compiler warn you if you use any\n" + "# feature of Qt which has been marked as deprecated (the exact warnings\n" + "# depend on your compiler). Please consult the documentation of the\n" + "# deprecated API in order to know how to port your code away from it.\n" + "DEFINES += QT_DEPRECATED_WARNINGS\n" + "\n" + "# You can also make your code fail to compile if you use deprecated APIs.\n" + "# In order to do so, uncomment the following line.\n" + "# You can also select to disable deprecated APIs only up to a certain version of Qt.\n" + "#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0\n\n"; + t << "# Input" << "\n"; t << getWritableVar("HEADERS") << getWritableVar("FORMS") diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 349dcd2f40..794d04a6e9 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -599,10 +599,13 @@ UnixMakefileGenerator::defaultInstall(const QString &t) plain_targ = escapeFilePath(plain_targ); if (bundle != NoBundle) { QString suffix; - if (project->first("TEMPLATE") == "lib") - suffix = "/Versions/" + project->first("QMAKE_FRAMEWORK_VERSION") + "/$(TARGET)"; - else + if (project->first("TEMPLATE") == "lib") { + if (!project->isActiveConfig("shallow_bundle")) + suffix += "/Versions/" + project->first("QMAKE_FRAMEWORK_VERSION"); + suffix += "/$(TARGET)"; + } else { suffix = "/" + project->first("QMAKE_BUNDLE_LOCATION") + "/$(QMAKE_TARGET)"; + } dst_targ += suffix; if (bundle == SolidBundle) { if (!ret.isEmpty()) diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index b4d43a3dc2..5b56cac784 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -596,9 +596,10 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) << var("QMAKE_LINK_SHLIB_CMD") << "\n\t" << mkdir_p_asstring("\"`dirname $(DESTDIR)$(TARGETD)`\"", false) << "\n\t" << "-$(MOVE) $(TARGET) $(DESTDIR)$(TARGETD)\n\t" - << mkdir_p_asstring("\"`dirname $(DESTDIR)$(TARGET0)`\"", false) << "\n\t" - << varGlue("QMAKE_LN_SHLIB", "-", " ", - " Versions/Current/$(TARGET) $(DESTDIR)$(TARGET0)") << "\n\t"; + << mkdir_p_asstring("\"`dirname $(DESTDIR)$(TARGET0)`\"", false) << "\n\t"; + if (!project->isActiveConfig("shallow_bundle")) + t << varGlue("QMAKE_LN_SHLIB", "-", " ", + " Versions/Current/$(TARGET) $(DESTDIR)$(TARGET0)") << "\n\t"; if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" << var("QMAKE_POST_LINK"); t << endl << endl; @@ -785,10 +786,17 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) } else { info_plist = escapeFilePath(fileFixify(info_plist)); } - bool isFramework = project->first("TEMPLATE") == "lib" && project->isActiveConfig("lib_bundle"); + bool isFramework = project->first("TEMPLATE") == "lib" + && !project->isActiveConfig("plugin") + && project->isActiveConfig("lib_bundle"); + bool isShallowBundle = project->isActiveConfig("shallow_bundle"); QString info_plist_out = bundle_dir + - (isFramework ? ("Versions/" + project->first("QMAKE_FRAMEWORK_VERSION") + "/Resources/Info.plist") - : "Contents/Info.plist"); + (!isShallowBundle + ? (isFramework + ? ("Versions/" + project->first("QMAKE_FRAMEWORK_VERSION") + "/Resources/") + : "Contents/") + : QString()) + + "Info.plist"; bundledFiles << info_plist_out; alldeps << info_plist_out; QString destdir = info_plist_out.section(Option::dir_sep, 0, -2); @@ -822,14 +830,22 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) commonSedArgs << "-e \"s,@BUNDLEIDENTIFIER@," << bundleIdentifier << ",g\" "; if (!isFramework) { + ProString app_bundle_name = var("QMAKE_APPLICATION_BUNDLE_NAME"); + if (app_bundle_name.isEmpty()) + app_bundle_name = var("QMAKE_ORIG_TARGET"); + + ProString plugin_bundle_name = var("QMAKE_PLUGIN_BUNDLE_NAME"); + if (plugin_bundle_name.isEmpty()) + plugin_bundle_name = var("QMAKE_ORIG_TARGET"); + QString icon = fileFixify(var("ICON")); t << "@$(DEL_FILE) " << info_plist_out << "\n\t" << "@sed "; for (const ProString &arg : qAsConst(commonSedArgs)) t << arg; t << "-e \"s,@ICON@," << icon.section(Option::dir_sep, -1) << ",g\" " - << "-e \"s,@EXECUTABLE@," << var("QMAKE_ORIG_TARGET") << ",g\" " - << "-e \"s,@LIBRARY@," << var("QMAKE_ORIG_TARGET") << ",g\" " + << "-e \"s,@EXECUTABLE@," << app_bundle_name << ",g\" " + << "-e \"s,@LIBRARY@," << plugin_bundle_name << ",g\" " << "-e \"s,@TYPEINFO@,"<< (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ? QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) << ",g\" " << "" << info_plist << " >" << info_plist_out << endl; @@ -846,12 +862,17 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) << "@$(COPY_FILE) " << escapeFilePath(icon) << ' ' << icon_path_f << endl; } } else { - symlinks[bundle_dir + "Resources"] = "Versions/Current/Resources"; + ProString lib_bundle_name = var("QMAKE_FRAMEWORK_BUNDLE_NAME"); + if (lib_bundle_name.isEmpty()) + lib_bundle_name = var("QMAKE_ORIG_TARGET"); + + if (!isShallowBundle) + symlinks[bundle_dir + "Resources"] = "Versions/Current/Resources"; t << "@$(DEL_FILE) " << info_plist_out << "\n\t" << "@sed "; for (const ProString &arg : qAsConst(commonSedArgs)) t << arg; - t << "-e \"s,@LIBRARY@," << var("QMAKE_ORIG_TARGET") << ",g\" " + t << "-e \"s,@LIBRARY@," << lib_bundle_name << ",g\" " << "-e \"s,@TYPEINFO@," << (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ? QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) << ",g\" " @@ -865,18 +886,20 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) for(int i = 0; i < bundle_data.count(); i++) { const ProStringList &files = project->values(ProKey(bundle_data[i] + ".files")); QString path = bundle_dir; - const ProKey vkey(bundle_data[i] + ".version"); const ProKey pkey(bundle_data[i] + ".path"); - if (!project->isEmpty(vkey)) { - QString version = project->first(vkey) + "/" + - project->first("QMAKE_FRAMEWORK_VERSION") + "/"; - ProString name = project->first(pkey); - int pos = name.indexOf('/'); - if (pos > 0) - name = name.mid(0, pos); - symlinks[Option::fixPathToTargetOS(path + name)] = - project->first(vkey) + "/Current/" + name; - path += version; + if (!project->isActiveConfig("shallow_bundle")) { + const ProKey vkey(bundle_data[i] + ".version"); + if (!project->isEmpty(vkey)) { + QString version = project->first(vkey) + "/" + + project->first("QMAKE_FRAMEWORK_VERSION") + "/"; + ProString name = project->first(pkey); + int pos = name.indexOf('/'); + if (pos > 0) + name = name.mid(0, pos); + symlinks[Option::fixPathToTargetOS(path + name)] = + project->first(vkey) + "/Current/" + name; + path += version; + } } path += project->first(pkey).toQString(); path = Option::fixPathToTargetOS(path); @@ -914,15 +937,17 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) << "@$(SYMLINK) " << escapeFilePath(symIt.value()) << ' ' << bundle_dir_f << endl; } - QString currentLink = bundle_dir + "Versions/Current"; - QString currentLink_f = escapeDependencyPath(currentLink); - bundledFiles << currentLink; - alldeps << currentLink; - t << currentLink_f << ": $(MAKEFILE)\n\t" - << mkdir_p_asstring(bundle_dir + "Versions") << "\n\t" - << "@-$(DEL_FILE) " << currentLink_f << "\n\t" - << "@$(SYMLINK) " << project->first("QMAKE_FRAMEWORK_VERSION") - << ' ' << currentLink_f << endl; + if (!project->isActiveConfig("shallow_bundle")) { + QString currentLink = bundle_dir + "Versions/Current"; + QString currentLink_f = escapeDependencyPath(currentLink); + bundledFiles << currentLink; + alldeps << currentLink; + t << currentLink_f << ": $(MAKEFILE)\n\t" + << mkdir_p_asstring(bundle_dir + "Versions") << "\n\t" + << "@-$(DEL_FILE) " << currentLink_f << "\n\t" + << "@$(SYMLINK) " << project->first("QMAKE_FRAMEWORK_VERSION") + << ' ' << currentLink_f << endl; + } } } @@ -1194,12 +1219,17 @@ void UnixMakefileGenerator::init2() bundle_loc.prepend("/"); if(!bundle_loc.endsWith("/")) bundle_loc += "/"; - project->values("TARGET_").append(project->first("QMAKE_BUNDLE") + - bundle_loc + project->first("TARGET")); - project->values("TARGET_x.y").append(project->first("QMAKE_BUNDLE") + - "/Versions/" + - project->first("QMAKE_FRAMEWORK_VERSION") + - bundle_loc + project->first("TARGET")); + const QString target = project->first("QMAKE_BUNDLE") + + bundle_loc + project->first("TARGET"); + project->values("TARGET_").append(target); + if (!project->isActiveConfig("shallow_bundle")) { + project->values("TARGET_x.y").append(project->first("QMAKE_BUNDLE") + + "/Versions/" + + project->first("QMAKE_FRAMEWORK_VERSION") + + bundle_loc + project->first("TARGET")); + } else { + project->values("TARGET_x.y").append(target); + } } else if(project->isActiveConfig("plugin")) { QString prefix; if(!project->isActiveConfig("no_plugin_name_prefix")) diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp index 9cc125d396..129fb28e01 100644 --- a/qmake/generators/win32/msbuild_objectmodel.cpp +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -614,7 +614,6 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool) << attrTag("Label", "ProjectConfigurations"); bool isWinRT = false; - bool isWinPhone = false; for (int i = 0; i < tool.SingleProjects.count(); ++i) { xml << tag("ProjectConfiguration") << attrTag("Include" , tool.SingleProjects.at(i).Configuration.Name) @@ -622,7 +621,6 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool) << tagValue("Platform", tool.SingleProjects.at(i).PlatformName) << closetag(); isWinRT = isWinRT || tool.SingleProjects.at(i).Configuration.WinRT; - isWinPhone = isWinPhone || tool.SingleProjects.at(i).Configuration.WinPhone; } xml << closetag() @@ -636,7 +634,7 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool) xml << tagValue("MinimumVisualStudioVersion", tool.Version) << tagValue("DefaultLanguage", "en") << tagValue("AppContainerApplication", "true") - << tagValue("ApplicationType", isWinPhone ? "Windows Phone" : "Windows Store") + << tagValue("ApplicationType", "Windows Store") << tagValue("ApplicationTypeRevision", tool.SdkVersion); if (tool.SdkVersion == "10.0") { const QString ucrtVersion = qgetenv("UCRTVERSION"); diff --git a/qmake/generators/win32/msbuild_objectmodel.h b/qmake/generators/win32/msbuild_objectmodel.h index 4bec517fa6..2e77537916 100644 --- a/qmake/generators/win32/msbuild_objectmodel.h +++ b/qmake/generators/win32/msbuild_objectmodel.h @@ -32,12 +32,9 @@ #include "project.h" #include "xmloutput.h" #include "msvc_objectmodel.h" -#include <qatomic.h> #include <qlist.h> #include <qstring.h> -#include <qstringlist.h> #include <qmap.h> -#include <qdebug.h> QT_BEGIN_NAMESPACE diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 92043e829f..8ac462da6b 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -124,7 +124,6 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t) return false; } - const bool isPhone = project->isActiveConfig(QStringLiteral("winphone")); #ifdef Q_OS_WIN QString regKey; if (msvcVer == QStringLiteral("15.0")) @@ -137,12 +136,7 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t) return false; } - QString windowsPath; - if (isPhone) { - windowsPath = "Software\\Microsoft\\Microsoft SDKs\\WindowsPhoneApp\\v"; - } else { - windowsPath = "Software\\Microsoft\\Microsoft SDKs\\Windows\\v"; - } + const QString windowsPath = "Software\\Microsoft\\Microsoft SDKs\\Windows\\v"; regKey = windowsPath + winsdkVer + QStringLiteral("\\InstallationFolder"); const QString kitDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey, KEY_WOW64_32KEY); @@ -228,23 +222,6 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t) libDirs << crtLib + QStringLiteral("/ucrt/") + arch; libDirs << crtLib + QStringLiteral("/um/") + arch; - } else if (isPhone) { - QString sdkDir = vcInstallDir; - if (!QDir(sdkDir).exists()) { - fprintf(stderr, "Failed to find the Windows Phone SDK in %s.\n" - "Check that it is properly installed.\n", - qPrintable(QDir::toNativeSeparators(sdkDir))); - return false; - } - incDirs << sdkDir + QStringLiteral("/include"); - libDirs << sdkDir + QStringLiteral("/lib/store/") + compilerArch - << sdkDir + QStringLiteral("/lib/") + compilerArch; - binDirs << sdkDir + QStringLiteral("/bin/") + compiler; - libDirs << kitDir + QStringLiteral("/lib/") + arch; - incDirs << kitDir + QStringLiteral("/include") - << kitDir + QStringLiteral("/include/abi") - << kitDir + QStringLiteral("/include/mincore") - << kitDir + QStringLiteral("/include/minwin"); } else { incDirs << vcInstallDir + QStringLiteral("/include"); libDirs << vcInstallDir + QStringLiteral("/lib/store/") + compilerArch @@ -589,9 +566,9 @@ void NmakeMakefileGenerator::writeBuildRulesPart(QTextStream &t) if(!project->isEmpty("QMAKE_PRE_LINK")) t << "\n\t" <<var("QMAKE_PRE_LINK"); if(project->isActiveConfig("staticlib")) { - t << "\n\t$(LIBAPP) $(LIBFLAGS) " << var("QMAKE_LINK_O_FLAG") << "$(DESTDIR_TARGET) @<<\n\t " - << "$(OBJECTS)" - << "\n<<"; + t << "\n\t$(LIBAPP) $(LIBFLAGS) " << var("QMAKE_LINK_O_FLAG") << "$(DESTDIR_TARGET) @<<\n\t "; + writeResponseFileFiles(t, project->values("OBJECTS")); + t << "<<"; } else { const bool embedManifest = ((templateName == "app" && project->isActiveConfig("embed_manifest_exe")) || (templateName == "lib" && project->isActiveConfig("embed_manifest_dll") @@ -675,11 +652,36 @@ void NmakeMakefileGenerator::writeLinkCommand(QTextStream &t, const QString &ext t << "$(LINKER) $(LFLAGS)"; if (!extraFlags.isEmpty()) t << ' ' << extraFlags; - t << " " << var("QMAKE_LINK_O_FLAG") << "$(DESTDIR_TARGET) @<<\n" - << "$(OBJECTS) $(LIBS)"; + t << " " << var("QMAKE_LINK_O_FLAG") << "$(DESTDIR_TARGET) @<<\n"; + writeResponseFileFiles(t, project->values("OBJECTS")); + t << "$(LIBS)\n"; if (!extraInlineFileContent.isEmpty()) - t << ' ' << extraInlineFileContent; - t << "\n<<"; + t << extraInlineFileContent << '\n'; + t << "<<"; +} + +void NmakeMakefileGenerator::writeResponseFileFiles(QTextStream &t, const ProStringList &files) +{ + // Add line breaks in file lists in reponse files to work around LNK1170. + // The actual line length limit is 131070, but let's use a smaller limit + // in case other tools are similarly hampered. + const int maxLineLength = 1000; + int len = 0; + for (const ProString &file : files) { + const ProString escapedFilePath = escapeFilePath(file); + if (len) { + if (len + escapedFilePath.length() > maxLineLength) { + t << '\n'; + len = 0; + } else { + t << ' '; + len++; + } + } + t << escapedFilePath; + len += escapedFilePath.length(); + } + t << '\n'; } int NmakeMakefileGenerator::msvcVersion() const diff --git a/qmake/generators/win32/msvc_nmake.h b/qmake/generators/win32/msvc_nmake.h index 9c88934e36..f782f9d734 100644 --- a/qmake/generators/win32/msvc_nmake.h +++ b/qmake/generators/win32/msvc_nmake.h @@ -40,6 +40,7 @@ class NmakeMakefileGenerator : public Win32MakefileGenerator void writeImplicitRulesPart(QTextStream &t); void writeBuildRulesPart(QTextStream &t); void writeLinkCommand(QTextStream &t, const QString &extraFlags = QString(), const QString &extraInlineFileContent = QString()); + void writeResponseFileFiles(QTextStream &t, const ProStringList &files); int msvcVersion() const; void init(); static QStringList sourceFilesForImplicitRulesFilter(); diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index ac57a3379c..60734b4d1b 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -33,13 +33,43 @@ #include <ioutils.h> #include <qscopedpointer.h> -#include <qstringlist.h> #include <qfileinfo.h> using namespace QMakeInternal; QT_BEGIN_NAMESPACE +static DotNET vsVersionFromString(const char *versionString) +{ + struct VSVersionMapping + { + const char *str; + DotNET version; + }; + static VSVersionMapping mapping[] = { + "7.0", NET2002, + "7.1", NET2003, + "8.0", NET2005, + "9.0", NET2008, + "10.0", NET2010, + "11.0", NET2012, + "12.0", NET2013, + "14.0", NET2015, + "15.0", NET2017 + }; + DotNET result = NETUnknown; + for (const auto entry : mapping) { + if (strcmp(entry.str, versionString) == 0) + return entry.version; + } + return result; +} + +DotNET vsVersionFromString(const ProString &versionString) +{ + return vsVersionFromString(versionString.toLatin1().constData()); +} + // XML Tags --------------------------------------------------------- const char _Configuration[] = "Configuration"; const char _Configurations[] = "Configurations"; @@ -2136,7 +2166,6 @@ VCPreLinkEventTool::VCPreLinkEventTool() VCConfiguration::VCConfiguration() : WinRT(false), - WinPhone(false), ATLMinimizesCRunTimeLibraryUsage(unset), BuildBrowserInformation(unset), CharacterSet(charSetNotSet), diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h index f9734e8e1b..10d44970ff 100644 --- a/qmake/generators/win32/msvc_objectmodel.h +++ b/qmake/generators/win32/msvc_objectmodel.h @@ -34,7 +34,6 @@ #include <proitems.h> -#include <qatomic.h> #include <qlist.h> #include <qstring.h> #include <qstringlist.h> @@ -56,6 +55,8 @@ enum DotNET { NET2017 = 0xe0 }; +DotNET vsVersionFromString(const ProString &versionString); + /* This Object model is of course VERY simplyfied, and does not actually follow the original MSVC @@ -869,7 +870,7 @@ public: bool suppressUnknownOptionWarnings; DotNET CompilerVersion; - bool WinRT, WinPhone; + bool WinRT; // Variables triState ATLMinimizesCRunTimeLibraryUsage; diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index a7312d0124..48b8bea812 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -35,7 +35,6 @@ #include <qdir.h> #include <qdiriterator.h> #include <qcryptographichash.h> -#include <qregexp.h> #include <qhash.h> #include <quuid.h> @@ -57,98 +56,6 @@ const char _GUIDFormFiles[] = "{99349809-55BA-4b9d-BF79-8FDBB0286EB3} const char _GUIDExtraCompilerFiles[] = "{E0D8C965-CC5F-43d7-AD63-FAEF0BBC0F85}"; const char _GUIDDeploymentFiles[] = "{D9D6E243-F8AF-46E4-B9FD-80ECBC20BA3E}"; const char _GUIDDistributionFiles[] = "{B83CAF91-C7BF-462F-B76C-EA11631F866C}"; -QT_END_NAMESPACE - -#ifdef Q_OS_WIN32 -#include <qt_windows.h> -#include <registry_p.h> - -QT_BEGIN_NAMESPACE - -struct DotNetCombo { - DotNET version; - const char *versionStr; - const char *regKey; -} dotNetCombo[] = { - {NET2017, "MSVC.NET 2017 (15.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VS7\\15.0"}, - {NET2015, "MSVC.NET 2015 (14.0)", "Software\\Microsoft\\VisualStudio\\14.0\\Setup\\VC\\ProductDir"}, - {NET2013, "MSVC.NET 2013 (12.0)", "Software\\Microsoft\\VisualStudio\\12.0\\Setup\\VC\\ProductDir"}, - {NET2013, "MSVC.NET 2013 Express Edition (12.0)", "Software\\Microsoft\\VCExpress\\12.0\\Setup\\VC\\ProductDir"}, - {NET2012, "MSVC.NET 2012 (11.0)", "Software\\Microsoft\\VisualStudio\\11.0\\Setup\\VC\\ProductDir"}, - {NET2012, "MSVC.NET 2012 Express Edition (11.0)", "Software\\Microsoft\\VCExpress\\11.0\\Setup\\VC\\ProductDir"}, - {NET2010, "MSVC.NET 2010 (10.0)", "Software\\Microsoft\\VisualStudio\\10.0\\Setup\\VC\\ProductDir"}, - {NET2010, "MSVC.NET 2010 Express Edition (10.0)", "Software\\Microsoft\\VCExpress\\10.0\\Setup\\VC\\ProductDir"}, - {NET2008, "MSVC.NET 2008 (9.0)", "Software\\Microsoft\\VisualStudio\\9.0\\Setup\\VC\\ProductDir"}, - {NET2008, "MSVC.NET 2008 Express Edition (9.0)", "Software\\Microsoft\\VCExpress\\9.0\\Setup\\VC\\ProductDir"}, - {NET2005, "MSVC.NET 2005 (8.0)", "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"}, - {NET2005, "MSVC.NET 2005 Express Edition (8.0)", "Software\\Microsoft\\VCExpress\\8.0\\Setup\\VC\\ProductDir"}, - {NET2003, "MSVC.NET 2003 (7.1)", "Software\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir"}, - {NET2002, "MSVC.NET 2002 (7.0)", "Software\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"}, - {NETUnknown, "", ""}, -}; - -QT_END_NAMESPACE -#endif - -QT_BEGIN_NAMESPACE -DotNET which_dotnet_version(const QByteArray &preferredVersion = QByteArray()) -{ -#ifndef Q_OS_WIN32 - Q_UNUSED(preferredVersion); - return NET2002; // Always generate 7.0 versions on other platforms -#else - // Only search for the version once - static DotNET current_version = NETUnknown; - if(current_version != NETUnknown) - return current_version; - - // Fallback to .NET 2002 - current_version = NET2002; - - const DotNetCombo *lowestInstalledVersion = 0; - QHash<DotNET, QString> installPaths; - int installed = 0; - int i = 0; - for(; dotNetCombo[i].version; ++i) { - QString path = qt_readRegistryKey(HKEY_LOCAL_MACHINE, dotNetCombo[i].regKey, - KEY_WOW64_32KEY); - if (!path.isEmpty() && installPaths.value(dotNetCombo[i].version) != path) { - lowestInstalledVersion = &dotNetCombo[i]; - installPaths.insert(lowestInstalledVersion->version, path); - ++installed; - current_version = lowestInstalledVersion->version; - if (QByteArray(lowestInstalledVersion->versionStr).contains(preferredVersion)) { - installed = 1; - break; - } - } - } - - if (installed < 2) - return current_version; - - // More than one version installed, search directory path - QString paths = qgetenv("PATH"); - const QStringList pathlist = paths.split(QLatin1Char(';')); - for (const QString &path : pathlist) { - for (i = 0; dotNetCombo[i].version; ++i) { - const QString productPath = installPaths.value(dotNetCombo[i].version); - if (productPath.isEmpty()) - continue; - if (path.startsWith(productPath, Qt::CaseInsensitive)) { - current_version = dotNetCombo[i].version; - return current_version; - } - } - } - - warn_msg(WarnLogic, "Generator: MSVC.NET: Found more than one version of Visual Studio, but" - " none in your PATH. Falling back to lowest version (%s)", - qPrintable(lowestInstalledVersion->versionStr)); - - return current_version; -#endif -}; // Flatfile Tags ---------------------------------------------------- const char _slnHeader70[] = "Microsoft Visual Studio Solution File, Format Version 7.00"; @@ -384,20 +291,16 @@ QString VcprojGenerator::retrievePlatformToolSet() const if (!envVar.isEmpty()) return envVar; - QString suffix; - if (project->isActiveConfig("winphone")) - suffix = '_' + project->first("WINTARGET_VER").toQString().toLower(); - switch (vcProject.Configuration.CompilerVersion) { case NET2012: - return QStringLiteral("v110") + suffix; + return QStringLiteral("v110"); case NET2013: - return QStringLiteral("v120") + suffix; + return QStringLiteral("v120"); case NET2015: - return QStringLiteral("v140") + suffix; + return QStringLiteral("v140"); case NET2017: - return QStringLiteral("v141") + suffix; + return QStringLiteral("v141"); default: return QString(); } @@ -624,7 +527,7 @@ void VcprojGenerator::writeSubDirs(QTextStream &t) return; } - switch (which_dotnet_version(project->first("MSVC_VER").toLatin1())) { + switch (vcProject.Configuration.CompilerVersion) { case NET2017: t << _slnHeader141; break; @@ -654,7 +557,8 @@ void VcprojGenerator::writeSubDirs(QTextStream &t) break; default: t << _slnHeader70; - warn_msg(WarnLogic, "Generator: MSVC.NET: Unknown version (%d) of MSVC detected for .sln", which_dotnet_version()); + warn_msg(WarnLogic, "Generator: MSVC.NET: Unknown version (%d) of MSVC detected for .sln", + vcProject.Configuration.CompilerVersion); break; } @@ -969,7 +873,7 @@ void VcprojGenerator::initProject() // Own elements ----------------------------- vcProject.Name = project->first("QMAKE_ORIG_TARGET").toQString(); - switch (which_dotnet_version(project->first("MSVC_VER").toLatin1())) { + switch (vcProject.Configuration.CompilerVersion) { case NET2017: vcProject.Version = "15.00"; break; @@ -1001,7 +905,7 @@ void VcprojGenerator::initProject() break; default: vcProject.Version = "7.00"; - warn_msg(WarnLogic, "Generator: MSVC.NET: Unknown version (%d) of MSVC detected for .vcproj", which_dotnet_version()); + warn_msg(WarnLogic, "Generator: MSVC.NET: Unknown version (%d) of MSVC detected for .vcproj", vcProject.Configuration.CompilerVersion); break; } @@ -1025,12 +929,11 @@ void VcprojGenerator::initConfiguration() // - to know of certain compiler/linker options VCConfiguration &conf = vcProject.Configuration; conf.suppressUnknownOptionWarnings = project->isActiveConfig("suppress_vcproj_warnings"); - conf.CompilerVersion = which_dotnet_version(project->first("MSVC_VER").toLatin1()); + conf.CompilerVersion = vsVersionFromString(project->first("MSVC_VER")); if (conf.CompilerVersion >= NET2012) { conf.WinRT = project->isActiveConfig("winrt"); if (conf.WinRT) { - conf.WinPhone = project->isActiveConfig("winphone"); // Saner defaults conf.compiler.UsePrecompiledHeader = pchNone; conf.compiler.CompileAsWinRT = _False; @@ -1431,18 +1334,9 @@ void VcprojGenerator::initWinDeployQtTool() // structure (for instance for plugins). However, the MDILXapCompile call // itself contains the original subdirectories as parameters and hence the // call fails. - // Neither there is a way to disable this behavior for Windows Phone, nor - // to influence the parameters. Hence the only way to get a build - // done is to recreate the directory structure manually by invoking - // windeployqt a second time, so that the MDILXapCompile call succeeds and - // deployment continues. - if (conf.WinPhone) { - conf.windeployqt.CommandLine = commandLine - + QStringLiteral(" -list relative -dir \"$(MSBuildProjectDirectory)\\") - + var("OBJECTS_DIR") - + QStringLiteral("MSIL\" \"$(OutDir)\\$(TargetName).exe\" ") - + QLatin1String(" && "); - } + // Hence the only way to get a build done is to recreate the directory + // structure manually by invoking windeployqt a second time, so that + // the MDILXapCompile call succeeds and deployment continues. conf.windeployqt.CommandLine += commandLine + QStringLiteral(" -list relative -dir \"$(MSBuildProjectDirectory)\" \"$(OutDir)\\$(TargetName).exe\" > ") + MakefileGenerator::shellQuote(conf.windeployqt.Record); |